From a05ff65dd2e5740f524e94ab642f26a4bdaa4781 Mon Sep 17 00:00:00 2001
From: thomascube <thomas@roundcube.net>
Date: Sat, 27 Nov 2010 09:10:11 -0500
Subject: [PATCH] Remove plugins under development

---
 /dev/null |  109 ------------------------------------------------------
 1 files changed, 0 insertions(+), 109 deletions(-)

diff --git a/plugins/enigma/README b/plugins/enigma/README
deleted file mode 100644
index afb2322..0000000
--- a/plugins/enigma/README
+++ /dev/null
@@ -1,35 +0,0 @@
-------------------------------------------------------------------
-THIS IS NOT EVEN AN "ALPHA" STATE. USE ONLY FOR DEVELOPMENT!!!!!!!
-------------------------------------------------------------------
-
-WARNING: Don't use with gnupg-2.x!
-
-Enigma Plugin Status:
-
-* DONE:
-
-- PGP signed messages verification
-- Handling of PGP keys files attached to incoming messages
-- PGP encrypted messages decryption (started)
-- PGP keys management UI (started)
-
-* TODO (must have):
-
-- Parsing of decrypted messages into array (see rcube_mime_struct) and then into rcube_message_part structure
-  (create core class rcube_mime_parser or take over PEAR::Mail_mimeDecode package and improve it)
-- Sending encrypted/signed messages (probably some changes in core will be needed)
-- Per-Identity settings (including keys/certs) (+ split Identities details page into tabs)
-- Handling big messages with temp files (including changes in Roundcube core)
-- Performance improvements (some caching, code review)
-- better (and more) icons
-
-* TODO (later):
-
-- Keys generation
-- Certs generation
-- Keys/Certs info in Contacts details page (+ split Contact details page into tabs)
-- Key server support
-- S/MIME signed messages verification
-- S/MIME encrypted messages decryption
-- Handling of S/MIME certs files attached to incoming messages
-- SSL (S/MIME) Certs management
diff --git a/plugins/enigma/config.inc.php b/plugins/enigma/config.inc.php
deleted file mode 100644
index ca841d0..0000000
--- a/plugins/enigma/config.inc.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-// Enigma Plugin options
-// --------------------
-
-// A driver to use for PGP. Default: "gnupg".
-$rcmail_config['enigma_pgp_driver'] = 'gnupg';
-
-// A driver to use for S/MIME. Default: "phpssl".
-$rcmail_config['enigma_smime_driver'] = 'phpssl';
-
-// Keys directory for all users. Default 'enigma/home'.
-// Must be writeable by PHP process
-$rcmail_config['enigma_pgp_homedir'] = null;
diff --git a/plugins/enigma/enigma.js b/plugins/enigma/enigma.js
deleted file mode 100644
index 29c6482..0000000
--- a/plugins/enigma/enigma.js
+++ /dev/null
@@ -1,206 +0,0 @@
-/* Enigma Plugin */
-
-if (window.rcmail)
-{
-    rcmail.addEventListener('init', function(evt)
-    {
-        if (rcmail.env.task == 'settings') {
-            rcmail.register_command('plugin.enigma', function() { rcmail.goto_url('plugin.enigma') }, true);
-            rcmail.register_command('plugin.enigma-key-import', function() { rcmail.enigma_key_import() }, true);
-            rcmail.register_command('plugin.enigma-key-export', function() { rcmail.enigma_key_export() }, true);
-
-            if (rcmail.gui_objects.keyslist)
-            {
-                var p = rcmail;
-                rcmail.keys_list = new rcube_list_widget(rcmail.gui_objects.keyslist,
-                    {multiselect:false, draggable:false, keyboard:false});
-                rcmail.keys_list.addEventListener('select', function(o){ p.enigma_key_select(o); });
-                rcmail.keys_list.init();
-                rcmail.keys_list.focus();
-
-                rcmail.enigma_list();
-
-                rcmail.register_command('firstpage', function(props) {return rcmail.enigma_list_page('first'); });
-                rcmail.register_command('previouspage', function(props) {return rcmail.enigma_list_page('previous'); });
-                rcmail.register_command('nextpage', function(props) {return rcmail.enigma_list_page('next'); });
-                rcmail.register_command('lastpage', function(props) {return rcmail.enigma_list_page('last'); });
-            }
-
-            if (rcmail.env.action == 'edit-prefs') {
-                rcmail.register_command('search', function(props) {return rcmail.enigma_search(props); }, true);
-                rcmail.register_command('reset-search', function(props) {return rcmail.enigma_search_reset(props); }, true);
-            }
-            else if (rcmail.env.action == 'plugin.enigma') {
-                rcmail.register_command('plugin.enigma-import', function() { rcmail.enigma_import() }, true);
-                rcmail.register_command('plugin.enigma-export', function() { rcmail.enigma_export() }, true);
-            }
-        }
-    });
-}
-
-/*********************************************************/
-/*********    Enigma Settings/Keys/Certs UI      *********/
-/*********************************************************/
-
-// Display key(s) import form
-rcube_webmail.prototype.enigma_key_import = function()
-{
-    this.enigma_loadframe(null, '&_a=keyimport');
-};
-
-// Submit key(s) form
-rcube_webmail.prototype.enigma_import = function()
-{
-    var form, file;
-    if (form = this.gui_objects.importform) {
-        file = document.getElementById('rcmimportfile');
-        if (file && !file.value) {
-            alert(this.get_label('selectimportfile'));
-            return;
-        }
-        form.submit();
-        this.set_busy(true, 'importwait');
-        this.lock_form(form, true);
-   }
-};
-
-// list row selection handler
-rcube_webmail.prototype.enigma_key_select = function(list)
-{
-    var id;
-    if (id = list.get_single_selection())
-        this.enigma_loadframe(id);
-};
-
-// load key frame
-rcube_webmail.prototype.enigma_loadframe = function(id, url)
-{
-    var frm, win;
-    if (this.env.contentframe && window.frames && (frm = window.frames[this.env.contentframe])) {
-        if (!id && !url && (win = window.frames[this.env.contentframe])) {
-            if (win.location && win.location.href.indexOf(this.env.blankpage)<0)
-                win.location.href = this.env.blankpage;
-            return;
-        }
-        this.set_busy(true);
-        if (!url)
-            url = '&_a=keyinfo&_id='+id;
-        frm.location.href = this.env.comm_path+'&_action=plugin.enigma&_framed=1' + url;
-    }
-};
-
-// Search keys/certs
-rcube_webmail.prototype.enigma_search = function(props)
-{
-    if (!props && this.gui_objects.qsearchbox)
-        props = this.gui_objects.qsearchbox.value;
-
-    if (props || this.env.search_request) {
-        var params = {'_a': 'keysearch', '_q': urlencode(props)},
-          lock = this.set_busy(true, 'searching');
-//        if (this.gui_objects.search_filter)
-  //          addurl += '&_filter=' + this.gui_objects.search_filter.value;
-        this.env.current_page = 1;  
-        this.enigma_loadframe();
-        this.enigma_clear_list();
-        this.http_post('plugin.enigma', params, lock);
-    }
-
-    return false;
-}
-
-// Reset search filter and the list
-rcube_webmail.prototype.enigma_search_reset = function(props)
-{
-    var s = this.env.search_request;
-    this.reset_qsearch();
-
-    if (s) {
-        this.enigma_loadframe();
-        this.enigma_clear_list();
-
-        // refresh the list
-        this.enigma_list();
-    }
-
-    return false;
-}
-
-// Keys/certs listing
-rcube_webmail.prototype.enigma_list = function(page)
-{
-    var params = {'_a': 'keylist'},
-      lock = this.set_busy(true, 'loading');
-
-    this.env.current_page = page ? page : 1;
-
-    if (this.env.search_request)
-        params._q = this.env.search_request;
-    if (page)
-        params._p = page;
-
-    this.enigma_clear_list();
-    this.http_post('plugin.enigma', params, lock);
-}
-
-// Change list page
-rcube_webmail.prototype.enigma_list_page = function(page)
-{
-    if (page == 'next')
-        page = this.env.current_page + 1;
-    else if (page == 'last')
-        page = this.env.pagecount;
-    else if (page == 'prev' && this.env.current_page > 1)
-        page = this.env.current_page - 1;
-    else if (page == 'first' && this.env.current_page > 1)
-        page = 1;
-
-    this.enigma_list(page);
-}
-
-// Remove list rows
-rcube_webmail.prototype.enigma_clear_list = function()
-{
-    this.enigma_loadframe();
-    if (this.keys_list)
-        this.keys_list.clear(true);
-}
-
-// Adds a row to the list
-rcube_webmail.prototype.enigma_add_list_row = function(r)
-{
-    if (!this.gui_objects.keyslist || !this.keys_list)
-        return false;
-
-    var list = this.keys_list,
-        tbody = this.gui_objects.keyslist.tBodies[0],
-        rowcount = tbody.rows.length,
-        even = rowcount%2,
-        css_class = 'message'
-            + (even ? ' even' : ' odd'),
-        // for performance use DOM instead of jQuery here
-        row = document.createElement('tr'),
-        col = document.createElement('td');
-
-    row.id = 'rcmrow' + r.id;
-    row.className = css_class;
-
-    col.innerHTML = r.name;
-    row.appendChild(col);
-    list.insert_row(row);
-}
-
-/*********************************************************/
-/*********        Enigma Message methods         *********/
-/*********************************************************/
-
-// Import attached keys/certs file
-rcube_webmail.prototype.enigma_import_attachment = function(mime_id)
-{
-    var lock = this.set_busy(true, 'loading');
-    this.http_post('plugin.enigmaimport', '_uid='+this.env.uid+'&_mbox='
-        +urlencode(this.env.mailbox)+'&_part='+urlencode(mime_id), lock);
-
-    return false;
-};
-
diff --git a/plugins/enigma/enigma.php b/plugins/enigma/enigma.php
deleted file mode 100644
index fb7c986..0000000
--- a/plugins/enigma/enigma.php
+++ /dev/null
@@ -1,475 +0,0 @@
-<?php
-/*
- +-------------------------------------------------------------------------+
- | Enigma Plugin for Roundcube                                             |
- | Version 0.1                                                             |
- |                                                                         |
- | This program is free software; you can redistribute it and/or modify    |
- | it under the terms of the GNU General Public License version 2          |
- | as published by the Free Software Foundation.                           |
- |                                                                         |
- | 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.             |
- |                                                                         |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                              |
- +-------------------------------------------------------------------------+
-*/
-
-/*
-    This class contains only hooks and action handlers.
-    Most plugin logic is placed in enigma_engine and enigma_ui classes.
-*/
-
-class enigma extends rcube_plugin
-{
-    public $task = 'mail|settings';
-    public $rc;
-    public $engine;
-
-    private $env_loaded;
-    private $message;
-    private $keys_parts = array();
-    private $keys_bodies = array();
-
-
-    /**
-     * Plugin initialization.
-     */
-    function init()
-    {
-        $rcmail = rcmail::get_instance();
-        $this->rc = $rcmail;
-
-        if ($this->rc->task == 'mail') {
-            // message parse/display hooks
-            $this->add_hook('message_part_structure', array($this, 'parse_structure'));
-            $this->add_hook('message_body_prefix', array($this, 'status_message'));
-
-            // message displaying
-            if ($rcmail->action == 'show' || $rcmail->action == 'preview') {
-                $this->add_hook('message_load', array($this, 'message_load'));
-                $this->add_hook('template_object_messagebody', array($this, 'message_output'));
-                $this->register_action('plugin.enigmaimport', array($this, 'import_file'));
-            }
-            // message composing
-            else if ($rcmail->action == 'compose') {
-                $this->load_ui();
-                $this->ui->init($section);
-            }
-            // message sending (and draft storing)
-            else if ($rcmail->action == 'sendmail') {
-                //$this->add_hook('outgoing_message_body', array($this, 'msg_encode'));
-                //$this->add_hook('outgoing_message_body', array($this, 'msg_sign'));
-            }
-        }
-        else if ($this->rc->task == 'settings') {
-            // add hooks for Enigma settings
-            $this->add_hook('preferences_sections_list', array($this, 'preferences_section'));
-            $this->add_hook('preferences_list', array($this, 'preferences_list'));
-            $this->add_hook('preferences_save', array($this, 'preferences_save'));
-
-            // register handler for keys/certs management
-            $this->register_action('plugin.enigma', array($this, 'preferences_ui'));
-
-            // grab keys/certs management iframe requests
-            $section = get_input_value('_section', RCUBE_INPUT_GET);
-            if ($this->rc->action == 'edit-prefs' && preg_match('/^enigma(certs|keys)/', $section)) {
-                $this->load_ui();
-                $this->ui->init($section);
-            }
-        }
-    }
-
-    /**
-     * Plugin environment initialization.
-     */
-    function load_env()
-    {
-        if ($this->env_loaded)
-            return;
-
-        $this->env_loaded = true;
-
-        // Add include path for Enigma classes and drivers
-        $include_path = $this->home . '/lib' . PATH_SEPARATOR;
-        $include_path .= ini_get('include_path');
-        set_include_path($include_path);
-
-        // load the Enigma plugin configuration
-        $this->load_config();
-
-        // include localization (if wasn't included before)
-        $this->add_texts('localization/');
-    }
-
-    /**
-     * Plugin UI initialization.
-     */
-    function load_ui()
-    {
-        if ($this->ui)
-            return;
-
-        // load config/localization
-        $this->load_env();
-
-        // Load UI
-        $this->ui = new enigma_ui($this, $this->home);
-    }
-
-    /**
-     * Plugin engine initialization.
-     */
-    function load_engine()
-    {
-        if ($this->engine)
-            return;
-
-        // load config/localization
-        $this->load_env();
-
-        $this->engine = new enigma_engine($this);
-    }
-
-    /**
-     * Handler for message_part_structure hook.
-     * Called for every part of the message.
-     *
-     * @param array Original parameters
-     *
-     * @return array Modified parameters
-     */
-    function parse_structure($p)
-    {
-        $struct = $p['structure'];
-
-        if ($p['mimetype'] == 'text/plain' || $p['mimetype'] == 'application/pgp') {
-            $this->parse_plain($p);
-        }
-        else if ($p['mimetype'] == 'multipart/signed') {
-            $this->parse_signed($p);
-        }
-        else if ($p['mimetype'] == 'multipart/encrypted') {
-            $this->parse_encrypted($p);
-        }
-        else if ($p['mimetype'] == 'application/pkcs7-mime') {
-            $this->parse_encrypted($p);
-        }
-
-        return $p;
-    }
-
-    /**
-     * Handler for preferences_sections_list hook.
-     * Adds Enigma settings sections into preferences sections list.
-     *
-     * @param array Original parameters
-     *
-     * @return array Modified parameters
-     */
-    function preferences_section($p)
-    {
-        // add labels
-        $this->add_texts('localization/');
-
-        $p['list']['enigmasettings'] = array(
-            'id' => 'enigmasettings', 'section' => $this->gettext('enigmasettings'),
-        );
-        $p['list']['enigmacerts'] = array(
-            'id' => 'enigmacerts', 'section' => $this->gettext('enigmacerts'),
-        );
-        $p['list']['enigmakeys'] = array(
-            'id' => 'enigmakeys', 'section' => $this->gettext('enigmakeys'),
-        );
-
-        return $p;
-    }
-
-    /**
-     * Handler for preferences_list hook.
-     * Adds options blocks into Enigma settings sections in Preferences.
-     *
-     * @param array Original parameters
-     *
-     * @return array Modified parameters
-     */
-    function preferences_list($p)
-    {
-        if ($p['section'] == 'enigmasettings') {
-            // This makes that section is not removed from the list
-            $p['blocks']['dummy']['options']['dummy'] = array();
-        }
-        else if ($p['section'] == 'enigmacerts') {
-            // This makes that section is not removed from the list
-            $p['blocks']['dummy']['options']['dummy'] = array();
-        }
-        else if ($p['section'] == 'enigmakeys') {
-            // This makes that section is not removed from the list
-            $p['blocks']['dummy']['options']['dummy'] = array();
-        }
-
-        return $p;
-    }
-
-    /**
-     * Handler for preferences_save hook.
-     * Executed on Enigma settings form submit.
-     *
-     * @param array Original parameters
-     *
-     * @return array Modified parameters
-     */
-    function preferences_save($p)
-    {
-        if ($p['section'] == 'enigmasettings') {
-            $a['prefs'] = array(
-//                'dummy' => get_input_value('_dummy', RCUBE_INPUT_POST),
-            );
-        }
-
-        return $p;
-    }
-
-    /**
-     * Handler for keys/certs management UI template.
-     */
-    function preferences_ui()
-    {
-        $this->load_ui();
-        $this->ui->init();
-    }
-
-    /**
-     * Handler for message_body_prefix hook.
-     * Called for every displayed (content) part of the message.
-     * Adds infobox about signature verification and/or decryption
-     * status above the body.
-     *
-     * @param array Original parameters
-     *
-     * @return array Modified parameters
-     */
-    function status_message($p)
-    {
-        $part_id = $p['part']->mime_id;
-
-        // skip: not a message part
-        if ($p['part'] instanceof rcube_message)
-            return $p;
-
-        // skip: message has no signed/encoded content
-        if (!$this->engine)
-            return $p;
-
-        // Decryption status
-        if (isset($this->engine->decryptions[$part_id])) {
-
-            // get decryption status
-            $status = $this->engine->decryptions[$part_id];
-
-            // Load UI and add css script
-            $this->load_ui();
-            $this->ui->add_css();
-
-            // display status info
-            $attrib['id'] = 'enigma-message';
-
-            if ($status instanceof enigma_error) {
-                $attrib['class'] = 'enigmaerror';
-                $code = $status->getCode();
-                if ($code == enigma_error::E_KEYNOTFOUND)
-                    $msg = Q(str_replace('$keyid', enigma_key::format_id($status->getData('id')),
-                        $this->gettext('decryptnokey')));
-                else if ($code == enigma_error::E_BADPASS)
-                    $msg = Q($this->gettext('decryptbadpass'));
-                else
-                    $msg = Q($this->gettext('decrypterror'));
-            }
-            else {
-                $attrib['class'] = 'enigmanotice';
-                $msg = Q($this->gettext('decryptok'));
-            }
-
-            $p['prefix'] .= html::div($attrib, $msg);
-        }
-
-        // Signature verification status
-        if (isset($this->engine->signed_parts[$part_id])
-            && ($sig = $this->engine->signatures[$this->engine->signed_parts[$part_id]])
-        ) {
-            // add css script
-            $this->load_ui();
-            $this->ui->add_css();
-
-            // display status info
-            $attrib['id'] = 'enigma-message';
-
-            if ($sig instanceof enigma_signature) {
-                if ($sig->valid) {
-                    $attrib['class'] = 'enigmanotice';
-                    $sender = ($sig->name ? $sig->name . ' ' : '') . '<' . $sig->email . '>';
-                    $msg = Q(str_replace('$sender', $sender, $this->gettext('sigvalid')));
-                }
-                else {
-                    $attrib['class'] = 'enigmawarning';
-                    $sender = ($sig->name ? $sig->name . ' ' : '') . '<' . $sig->email . '>';
-                    $msg = Q(str_replace('$sender', $sender, $this->gettext('siginvalid')));
-                }
-            }
-            else if ($sig->getCode() == enigma_error::E_KEYNOTFOUND) {
-                $attrib['class'] = 'enigmawarning';
-                $msg = Q(str_replace('$keyid', enigma_key::format_id($sig->getData('id')),
-                    $this->gettext('signokey')));
-            }
-            else {
-                $attrib['class'] = 'enigmaerror';
-                $msg = Q($this->gettext('sigerror'));
-            }
-/*
-            $msg .= '&nbsp;' . html::a(array('href' => "#sigdetails",
-                'onclick' => JS_OBJECT_NAME.".command('enigma-sig-details')"),
-                Q($this->gettext('showdetails')));
-*/
-            // test
-//            $msg .= '<br /><pre>'.$sig->body.'</pre>';
-
-            $p['prefix'] .= html::div($attrib, $msg);
-
-            // Display each signature message only once
-            unset($this->engine->signatures[$this->engine->signed_parts[$part_id]]);
-        }
-
-        return $p;
-    }
-
-    /**
-     * Handler for plain/text message.
-     *
-     * @param array Reference to hook's parameters (see enigma::parse_structure())
-     */
-    private function parse_plain(&$p)
-    {
-        $this->load_engine();
-        $this->engine->parse_plain($p);
-    }
-    
-    /**
-     * Handler for multipart/signed message.
-     * Verifies signature.
-     *
-     * @param array Reference to hook's parameters (see enigma::parse_structure())
-     */
-    private function parse_signed(&$p)
-    {
-        $this->load_engine();
-        $this->engine->parse_signed($p);
-    }
-
-    /**
-     * Handler for multipart/encrypted and application/pkcs7-mime message.
-     *
-     * @param array Reference to hook's parameters (see enigma::parse_structure())
-     */
-    private function parse_encrypted(&$p)
-    {
-        $this->load_engine();
-        $this->engine->parse_encrypted($p);
-    }
-    
-    /**
-     * Handler for message_load hook.
-     * Check message bodies and attachments for keys/certs.
-     */
-    function message_load($p)
-    {
-        $this->message = $p['object'];
-    
-        // handle attachments vcard attachments
-        foreach ((array)$this->message->attachments as $attachment) {
-            if ($this->is_keys_part($attachment)) {
-                $this->keys_parts[] = $attachment->mime_id;
-            }
-        }
-        // the same with message bodies
-        foreach ((array)$this->message->parts as $idx => $part) {
-            if ($this->is_keys_part($part)) {
-                $this->keys_parts[] = $part->mime_id;
-                $this->keys_bodies[] = $part->mime_id;
-            }
-        }
-        // @TODO: inline PGP keys
-
-        if ($this->keys_parts) {
-            $this->add_texts('localization');
-        }
-    }
-
-    /**
-     * Handler for template_object_messagebody hook.
-     * This callback function adds a box below the message content
-     * if there is a key/cert attachment available
-     */
-    function message_output($p)
-    {
-        $attach_script = false;
-
-        foreach ($this->keys_parts as $part) {
-
-            // remove part's body
-            if (in_array($part, $this->keys_bodies))
-                $p['content'] = '';
-
-            $style = "margin:0 1em; padding:0.2em 0.5em; border:1px solid #999; width: auto"
-                ." border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px";
-
-            // add box below messsage body
-            $p['content'] .= html::p(array('style' => $style),
-                html::a(array(
-                    'href' => "#",
-                    'onclick' => "return ".JS_OBJECT_NAME.".enigma_import_attachment('".JQ($part)."')",
-                    'title' => $this->gettext('keyattimport')),
-                    html::img(array('src' => $this->url('skins/default/key_add.png'), 'style' => "vertical-align:middle")))
-                . ' ' . html::span(null, $this->gettext('keyattfound')));
-
-            $attach_script = true;
-        }
-
-        if ($attach_script) {
-            $this->include_script('enigma.js');
-        }
-
-        return $p;
-    }
-
-    /**
-     * Handler for attached keys/certs import
-     */
-    function import_file()
-    {
-        $this->load_engine();
-        $this->engine->import_file();
-    }
-
-    /**
-     * Checks if specified message part is a PGP-key or S/MIME cert data
-     *
-     * @param rcube_message_part Part object
-     *
-     * @return boolean True if part is a key/cert
-     */
-    private function is_keys_part($part)
-    {
-        // @TODO: S/MIME
-        return (
-            // Content-Type: application/pgp-keys
-            $part->mimetype == 'application/pgp-keys'
-        );
-    }
-}
diff --git a/plugins/enigma/home/.htaccess b/plugins/enigma/home/.htaccess
deleted file mode 100644
index 8e6a345..0000000
--- a/plugins/enigma/home/.htaccess
+++ /dev/null
@@ -1,2 +0,0 @@
-Order allow,deny
-Deny from all 
\ No newline at end of file
diff --git a/plugins/enigma/lib/Crypt/GPG.php b/plugins/enigma/lib/Crypt/GPG.php
deleted file mode 100644
index 6e8e717..0000000
--- a/plugins/enigma/lib/Crypt/GPG.php
+++ /dev/null
@@ -1,2542 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Crypt_GPG is a package to use GPG from PHP
- *
- * This package provides an object oriented interface to GNU Privacy
- * Guard (GPG). It requires the GPG executable to be on the system.
- *
- * Though GPG can support symmetric-key cryptography, this package is intended
- * only to facilitate public-key cryptography.
- *
- * This file contains the main GPG class. The class in this file lets you
- * encrypt, decrypt, sign and verify data; import and delete keys; and perform
- * other useful GPG tasks.
- *
- * Example usage:
- * <code>
- * <?php
- * // encrypt some data
- * $gpg = new Crypt_GPG();
- * $gpg->addEncryptKey($mySecretKeyId);
- * $encryptedData = $gpg->encrypt($data);
- * ?>
- * </code>
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @version   CVS: $Id: GPG.php 302814 2010-08-26 15:43:07Z gauthierm $
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://pear.php.net/manual/en/package.encryption.crypt-gpg.php
- * @link      http://www.gnupg.org/
- */
-
-/**
- * Signature handler class
- */
-require_once 'Crypt/GPG/VerifyStatusHandler.php';
-
-/**
- * Decryption handler class
- */
-require_once 'Crypt/GPG/DecryptStatusHandler.php';
-
-/**
- * GPG key class
- */
-require_once 'Crypt/GPG/Key.php';
-
-/**
- * GPG sub-key class
- */
-require_once 'Crypt/GPG/SubKey.php';
-
-/**
- * GPG user id class
- */
-require_once 'Crypt/GPG/UserId.php';
-
-/**
- * GPG process and I/O engine class
- */
-require_once 'Crypt/GPG/Engine.php';
-
-/**
- * GPG exception classes
- */
-require_once 'Crypt/GPG/Exceptions.php';
-
-// {{{ class Crypt_GPG
-
-/**
- * A class to use GPG from PHP
- *
- * This class provides an object oriented interface to GNU Privacy Guard (GPG).
- *
- * Though GPG can support symmetric-key cryptography, this class is intended
- * only to facilitate public-key cryptography.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-class Crypt_GPG
-{
-    // {{{ class error constants
-
-    /**
-     * Error code returned when there is no error.
-     */
-    const ERROR_NONE = 0;
-
-    /**
-     * Error code returned when an unknown or unhandled error occurs.
-     */
-    const ERROR_UNKNOWN = 1;
-
-    /**
-     * Error code returned when a bad passphrase is used.
-     */
-    const ERROR_BAD_PASSPHRASE = 2;
-
-    /**
-     * Error code returned when a required passphrase is missing.
-     */
-    const ERROR_MISSING_PASSPHRASE = 3;
-
-    /**
-     * Error code returned when a key that is already in the keyring is
-     * imported.
-     */
-    const ERROR_DUPLICATE_KEY = 4;
-
-    /**
-     * Error code returned the required data is missing for an operation.
-     *
-     * This could be missing key data, missing encrypted data or missing
-     * signature data.
-     */
-    const ERROR_NO_DATA = 5;
-
-    /**
-     * Error code returned when an unsigned key is used.
-     */
-    const ERROR_UNSIGNED_KEY = 6;
-
-    /**
-     * Error code returned when a key that is not self-signed is used.
-     */
-    const ERROR_NOT_SELF_SIGNED = 7;
-
-    /**
-     * Error code returned when a public or private key that is not in the
-     * keyring is used.
-     */
-    const ERROR_KEY_NOT_FOUND = 8;
-
-    /**
-     * Error code returned when an attempt to delete public key having a
-     * private key is made.
-     */
-    const ERROR_DELETE_PRIVATE_KEY = 9;
-
-    /**
-     * Error code returned when one or more bad signatures are detected.
-     */
-    const ERROR_BAD_SIGNATURE = 10;
-
-    /**
-     * Error code returned when there is a problem reading GnuPG data files.
-     */
-    const ERROR_FILE_PERMISSIONS = 11;
-
-    // }}}
-    // {{{ class constants for data signing modes
-
-    /**
-     * Signing mode for normal signing of data. The signed message will not
-     * be readable without special software.
-     *
-     * This is the default signing mode.
-     *
-     * @see Crypt_GPG::sign()
-     * @see Crypt_GPG::signFile()
-     */
-    const SIGN_MODE_NORMAL = 1;
-
-    /**
-     * Signing mode for clearsigning data. Clearsigned signatures are ASCII
-     * armored data and are readable without special software. If the signed
-     * message is unencrypted, the message will still be readable. The message
-     * text will be in the original encoding.
-     *
-     * @see Crypt_GPG::sign()
-     * @see Crypt_GPG::signFile()
-     */
-    const SIGN_MODE_CLEAR = 2;
-
-    /**
-     * Signing mode for creating a detached signature. When using detached
-     * signatures, only the signature data is returned. The original message
-     * text may be distributed separately from the signature data. This is
-     * useful for miltipart/signed email messages as per
-     * {@link http://www.ietf.org/rfc/rfc3156.txt RFC 3156}.
-     *
-     * @see Crypt_GPG::sign()
-     * @see Crypt_GPG::signFile()
-     */
-    const SIGN_MODE_DETACHED = 3;
-
-    // }}}
-    // {{{ class constants for fingerprint formats
-
-    /**
-     * No formatting is performed.
-     *
-     * Example: C3BC615AD9C766E5A85C1F2716D27458B1BBA1C4
-     *
-     * @see Crypt_GPG::getFingerprint()
-     */
-    const FORMAT_NONE = 1;
-
-    /**
-     * Fingerprint is formatted in the format used by the GnuPG gpg command's
-     * default output.
-     *
-     * Example: C3BC 615A D9C7 66E5 A85C  1F27 16D2 7458 B1BB A1C4
-     *
-     * @see Crypt_GPG::getFingerprint()
-     */
-    const FORMAT_CANONICAL = 2;
-
-    /**
-     * Fingerprint is formatted in the format used when displaying X.509
-     * certificates
-     *
-     * Example: C3:BC:61:5A:D9:C7:66:E5:A8:5C:1F:27:16:D2:74:58:B1:BB:A1:C4
-     *
-     * @see Crypt_GPG::getFingerprint()
-     */
-    const FORMAT_X509 = 3;
-
-    // }}}
-    // {{{ other class constants
-
-    /**
-     * URI at which package bugs may be reported.
-     */
-    const BUG_URI = 'http://pear.php.net/bugs/report.php?package=Crypt_GPG';
-
-    // }}}
-    // {{{ protected class properties
-
-    /**
-     * Engine used to control the GPG subprocess
-     *
-     * @var Crypt_GPG_Engine
-     *
-     * @see Crypt_GPG::setEngine()
-     */
-    protected $engine = null;
-
-    /**
-     * Keys used to encrypt
-     *
-     * The array is of the form:
-     * <code>
-     * array(
-     *   $key_id => array(
-     *     'fingerprint' => $fingerprint,
-     *     'passphrase'  => null
-     *   )
-     * );
-     * </code>
-     *
-     * @var array
-     * @see Crypt_GPG::addEncryptKey()
-     * @see Crypt_GPG::clearEncryptKeys()
-     */
-    protected $encryptKeys = array();
-
-    /**
-     * Keys used to decrypt
-     *
-     * The array is of the form:
-     * <code>
-     * array(
-     *   $key_id => array(
-     *     'fingerprint' => $fingerprint,
-     *     'passphrase'  => $passphrase
-     *   )
-     * );
-     * </code>
-     *
-     * @var array
-     * @see Crypt_GPG::addSignKey()
-     * @see Crypt_GPG::clearSignKeys()
-     */
-    protected $signKeys = array();
-
-    /**
-     * Keys used to sign
-     *
-     * The array is of the form:
-     * <code>
-     * array(
-     *   $key_id => array(
-     *     'fingerprint' => $fingerprint,
-     *     'passphrase'  => $passphrase
-     *   )
-     * );
-     * </code>
-     *
-     * @var array
-     * @see Crypt_GPG::addDecryptKey()
-     * @see Crypt_GPG::clearDecryptKeys()
-     */
-    protected $decryptKeys = array();
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new GPG object
-     *
-     * Available options are:
-     *
-     * - <kbd>string  homedir</kbd>        - the directory where the GPG
-     *                                       keyring files are stored. If not
-     *                                       specified, Crypt_GPG uses the
-     *                                       default of <kbd>~/.gnupg</kbd>.
-     * - <kbd>string  publicKeyring</kbd>  - the file path of the public
-     *                                       keyring. Use this if the public
-     *                                       keyring is not in the homedir, or
-     *                                       if the keyring is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       keyring with this option
-     *                                       (/foo/bar/pubring.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  privateKeyring</kbd> - the file path of the private
-     *                                       keyring. Use this if the private
-     *                                       keyring is not in the homedir, or
-     *                                       if the keyring is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       keyring with this option
-     *                                       (/foo/bar/secring.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  trustDb</kbd>        - the file path of the web-of-trust
-     *                                       database. Use this if the trust
-     *                                       database is not in the homedir, or
-     *                                       if the database is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       trust database with this option
-     *                                       (/foo/bar/trustdb.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  binary</kbd>         - the location of the GPG binary. If
-     *                                       not specified, the driver attempts
-     *                                       to auto-detect the GPG binary
-     *                                       location using a list of known
-     *                                       default locations for the current
-     *                                       operating system. The option
-     *                                       <kbd>gpgBinary</kbd> is a
-     *                                       deprecated alias for this option.
-     * - <kbd>boolean debug</kbd>          - whether or not to use debug mode.
-     *                                       When debug mode is on, all
-     *                                       communication to and from the GPG
-     *                                       subprocess is logged. This can be
-     *
-     * @param array $options optional. An array of options used to create the
-     *                       GPG object. All options are optional and are
-     *                       represented as key-value pairs.
-     *
-     * @throws Crypt_GPG_FileException if the <kbd>homedir</kbd> does not exist
-     *         and cannot be created. This can happen if <kbd>homedir</kbd> is
-     *         not specified, Crypt_GPG is run as the web user, and the web
-     *         user has no home directory. This exception is also thrown if any
-     *         of the options <kbd>publicKeyring</kbd>,
-     *         <kbd>privateKeyring</kbd> or <kbd>trustDb</kbd> options are
-     *         specified but the files do not exist or are are not readable.
-     *         This can happen if the user running the Crypt_GPG process (for
-     *         example, the Apache user) does not have permission to read the
-     *         files.
-     *
-     * @throws PEAR_Exception if the provided <kbd>binary</kbd> is invalid, or
-     *         if no <kbd>binary</kbd> is provided and no suitable binary could
-     *         be found.
-     */
-    public function __construct(array $options = array())
-    {
-        $this->setEngine(new Crypt_GPG_Engine($options));
-    }
-
-    // }}}
-    // {{{ importKey()
-
-    /**
-     * Imports a public or private key into the keyring
-     *
-     * Keys may be removed from the keyring using
-     * {@link Crypt_GPG::deletePublicKey()} or
-     * {@link Crypt_GPG::deletePrivateKey()}.
-     *
-     * @param string $data the key data to be imported.
-     *
-     * @return array an associative array containing the following elements:
-     *               - <kbd>fingerprint</kbd>       - the fingerprint of the
-     *                                                imported key,
-     *               - <kbd>public_imported</kbd>   - the number of public
-     *                                                keys imported,
-     *               - <kbd>public_unchanged</kbd>  - the number of unchanged
-     *                                                public keys,
-     *               - <kbd>private_imported</kbd>  - the number of private
-     *                                                keys imported,
-     *               - <kbd>private_unchanged</kbd> - the number of unchanged
-     *                                                private keys.
-     *
-     * @throws Crypt_GPG_NoDataException if the key data is missing or if the
-     *         data is is not valid key data.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function importKey($data)
-    {
-        return $this->_importKey($data, false);
-    }
-
-    // }}}
-    // {{{ importKeyFile()
-
-    /**
-     * Imports a public or private key file into the keyring
-     *
-     * Keys may be removed from the keyring using
-     * {@link Crypt_GPG::deletePublicKey()} or
-     * {@link Crypt_GPG::deletePrivateKey()}.
-     *
-     * @param string $filename the key file to be imported.
-     *
-     * @return array an associative array containing the following elements:
-     *               - <kbd>fingerprint</kbd>       - the fingerprint of the
-     *                                                imported key,
-     *               - <kbd>public_imported</kbd>   - the number of public
-     *                                                keys imported,
-     *               - <kbd>public_unchanged</kbd>  - the number of unchanged
-     *                                                public keys,
-     *               - <kbd>private_imported</kbd>  - the number of private
-     *                                                keys imported,
-     *               - <kbd>private_unchanged</kbd> - the number of unchanged
-     *                                                private keys.
-     *                                                  private keys.
-     *
-     * @throws Crypt_GPG_NoDataException if the key data is missing or if the
-     *         data is is not valid key data.
-     *
-     * @throws Crypt_GPG_FileException if the key file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function importKeyFile($filename)
-    {
-        return $this->_importKey($filename, true);
-    }
-
-    // }}}
-    // {{{ exportPublicKey()
-
-    /**
-     * Exports a public key from the keyring
-     *
-     * The exported key remains on the keyring. To delete the public key, use
-     * {@link Crypt_GPG::deletePublicKey()}.
-     *
-     * If more than one key fingerprint is available for the specified
-     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
-     * first public key is exported.
-     *
-     * @param string  $keyId either the full uid of the public key, the email
-     *                       part of the uid of the public key or the key id of
-     *                       the public key. For example,
-     *                       "Test User (example) <test@example.com>",
-     *                       "test@example.com" or a hexadecimal string.
-     * @param boolean $armor optional. If true, ASCII armored data is returned;
-     *                       otherwise, binary data is returned. Defaults to
-     *                       true.
-     *
-     * @return string the public key data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if a public key with the given
-     *         <kbd>$keyId</kbd> is not found.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function exportPublicKey($keyId, $armor = true)
-    {
-        $fingerprint = $this->getFingerprint($keyId);
-
-        if ($fingerprint === null) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Public key not found: ' . $keyId,
-                Crypt_GPG::ERROR_KEY_NOT_FOUND, $keyId);
-        }
-
-        $keyData   = '';
-        $operation = '--export ' . escapeshellarg($fingerprint);
-        $arguments = ($armor) ? array('--armor') : array();
-
-        $this->engine->reset();
-        $this->engine->setOutput($keyData);
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        $code = $this->engine->getErrorCode();
-
-        if ($code !== Crypt_GPG::ERROR_NONE) {
-            throw new Crypt_GPG_Exception(
-                'Unknown error exporting public key. Please use the ' .
-                '\'debug\' option when creating the Crypt_GPG object, and ' .
-                'file a bug report at ' . self::BUG_URI, $code);
-        }
-
-        return $keyData;
-    }
-
-    // }}}
-    // {{{ deletePublicKey()
-
-    /**
-     * Deletes a public key from the keyring
-     *
-     * If more than one key fingerprint is available for the specified
-     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
-     * first public key is deleted.
-     *
-     * The private key must be deleted first or an exception will be thrown.
-     * See {@link Crypt_GPG::deletePrivateKey()}.
-     *
-     * @param string $keyId either the full uid of the public key, the email
-     *                      part of the uid of the public key or the key id of
-     *                      the public key. For example,
-     *                      "Test User (example) <test@example.com>",
-     *                      "test@example.com" or a hexadecimal string.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if a public key with the given
-     *         <kbd>$keyId</kbd> is not found.
-     *
-     * @throws Crypt_GPG_DeletePrivateKeyException if the specified public key
-     *         has an associated private key on the keyring. The private key
-     *         must be deleted first.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function deletePublicKey($keyId)
-    {
-        $fingerprint = $this->getFingerprint($keyId);
-
-        if ($fingerprint === null) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Public key not found: ' . $keyId,
-                Crypt_GPG::ERROR_KEY_NOT_FOUND, $keyId);
-        }
-
-        $operation = '--delete-key ' . escapeshellarg($fingerprint);
-        $arguments = array(
-            '--batch',
-            '--yes'
-        );
-
-        $this->engine->reset();
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        $code = $this->engine->getErrorCode();
-
-        switch ($code) {
-        case Crypt_GPG::ERROR_NONE:
-            break;
-        case Crypt_GPG::ERROR_DELETE_PRIVATE_KEY:
-            throw new Crypt_GPG_DeletePrivateKeyException(
-                'Private key must be deleted before public key can be ' .
-                'deleted.', $code, $keyId);
-        default:
-            throw new Crypt_GPG_Exception(
-                'Unknown error deleting public key. Please use the ' .
-                '\'debug\' option when creating the Crypt_GPG object, and ' .
-                'file a bug report at ' . self::BUG_URI, $code);
-        }
-    }
-
-    // }}}
-    // {{{ deletePrivateKey()
-
-    /**
-     * Deletes a private key from the keyring
-     *
-     * If more than one key fingerprint is available for the specified
-     * <kbd>$keyId</kbd> (for example, if you use a non-unique uid) only the
-     * first private key is deleted.
-     *
-     * Calls GPG with the <kbd>--delete-secret-key</kbd> command.
-     *
-     * @param string $keyId either the full uid of the private key, the email
-     *                      part of the uid of the private key or the key id of
-     *                      the private key. For example,
-     *                      "Test User (example) <test@example.com>",
-     *                      "test@example.com" or a hexadecimal string.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if a private key with the given
-     *         <kbd>$keyId</kbd> is not found.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function deletePrivateKey($keyId)
-    {
-        $fingerprint = $this->getFingerprint($keyId);
-
-        if ($fingerprint === null) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Private key not found: ' . $keyId,
-                Crypt_GPG::ERROR_KEY_NOT_FOUND, $keyId);
-        }
-
-        $operation = '--delete-secret-key ' . escapeshellarg($fingerprint);
-        $arguments = array(
-            '--batch',
-            '--yes'
-        );
-
-        $this->engine->reset();
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        $code = $this->engine->getErrorCode();
-
-        switch ($code) {
-        case Crypt_GPG::ERROR_NONE:
-            break;
-        case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Private key not found: ' . $keyId,
-                $code, $keyId);
-        default:
-            throw new Crypt_GPG_Exception(
-                'Unknown error deleting private key. Please use the ' .
-                '\'debug\' option when creating the Crypt_GPG object, and ' .
-                'file a bug report at ' . self::BUG_URI, $code);
-        }
-    }
-
-    // }}}
-    // {{{ getKeys()
-
-    /**
-     * Gets the available keys in the keyring
-     *
-     * Calls GPG with the <kbd>--list-keys</kbd> command and grabs keys. See
-     * the first section of <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG package} for a detailed
-     * description of how the GPG command output is parsed.
-     *
-     * @param string $keyId optional. Only keys with that match the specified
-     *                      pattern are returned. The pattern may be part of
-     *                      a user id, a key id or a key fingerprint. If not
-     *                      specified, all keys are returned.
-     *
-     * @return array an array of {@link Crypt_GPG_Key} objects. If no keys
-     *               match the specified <kbd>$keyId</kbd> an empty array is
-     *               returned.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Key
-     */
-    public function getKeys($keyId = '')
-    {
-        // get private key fingerprints
-        if ($keyId == '') {
-            $operation = '--list-secret-keys';
-        } else {
-            $operation = '--list-secret-keys ' . escapeshellarg($keyId);
-        }
-
-        // According to The file 'doc/DETAILS' in the GnuPG distribution, using
-        // double '--with-fingerprint' also prints the fingerprint for subkeys.
-        $arguments = array(
-            '--with-colons',
-            '--with-fingerprint',
-            '--with-fingerprint',
-            '--fixed-list-mode'
-        );
-
-        $output = '';
-
-        $this->engine->reset();
-        $this->engine->setOutput($output);
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        $code = $this->engine->getErrorCode();
-
-        switch ($code) {
-        case Crypt_GPG::ERROR_NONE:
-        case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-            // ignore not found key errors
-            break;
-        case Crypt_GPG::ERROR_FILE_PERMISSIONS:
-            $filename = $this->engine->getErrorFilename();
-            if ($filename) {
-                throw new Crypt_GPG_FileException(sprintf(
-                    'Error reading GnuPG data file \'%s\'. Check to make ' .
-                    'sure it is readable by the current user.', $filename),
-                    $code, $filename);
-            }
-            throw new Crypt_GPG_FileException(
-                'Error reading GnuPG data file. Check to make GnuPG data ' .
-                'files are readable by the current user.', $code);
-        default:
-            throw new Crypt_GPG_Exception(
-                'Unknown error getting keys. Please use the \'debug\' option ' .
-                'when creating the Crypt_GPG object, and file a bug report ' .
-                'at ' . self::BUG_URI, $code);
-        }
-
-        $privateKeyFingerprints = array();
-
-        $lines = explode(PHP_EOL, $output);
-        foreach ($lines as $line) {
-            $lineExp = explode(':', $line);
-            if ($lineExp[0] == 'fpr') {
-                $privateKeyFingerprints[] = $lineExp[9];
-            }
-        }
-
-        // get public keys
-        if ($keyId == '') {
-            $operation = '--list-public-keys';
-        } else {
-            $operation = '--list-public-keys ' . escapeshellarg($keyId);
-        }
-
-        $output = '';
-
-        $this->engine->reset();
-        $this->engine->setOutput($output);
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        $code = $this->engine->getErrorCode();
-
-        switch ($code) {
-        case Crypt_GPG::ERROR_NONE:
-        case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-            // ignore not found key errors
-            break;
-        case Crypt_GPG::ERROR_FILE_PERMISSIONS:
-            $filename = $this->engine->getErrorFilename();
-            if ($filename) {
-                throw new Crypt_GPG_FileException(sprintf(
-                    'Error reading GnuPG data file \'%s\'. Check to make ' .
-                    'sure it is readable by the current user.', $filename),
-                    $code, $filename);
-            }
-            throw new Crypt_GPG_FileException(
-                'Error reading GnuPG data file. Check to make GnuPG data ' .
-                'files are readable by the current user.', $code);
-        default:
-            throw new Crypt_GPG_Exception(
-                'Unknown error getting keys. Please use the \'debug\' option ' .
-                'when creating the Crypt_GPG object, and file a bug report ' .
-                'at ' . self::BUG_URI, $code);
-        }
-
-        $keys = array();
-
-        $key    = null; // current key
-        $subKey = null; // current sub-key
-
-        $lines = explode(PHP_EOL, $output);
-        foreach ($lines as $line) {
-            $lineExp = explode(':', $line);
-
-            if ($lineExp[0] == 'pub') {
-
-                // new primary key means last key should be added to the array
-                if ($key !== null) {
-                    $keys[] = $key;
-                }
-
-                $key = new Crypt_GPG_Key();
-
-                $subKey = Crypt_GPG_SubKey::parse($line);
-                $key->addSubKey($subKey);
-
-            } elseif ($lineExp[0] == 'sub') {
-
-                $subKey = Crypt_GPG_SubKey::parse($line);
-                $key->addSubKey($subKey);
-
-            } elseif ($lineExp[0] == 'fpr') {
-
-                $fingerprint = $lineExp[9];
-
-                // set current sub-key fingerprint
-                $subKey->setFingerprint($fingerprint);
-
-                // if private key exists, set has private to true
-                if (in_array($fingerprint, $privateKeyFingerprints)) {
-                    $subKey->setHasPrivate(true);
-                }
-
-            } elseif ($lineExp[0] == 'uid') {
-
-                $string = stripcslashes($lineExp[9]); // as per documentation
-                $userId = new Crypt_GPG_UserId($string);
-
-                if ($lineExp[1] == 'r') {
-                    $userId->setRevoked(true);
-                }
-
-                $key->addUserId($userId);
-
-            }
-        }
-
-        // add last key
-        if ($key !== null) {
-            $keys[] = $key;
-        }
-
-        return $keys;
-    }
-
-    // }}}
-    // {{{ getFingerprint()
-
-    /**
-     * Gets a key fingerprint from the keyring
-     *
-     * If more than one key fingerprint is available (for example, if you use
-     * a non-unique user id) only the first key fingerprint is returned.
-     *
-     * Calls the GPG <kbd>--list-keys</kbd> command with the
-     * <kbd>--with-fingerprint</kbd> option to retrieve a public key
-     * fingerprint.
-     *
-     * @param string  $keyId  either the full user id of the key, the email
-     *                        part of the user id of the key, or the key id of
-     *                        the key. For example,
-     *                        "Test User (example) <test@example.com>",
-     *                        "test@example.com" or a hexadecimal string.
-     * @param integer $format optional. How the fingerprint should be formatted.
-     *                        Use {@link Crypt_GPG::FORMAT_X509} for X.509
-     *                        certificate format,
-     *                        {@link Crypt_GPG::FORMAT_CANONICAL} for the format
-     *                        used by GnuPG output and
-     *                        {@link Crypt_GPG::FORMAT_NONE} for no formatting.
-     *                        Defaults to <code>Crypt_GPG::FORMAT_NONE</code>.
-     *
-     * @return string the fingerprint of the key, or null if no fingerprint
-     *                is found for the given <kbd>$keyId</kbd>.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function getFingerprint($keyId, $format = Crypt_GPG::FORMAT_NONE)
-    {
-        $output    = '';
-        $operation = '--list-keys ' . escapeshellarg($keyId);
-        $arguments = array(
-            '--with-colons',
-            '--with-fingerprint'
-        );
-
-        $this->engine->reset();
-        $this->engine->setOutput($output);
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        $code = $this->engine->getErrorCode();
-
-        switch ($code) {
-        case Crypt_GPG::ERROR_NONE:
-        case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-            // ignore not found key errors
-            break;
-        default:
-            throw new Crypt_GPG_Exception(
-                'Unknown error getting key fingerprint. Please use the ' .
-                '\'debug\' option when creating the Crypt_GPG object, and ' .
-                'file a bug report at ' . self::BUG_URI, $code);
-        }
-
-        $fingerprint = null;
-
-        $lines = explode(PHP_EOL, $output);
-        foreach ($lines as $line) {
-            if (substr($line, 0, 3) == 'fpr') {
-                $lineExp     = explode(':', $line);
-                $fingerprint = $lineExp[9];
-
-                switch ($format) {
-                case Crypt_GPG::FORMAT_CANONICAL:
-                    $fingerprintExp = str_split($fingerprint, 4);
-                    $format         = '%s %s %s %s %s  %s %s %s %s %s';
-                    $fingerprint    = vsprintf($format, $fingerprintExp);
-                    break;
-
-                case Crypt_GPG::FORMAT_X509:
-                    $fingerprintExp = str_split($fingerprint, 2);
-                    $fingerprint    = implode(':', $fingerprintExp);
-                    break;
-                }
-
-                break;
-            }
-        }
-
-        return $fingerprint;
-    }
-
-    // }}}
-    // {{{ encrypt()
-
-    /**
-     * Encrypts string data
-     *
-     * Data is ASCII armored by default but may optionally be returned as
-     * binary.
-     *
-     * @param string  $data  the data to be encrypted.
-     * @param boolean $armor optional. If true, ASCII armored data is returned;
-     *                       otherwise, binary data is returned. Defaults to
-     *                       true.
-     *
-     * @return string the encrypted data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
-     *         See {@link Crypt_GPG::addEncryptKey()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @sensitive $data
-     */
-    public function encrypt($data, $armor = true)
-    {
-        return $this->_encrypt($data, false, null, $armor);
-    }
-
-    // }}}
-    // {{{ encryptFile()
-
-    /**
-     * Encrypts a file
-     *
-     * Encrypted data is ASCII armored by default but may optionally be saved
-     * as binary.
-     *
-     * @param string  $filename      the filename of the file to encrypt.
-     * @param string  $encryptedFile optional. The filename of the file in
-     *                               which to store the encrypted data. If null
-     *                               or unspecified, the encrypted data is
-     *                               returned as a string.
-     * @param boolean $armor         optional. If true, ASCII armored data is
-     *                               returned; otherwise, binary data is
-     *                               returned. Defaults to true.
-     *
-     * @return void|string if the <kbd>$encryptedFile</kbd> parameter is null,
-     *                     a string containing the encrypted data is returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
-     *         See {@link Crypt_GPG::addEncryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function encryptFile($filename, $encryptedFile = null, $armor = true)
-    {
-        return $this->_encrypt($filename, true, $encryptedFile, $armor);
-    }
-
-    // }}}
-    // {{{ encryptAndSign()
-
-    /**
-     * Encrypts and signs data
-     *
-     * Data is encrypted and signed in a single pass.
-     *
-     * NOTE: Until GnuPG version 1.4.10, it was not possible to verify
-     * encrypted-signed data without decrypting it at the same time. If you try
-     * to use {@link Crypt_GPG::verify()} method on encrypted-signed data with
-     * earlier GnuPG versions, you will get an error. Please use
-     * {@link Crypt_GPG::decryptAndVerify()} to verify encrypted-signed data.
-     *
-     * @param string  $data  the data to be encrypted and signed.
-     * @param boolean $armor optional. If true, ASCII armored data is returned;
-     *                       otherwise, binary data is returned. Defaults to
-     *                       true.
-     *
-     * @return string the encrypted signed data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
-     *         or if no signing key is specified. See
-     *         {@link Crypt_GPG::addEncryptKey()} and
-     *         {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG::decryptAndVerify()
-     */
-    public function encryptAndSign($data, $armor = true)
-    {
-        return $this->_encryptAndSign($data, false, null, $armor);
-    }
-
-    // }}}
-    // {{{ encryptAndSignFile()
-
-    /**
-     * Encrypts and signs a file
-     *
-     * The file is encrypted and signed in a single pass.
-     *
-     * NOTE: Until GnuPG version 1.4.10, it was not possible to verify
-     * encrypted-signed files without decrypting them at the same time. If you
-     * try to use {@link Crypt_GPG::verify()} method on encrypted-signed files
-     * with earlier GnuPG versions, you will get an error. Please use
-     * {@link Crypt_GPG::decryptAndVerifyFile()} to verify encrypted-signed
-     * files.
-     *
-     * @param string  $filename   the name of the file containing the data to
-     *                            be encrypted and signed.
-     * @param string  $signedFile optional. The name of the file in which the
-     *                            encrypted, signed data should be stored. If
-     *                            null or unspecified, the encrypted, signed
-     *                            data is returned as a string.
-     * @param boolean $armor      optional. If true, ASCII armored data is
-     *                            returned; otherwise, binary data is returned.
-     *                            Defaults to true.
-     *
-     * @return void|string if the <kbd>$signedFile</kbd> parameter is null, a
-     *                     string containing the encrypted, signed data is
-     *                     returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
-     *         or if no signing key is specified. See
-     *         {@link Crypt_GPG::addEncryptKey()} and
-     *         {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG::decryptAndVerifyFile()
-     */
-    public function encryptAndSignFile($filename, $signedFile = null,
-        $armor = true
-    ) {
-        return $this->_encryptAndSign($filename, true, $signedFile, $armor);
-    }
-
-    // }}}
-    // {{{ decrypt()
-
-    /**
-     * Decrypts string data
-     *
-     * This method assumes the required private key is available in the keyring
-     * and throws an exception if the private key is not available. To add a
-     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
-     * {@link Crypt_GPG::importKeyFile()} methods.
-     *
-     * @param string $encryptedData the data to be decrypted.
-     *
-     * @return string the decrypted data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function decrypt($encryptedData)
-    {
-        return $this->_decrypt($encryptedData, false, null);
-    }
-
-    // }}}
-    // {{{ decryptFile()
-
-    /**
-     * Decrypts a file
-     *
-     * This method assumes the required private key is available in the keyring
-     * and throws an exception if the private key is not available. To add a
-     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
-     * {@link Crypt_GPG::importKeyFile()} methods.
-     *
-     * @param string $encryptedFile the name of the encrypted file data to
-     *                              decrypt.
-     * @param string $decryptedFile optional. The name of the file to which the
-     *                              decrypted data should be written. If null
-     *                              or unspecified, the decrypted data is
-     *                              returned as a string.
-     *
-     * @return void|string if the <kbd>$decryptedFile</kbd> parameter is null,
-     *                     a string containing the decrypted data is returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function decryptFile($encryptedFile, $decryptedFile = null)
-    {
-        return $this->_decrypt($encryptedFile, true, $decryptedFile);
-    }
-
-    // }}}
-    // {{{ decryptAndVerify()
-
-    /**
-     * Decrypts and verifies string data
-     *
-     * This method assumes the required private key is available in the keyring
-     * and throws an exception if the private key is not available. To add a
-     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
-     * {@link Crypt_GPG::importKeyFile()} methods.
-     *
-     * @param string $encryptedData the encrypted, signed data to be decrypted
-     *                              and verified.
-     *
-     * @return array two element array. The array has an element 'data'
-     *               containing the decrypted data and an element
-     *               'signatures' containing an array of
-     *               {@link Crypt_GPG_Signature} objects for the signed data.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function decryptAndVerify($encryptedData)
-    {
-        return $this->_decryptAndVerify($encryptedData, false, null);
-    }
-
-    // }}}
-    // {{{ decryptAndVerifyFile()
-
-    /**
-     * Decrypts and verifies a signed, encrypted file
-     *
-     * This method assumes the required private key is available in the keyring
-     * and throws an exception if the private key is not available. To add a
-     * private key to the keyring, use the {@link Crypt_GPG::importKey()} or
-     * {@link Crypt_GPG::importKeyFile()} methods.
-     *
-     * @param string $encryptedFile the name of the signed, encrypted file to
-     *                              to decrypt and verify.
-     * @param string $decryptedFile optional. The name of the file to which the
-     *                              decrypted data should be written. If null
-     *                              or unspecified, the decrypted data is
-     *                              returned in the results array.
-     *
-     * @return array two element array. The array has an element 'data'
-     *               containing the decrypted data and an element
-     *               'signatures' containing an array of
-     *               {@link Crypt_GPG_Signature} objects for the signed data.
-     *               If the decrypted data is written to a file, the 'data'
-     *               element is null.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function decryptAndVerifyFile($encryptedFile, $decryptedFile = null)
-    {
-        return $this->_decryptAndVerify($encryptedFile, true, $decryptedFile);
-    }
-
-    // }}}
-    // {{{ sign()
-
-    /**
-     * Signs data
-     *
-     * Data may be signed using any one of the three available signing modes:
-     * - {@link Crypt_GPG::SIGN_MODE_NORMAL}
-     * - {@link Crypt_GPG::SIGN_MODE_CLEAR}
-     * - {@link Crypt_GPG::SIGN_MODE_DETACHED}
-     *
-     * @param string  $data     the data to be signed.
-     * @param boolean $mode     optional. The data signing mode to use. Should
-     *                          be one of {@link Crypt_GPG::SIGN_MODE_NORMAL},
-     *                          {@link Crypt_GPG::SIGN_MODE_CLEAR} or
-     *                          {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not
-     *                          specified, defaults to
-     *                          <kbd>Crypt_GPG::SIGN_MODE_NORMAL</kbd>.
-     * @param boolean $armor    optional. If true, ASCII armored data is
-     *                          returned; otherwise, binary data is returned.
-     *                          Defaults to true. This has no effect if the
-     *                          mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                          used.
-     * @param boolean $textmode optional. If true, line-breaks in signed data
-     *                          are normalized. Use this option when signing
-     *                          e-mail, or for greater compatibility between
-     *                          systems with different line-break formats.
-     *                          Defaults to false. This has no effect if the
-     *                          mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                          used as clear-signing always uses textmode.
-     *
-     * @return string the signed data, or the signature data if a detached
-     *                signature is requested.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
-     *         See {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function sign($data, $mode = Crypt_GPG::SIGN_MODE_NORMAL,
-        $armor = true, $textmode = false
-    ) {
-        return $this->_sign($data, false, null, $mode, $armor, $textmode);
-    }
-
-    // }}}
-    // {{{ signFile()
-
-    /**
-     * Signs a file
-     *
-     * The file may be signed using any one of the three available signing
-     * modes:
-     * - {@link Crypt_GPG::SIGN_MODE_NORMAL}
-     * - {@link Crypt_GPG::SIGN_MODE_CLEAR}
-     * - {@link Crypt_GPG::SIGN_MODE_DETACHED}
-     *
-     * @param string  $filename   the name of the file containing the data to
-     *                            be signed.
-     * @param string  $signedFile optional. The name of the file in which the
-     *                            signed data should be stored. If null or
-     *                            unspecified, the signed data is returned as a
-     *                            string.
-     * @param boolean $mode       optional. The data signing mode to use. Should
-     *                            be one of {@link Crypt_GPG::SIGN_MODE_NORMAL},
-     *                            {@link Crypt_GPG::SIGN_MODE_CLEAR} or
-     *                            {@link Crypt_GPG::SIGN_MODE_DETACHED}. If not
-     *                            specified, defaults to
-     *                            <kbd>Crypt_GPG::SIGN_MODE_NORMAL</kbd>.
-     * @param boolean $armor      optional. If true, ASCII armored data is
-     *                            returned; otherwise, binary data is returned.
-     *                            Defaults to true. This has no effect if the
-     *                            mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                            used.
-     * @param boolean $textmode   optional. If true, line-breaks in signed data
-     *                            are normalized. Use this option when signing
-     *                            e-mail, or for greater compatibility between
-     *                            systems with different line-break formats.
-     *                            Defaults to false. This has no effect if the
-     *                            mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                            used as clear-signing always uses textmode.
-     *
-     * @return void|string if the <kbd>$signedFile</kbd> parameter is null, a
-     *                     string containing the signed data (or the signature
-     *                     data if a detached signature is requested) is
-     *                     returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
-     *         See {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function signFile($filename, $signedFile = null,
-        $mode = Crypt_GPG::SIGN_MODE_NORMAL, $armor = true, $textmode = false
-    ) {
-        return $this->_sign(
-            $filename,
-            true,
-            $signedFile,
-            $mode,
-            $armor,
-            $textmode
-        );
-    }
-
-    // }}}
-    // {{{ verify()
-
-    /**
-     * Verifies signed data
-     *
-     * The {@link Crypt_GPG::decrypt()} method may be used to get the original
-     * message if the signed data is not clearsigned and does not use a
-     * detached signature.
-     *
-     * @param string $signedData the signed data to be verified.
-     * @param string $signature  optional. If verifying data signed using a
-     *                           detached signature, this must be the detached
-     *                           signature data. The data that was signed is
-     *                           specified in <kbd>$signedData</kbd>.
-     *
-     * @return array an array of {@link Crypt_GPG_Signature} objects for the
-     *               signed data. For each signature that is valid, the
-     *               {@link Crypt_GPG_Signature::isValid()} will return true.
-     *
-     * @throws Crypt_GPG_NoDataException if the provided data is not signed
-     *         data.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Signature
-     */
-    public function verify($signedData, $signature = '')
-    {
-        return $this->_verify($signedData, false, $signature);
-    }
-
-    // }}}
-    // {{{ verifyFile()
-
-    /**
-     * Verifies a signed file
-     *
-     * The {@link Crypt_GPG::decryptFile()} method may be used to get the
-     * original message if the signed data is not clearsigned and does not use
-     * a detached signature.
-     *
-     * @param string $filename  the signed file to be verified.
-     * @param string $signature optional. If verifying a file signed using a
-     *                          detached signature, this must be the detached
-     *                          signature data. The file that was signed is
-     *                          specified in <kbd>$filename</kbd>.
-     *
-     * @return array an array of {@link Crypt_GPG_Signature} objects for the
-     *               signed data. For each signature that is valid, the
-     *               {@link Crypt_GPG_Signature::isValid()} will return true.
-     *
-     * @throws Crypt_GPG_NoDataException if the provided data is not signed
-     *         data.
-     *
-     * @throws Crypt_GPG_FileException if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Signature
-     */
-    public function verifyFile($filename, $signature = '')
-    {
-        return $this->_verify($filename, true, $signature);
-    }
-
-    // }}}
-    // {{{ addDecryptKey()
-
-    /**
-     * Adds a key to use for decryption
-     *
-     * @param mixed  $key        the key to use. This may be a key identifier,
-     *                           user id, fingerprint, {@link Crypt_GPG_Key} or
-     *                           {@link Crypt_GPG_SubKey}. The key must be able
-     *                           to encrypt.
-     * @param string $passphrase optional. The passphrase of the key required
-     *                           for decryption.
-     *
-     * @return void
-     *
-     * @see Crypt_GPG::decrypt()
-     * @see Crypt_GPG::decryptFile()
-     * @see Crypt_GPG::clearDecryptKeys()
-     * @see Crypt_GPG::_addKey()
-     * @see Crypt_GPG_DecryptStatusHandler
-     *
-     * @sensitive $passphrase
-     */
-    public function addDecryptKey($key, $passphrase = null)
-    {
-        $this->_addKey($this->decryptKeys, true, false, $key, $passphrase);
-    }
-
-    // }}}
-    // {{{ addEncryptKey()
-
-    /**
-     * Adds a key to use for encryption
-     *
-     * @param mixed $key the key to use. This may be a key identifier, user id
-     *                   user id, fingerprint, {@link Crypt_GPG_Key} or
-     *                   {@link Crypt_GPG_SubKey}. The key must be able to
-     *                   encrypt.
-     *
-     * @return void
-     *
-     * @see Crypt_GPG::encrypt()
-     * @see Crypt_GPG::encryptFile()
-     * @see Crypt_GPG::clearEncryptKeys()
-     * @see Crypt_GPG::_addKey()
-     */
-    public function addEncryptKey($key)
-    {
-        $this->_addKey($this->encryptKeys, true, false, $key);
-    }
-
-    // }}}
-    // {{{ addSignKey()
-
-    /**
-     * Adds a key to use for signing
-     *
-     * @param mixed  $key        the key to use. This may be a key identifier,
-     *                           user id, fingerprint, {@link Crypt_GPG_Key} or
-     *                           {@link Crypt_GPG_SubKey}. The key must be able
-     *                           to sign.
-     * @param string $passphrase optional. The passphrase of the key required
-     *                           for signing.
-     *
-     * @return void
-     *
-     * @see Crypt_GPG::sign()
-     * @see Crypt_GPG::signFile()
-     * @see Crypt_GPG::clearSignKeys()
-     * @see Crypt_GPG::handleSignStatus()
-     * @see Crypt_GPG::_addKey()
-     *
-     * @sensitive $passphrase
-     */
-    public function addSignKey($key, $passphrase = null)
-    {
-        $this->_addKey($this->signKeys, false, true, $key, $passphrase);
-    }
-
-    // }}}
-    // {{{ clearDecryptKeys()
-
-    /**
-     * Clears all decryption keys
-     *
-     * @return void
-     *
-     * @see Crypt_GPG::decrypt()
-     * @see Crypt_GPG::addDecryptKey()
-     */
-    public function clearDecryptKeys()
-    {
-        $this->decryptKeys = array();
-    }
-
-    // }}}
-    // {{{ clearEncryptKeys()
-
-    /**
-     * Clears all encryption keys
-     *
-     * @return void
-     *
-     * @see Crypt_GPG::encrypt()
-     * @see Crypt_GPG::addEncryptKey()
-     */
-    public function clearEncryptKeys()
-    {
-        $this->encryptKeys = array();
-    }
-
-    // }}}
-    // {{{ clearSignKeys()
-
-    /**
-     * Clears all signing keys
-     *
-     * @return void
-     *
-     * @see Crypt_GPG::sign()
-     * @see Crypt_GPG::addSignKey()
-     */
-    public function clearSignKeys()
-    {
-        $this->signKeys = array();
-    }
-
-    // }}}
-    // {{{ handleSignStatus()
-
-    /**
-     * Handles the status output from GPG for the sign operation
-     *
-     * This method is responsible for sending the passphrase commands when
-     * required by the {@link Crypt_GPG::sign()} method. See <b>doc/DETAILS</b>
-     * in the {@link http://www.gnupg.org/download/ GPG distribution} for
-     * detailed information on GPG's status output.
-     *
-     * @param string $line the status line to handle.
-     *
-     * @return void
-     *
-     * @see Crypt_GPG::sign()
-     */
-    public function handleSignStatus($line)
-    {
-        $tokens = explode(' ', $line);
-        switch ($tokens[0]) {
-        case 'NEED_PASSPHRASE':
-            $subKeyId = $tokens[1];
-            if (array_key_exists($subKeyId, $this->signKeys)) {
-                $passphrase = $this->signKeys[$subKeyId]['passphrase'];
-                $this->engine->sendCommand($passphrase);
-            } else {
-                $this->engine->sendCommand('');
-            }
-            break;
-        }
-    }
-
-    // }}}
-    // {{{ handleImportKeyStatus()
-
-    /**
-     * Handles the status output from GPG for the import operation
-     *
-     * This method is responsible for building the result array that is
-     * returned from the {@link Crypt_GPG::importKey()} method. See
-     * <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG distribution} for detailed
-     * information on GPG's status output.
-     *
-     * @param string $line    the status line to handle.
-     * @param array  &$result the current result array being processed.
-     *
-     * @return void
-     *
-     * @see Crypt_GPG::importKey()
-     * @see Crypt_GPG::importKeyFile()
-     * @see Crypt_GPG_Engine::addStatusHandler()
-     */
-    public function handleImportKeyStatus($line, array &$result)
-    {
-        $tokens = explode(' ', $line);
-        switch ($tokens[0]) {
-        case 'IMPORT_OK':
-            $result['fingerprint'] = $tokens[2];
-            break;
-
-        case 'IMPORT_RES':
-            $result['public_imported']   = intval($tokens[3]);
-            $result['public_unchanged']  = intval($tokens[5]);
-            $result['private_imported']  = intval($tokens[11]);
-            $result['private_unchanged'] = intval($tokens[12]);
-            break;
-        }
-    }
-
-    // }}}
-    // {{{ setEngine()
-
-    /**
-     * Sets the I/O engine to use for GnuPG operations
-     *
-     * Normally this method does not need to be used. It provides a means for
-     * dependency injection.
-     *
-     * @param Crypt_GPG_Engine $engine the engine to use.
-     *
-     * @return void
-     */
-    public function setEngine(Crypt_GPG_Engine $engine)
-    {
-        $this->engine = $engine;
-    }
-
-    // }}}
-    // {{{ _addKey()
-
-    /**
-     * Adds a key to one of the internal key arrays
-     *
-     * This handles resolving full key objects from the provided
-     * <kbd>$key</kbd> value.
-     *
-     * @param array   &$array     the array to which the key should be added.
-     * @param boolean $encrypt    whether or not the key must be able to
-     *                            encrypt.
-     * @param boolean $sign       whether or not the key must be able to sign.
-     * @param mixed   $key        the key to add. This may be a key identifier,
-     *                            user id, fingerprint, {@link Crypt_GPG_Key} or
-     *                            {@link Crypt_GPG_SubKey}.
-     * @param string  $passphrase optional. The passphrase associated with the
-     *                            key.
-     *
-     * @return void
-     *
-     * @sensitive $passphrase
-     */
-    private function _addKey(array &$array, $encrypt, $sign, $key,
-        $passphrase = null
-    ) {
-        $subKeys = array();
-
-        if (is_scalar($key)) {
-            $keys = $this->getKeys($key);
-            if (count($keys) == 0) {
-                throw new Crypt_GPG_KeyNotFoundException(
-                    'Key "' . $key . '" not found.', 0, $key);
-            }
-            $key = $keys[0];
-        }
-
-        if ($key instanceof Crypt_GPG_Key) {
-            if ($encrypt && !$key->canEncrypt()) {
-                throw new InvalidArgumentException(
-                    'Key "' . $key . '" cannot encrypt.');
-            }
-
-            if ($sign && !$key->canSign()) {
-                throw new InvalidArgumentException(
-                    'Key "' . $key . '" cannot sign.');
-            }
-
-            foreach ($key->getSubKeys() as $subKey) {
-                $canEncrypt = $subKey->canEncrypt();
-                $canSign    = $subKey->canSign();
-                if (   ($encrypt && $sign && $canEncrypt && $canSign)
-                    || ($encrypt && !$sign && $canEncrypt)
-                    || (!$encrypt && $sign && $canSign)
-                ) {
-                    // We add all subkeys that meet the requirements because we
-                    // were not told which subkey is required.
-                    $subKeys[] = $subKey;
-                }
-            }
-        } elseif ($key instanceof Crypt_GPG_SubKey) {
-            $subKeys[] = $key;
-        }
-
-        if (count($subKeys) === 0) {
-            throw new InvalidArgumentException(
-                'Key "' . $key . '" is not in a recognized format.');
-        }
-
-        foreach ($subKeys as $subKey) {
-            if ($encrypt && !$subKey->canEncrypt()) {
-                throw new InvalidArgumentException(
-                    'Key "' . $key . '" cannot encrypt.');
-            }
-
-            if ($sign && !$subKey->canSign()) {
-                throw new InvalidArgumentException(
-                    'Key "' . $key . '" cannot sign.');
-            }
-
-            $array[$subKey->getId()] = array(
-                'fingerprint' => $subKey->getFingerprint(),
-                'passphrase'  => $passphrase
-            );
-        }
-    }
-
-    // }}}
-    // {{{ _importKey()
-
-    /**
-     * Imports a public or private key into the keyring
-     *
-     * @param string  $key    the key to be imported.
-     * @param boolean $isFile whether or not the input is a filename.
-     *
-     * @return array an associative array containing the following elements:
-     *               - <kbd>fingerprint</kbd>       - the fingerprint of the
-     *                                                imported key,
-     *               - <kbd>public_imported</kbd>   - the number of public
-     *                                                keys imported,
-     *               - <kbd>public_unchanged</kbd>  - the number of unchanged
-     *                                                public keys,
-     *               - <kbd>private_imported</kbd>  - the number of private
-     *                                                keys imported,
-     *               - <kbd>private_unchanged</kbd> - the number of unchanged
-     *                                                private keys.
-     *
-     * @throws Crypt_GPG_NoDataException if the key data is missing or if the
-     *         data is is not valid key data.
-     *
-     * @throws Crypt_GPG_FileException if the key file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    private function _importKey($key, $isFile)
-    {
-        $result = array();
-
-        if ($isFile) {
-            $input = @fopen($key, 'rb');
-            if ($input === false) {
-                throw new Crypt_GPG_FileException('Could not open key file "' .
-                    $key . '" for importing.', 0, $key);
-            }
-        } else {
-            $input = strval($key);
-            if ($input == '') {
-                throw new Crypt_GPG_NoDataException(
-                    'No valid GPG key data found.', Crypt_GPG::ERROR_NO_DATA);
-            }
-        }
-
-        $arguments = array();
-        $version   = $this->engine->getVersion();
-
-        if (   version_compare($version, '1.0.5', 'ge')
-            && version_compare($version, '1.0.7', 'lt')
-        ) {
-            $arguments[] = '--allow-secret-key-import';
-        }
-
-        $this->engine->reset();
-        $this->engine->addStatusHandler(
-            array($this, 'handleImportKeyStatus'),
-            array(&$result)
-        );
-
-        $this->engine->setOperation('--import', $arguments);
-        $this->engine->setInput($input);
-        $this->engine->run();
-
-        if ($isFile) {
-            fclose($input);
-        }
-
-        $code = $this->engine->getErrorCode();
-
-        switch ($code) {
-        case Crypt_GPG::ERROR_DUPLICATE_KEY:
-        case Crypt_GPG::ERROR_NONE:
-            // ignore duplicate key import errors
-            break;
-        case Crypt_GPG::ERROR_NO_DATA:
-            throw new Crypt_GPG_NoDataException(
-                'No valid GPG key data found.', $code);
-        default:
-            throw new Crypt_GPG_Exception(
-                'Unknown error importing GPG key. Please use the \'debug\' ' .
-                'option when creating the Crypt_GPG object, and file a bug ' .
-                'report at ' . self::BUG_URI, $code);
-        }
-
-        return $result;
-    }
-
-    // }}}
-    // {{{ _encrypt()
-
-    /**
-     * Encrypts data
-     *
-     * @param string  $data       the data to encrypt.
-     * @param boolean $isFile     whether or not the data is a filename.
-     * @param string  $outputFile the filename of the file in which to store
-     *                            the encrypted data. If null, the encrypted
-     *                            data is returned as a string.
-     * @param boolean $armor      if true, ASCII armored data is returned;
-     *                            otherwise, binary data is returned.
-     *
-     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
-     *                     string containing the encrypted data is returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified.
-     *         See {@link Crypt_GPG::addEncryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    private function _encrypt($data, $isFile, $outputFile, $armor)
-    {
-        if (count($this->encryptKeys) === 0) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'No encryption keys specified.');
-        }
-
-        if ($isFile) {
-            $input = @fopen($data, 'rb');
-            if ($input === false) {
-                throw new Crypt_GPG_FileException('Could not open input file "' .
-                    $data . '" for encryption.', 0, $data);
-            }
-        } else {
-            $input = strval($data);
-        }
-
-        if ($outputFile === null) {
-            $output = '';
-        } else {
-            $output = @fopen($outputFile, 'wb');
-            if ($output === false) {
-                if ($isFile) {
-                    fclose($input);
-                }
-                throw new Crypt_GPG_FileException('Could not open output ' .
-                    'file "' . $outputFile . '" for storing encrypted data.',
-                    0, $outputFile);
-            }
-        }
-
-        $arguments = ($armor) ? array('--armor') : array();
-        foreach ($this->encryptKeys as $key) {
-            $arguments[] = '--recipient ' . escapeshellarg($key['fingerprint']);
-        }
-
-        $this->engine->reset();
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->setOperation('--encrypt', $arguments);
-        $this->engine->run();
-
-        if ($isFile) {
-            fclose($input);
-        }
-
-        if ($outputFile !== null) {
-            fclose($output);
-        }
-
-        $code = $this->engine->getErrorCode();
-
-        if ($code !== Crypt_GPG::ERROR_NONE) {
-            throw new Crypt_GPG_Exception(
-                'Unknown error encrypting data. Please use the \'debug\' ' .
-                'option when creating the Crypt_GPG object, and file a bug ' .
-                'report at ' . self::BUG_URI, $code);
-        }
-
-        if ($outputFile === null) {
-            return $output;
-        }
-    }
-
-    // }}}
-    // {{{ _decrypt()
-
-    /**
-     * Decrypts data
-     *
-     * @param string  $data       the data to be decrypted.
-     * @param boolean $isFile     whether or not the data is a filename.
-     * @param string  $outputFile the name of the file to which the decrypted
-     *                            data should be written. If null, the decrypted
-     *                            data is returned as a string.
-     *
-     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
-     *                     string containing the decrypted data is returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    private function _decrypt($data, $isFile, $outputFile)
-    {
-        if ($isFile) {
-            $input = @fopen($data, 'rb');
-            if ($input === false) {
-                throw new Crypt_GPG_FileException('Could not open input file "' .
-                    $data . '" for decryption.', 0, $data);
-            }
-        } else {
-            $input = strval($data);
-            if ($input == '') {
-                throw new Crypt_GPG_NoDataException(
-                    'Cannot decrypt data. No PGP encrypted data was found in '.
-                    'the provided data.', Crypt_GPG::ERROR_NO_DATA);
-            }
-        }
-
-        if ($outputFile === null) {
-            $output = '';
-        } else {
-            $output = @fopen($outputFile, 'wb');
-            if ($output === false) {
-                if ($isFile) {
-                    fclose($input);
-                }
-                throw new Crypt_GPG_FileException('Could not open output ' .
-                    'file "' . $outputFile . '" for storing decrypted data.',
-                    0, $outputFile);
-            }
-        }
-
-        $handler = new Crypt_GPG_DecryptStatusHandler($this->engine,
-            $this->decryptKeys);
-
-        $this->engine->reset();
-        $this->engine->addStatusHandler(array($handler, 'handle'));
-        $this->engine->setOperation('--decrypt');
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->run();
-
-        if ($isFile) {
-            fclose($input);
-        }
-
-        if ($outputFile !== null) {
-            fclose($output);
-        }
-
-        // if there was any problem decrypting the data, the handler will
-        // deal with it here.
-        $handler->throwException();
-
-        if ($outputFile === null) {
-            return $output;
-        }
-    }
-
-    // }}}
-    // {{{ _sign()
-
-    /**
-     * Signs data
-     *
-     * @param string  $data       the data to be signed.
-     * @param boolean $isFile     whether or not the data is a filename.
-     * @param string  $outputFile the name of the file in which the signed data
-     *                            should be stored. If null, the signed data is
-     *                            returned as a string.
-     * @param boolean $mode       the data signing mode to use. Should be one of
-     *                            {@link Crypt_GPG::SIGN_MODE_NORMAL},
-     *                            {@link Crypt_GPG::SIGN_MODE_CLEAR} or
-     *                            {@link Crypt_GPG::SIGN_MODE_DETACHED}.
-     * @param boolean $armor      if true, ASCII armored data is returned;
-     *                            otherwise, binary data is returned. This has
-     *                            no effect if the mode
-     *                            <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                            used.
-     * @param boolean $textmode   if true, line-breaks in signed data be
-     *                            normalized. Use this option when signing
-     *                            e-mail, or for greater compatibility between
-     *                            systems with different line-break formats.
-     *                            Defaults to false. This has no effect if the
-     *                            mode <kbd>Crypt_GPG::SIGN_MODE_CLEAR</kbd> is
-     *                            used as clear-signing always uses textmode.
-     *
-     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
-     *                     string containing the signed data (or the signature
-     *                     data if a detached signature is requested) is
-     *                     returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no signing key is specified.
-     *         See {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    private function _sign($data, $isFile, $outputFile, $mode, $armor,
-        $textmode
-    ) {
-        if (count($this->signKeys) === 0) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'No signing keys specified.');
-        }
-
-        if ($isFile) {
-            $input = @fopen($data, 'rb');
-            if ($input === false) {
-                throw new Crypt_GPG_FileException('Could not open input ' .
-                    'file "' . $data . '" for signing.', 0, $data);
-            }
-        } else {
-            $input = strval($data);
-        }
-
-        if ($outputFile === null) {
-            $output = '';
-        } else {
-            $output = @fopen($outputFile, 'wb');
-            if ($output === false) {
-                if ($isFile) {
-                    fclose($input);
-                }
-                throw new Crypt_GPG_FileException('Could not open output ' .
-                    'file "' . $outputFile . '" for storing signed ' .
-                    'data.', 0, $outputFile);
-            }
-        }
-
-        switch ($mode) {
-        case Crypt_GPG::SIGN_MODE_DETACHED:
-            $operation = '--detach-sign';
-            break;
-        case Crypt_GPG::SIGN_MODE_CLEAR:
-            $operation = '--clearsign';
-            break;
-        case Crypt_GPG::SIGN_MODE_NORMAL:
-        default:
-            $operation = '--sign';
-            break;
-        }
-
-        $arguments  = array();
-
-        if ($armor) {
-            $arguments[] = '--armor';
-        }
-        if ($textmode) {
-            $arguments[] = '--textmode';
-        }
-
-        foreach ($this->signKeys as $key) {
-            $arguments[] = '--local-user ' .
-                escapeshellarg($key['fingerprint']);
-        }
-
-        $this->engine->reset();
-        $this->engine->addStatusHandler(array($this, 'handleSignStatus'));
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        if ($isFile) {
-            fclose($input);
-        }
-
-        if ($outputFile !== null) {
-            fclose($output);
-        }
-
-        $code = $this->engine->getErrorCode();
-
-        switch ($code) {
-        case Crypt_GPG::ERROR_NONE:
-            break;
-        case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Cannot sign data. Private key not found. Import the '.
-                'private key before trying to sign data.', $code,
-                $this->engine->getErrorKeyId());
-        case Crypt_GPG::ERROR_BAD_PASSPHRASE:
-            throw new Crypt_GPG_BadPassphraseException(
-                'Cannot sign data. Incorrect passphrase provided.', $code);
-        case Crypt_GPG::ERROR_MISSING_PASSPHRASE:
-            throw new Crypt_GPG_BadPassphraseException(
-                'Cannot sign data. No passphrase provided.', $code);
-        default:
-            throw new Crypt_GPG_Exception(
-                'Unknown error signing data. Please use the \'debug\' option ' .
-                'when creating the Crypt_GPG object, and file a bug report ' .
-                'at ' . self::BUG_URI, $code);
-        }
-
-        if ($outputFile === null) {
-            return $output;
-        }
-    }
-
-    // }}}
-    // {{{ _encryptAndSign()
-
-    /**
-     * Encrypts and signs data
-     *
-     * @param string  $data       the data to be encrypted and signed.
-     * @param boolean $isFile     whether or not the data is a filename.
-     * @param string  $outputFile the name of the file in which the encrypted,
-     *                            signed data should be stored. If null, the
-     *                            encrypted, signed data is returned as a
-     *                            string.
-     * @param boolean $armor      if true, ASCII armored data is returned;
-     *                            otherwise, binary data is returned.
-     *
-     * @return void|string if the <kbd>$outputFile</kbd> parameter is null, a
-     *                     string containing the encrypted, signed data is
-     *                     returned.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if no encryption key is specified
-     *         or if no signing key is specified. See
-     *         {@link Crypt_GPG::addEncryptKey()} and
-     *         {@link Crypt_GPG::addSignKey()}.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a specified passphrase is
-     *         incorrect or if a required passphrase is not specified.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     */
-    private function _encryptAndSign($data, $isFile, $outputFile, $armor)
-    {
-        if (count($this->signKeys) === 0) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'No signing keys specified.');
-        }
-
-        if (count($this->encryptKeys) === 0) {
-            throw new Crypt_GPG_KeyNotFoundException(
-                'No encryption keys specified.');
-        }
-
-
-        if ($isFile) {
-            $input = @fopen($data, 'rb');
-            if ($input === false) {
-                throw new Crypt_GPG_FileException('Could not open input ' .
-                    'file "' . $data . '" for encrypting and signing.', 0,
-                    $data);
-            }
-        } else {
-            $input = strval($data);
-        }
-
-        if ($outputFile === null) {
-            $output = '';
-        } else {
-            $output = @fopen($outputFile, 'wb');
-            if ($output === false) {
-                if ($isFile) {
-                    fclose($input);
-                }
-                throw new Crypt_GPG_FileException('Could not open output ' .
-                    'file "' . $outputFile . '" for storing encrypted, ' .
-                    'signed data.', 0, $outputFile);
-            }
-        }
-
-        $arguments  = ($armor) ? array('--armor') : array();
-
-        foreach ($this->signKeys as $key) {
-            $arguments[] = '--local-user ' .
-                escapeshellarg($key['fingerprint']);
-        }
-
-        foreach ($this->encryptKeys as $key) {
-            $arguments[] = '--recipient ' . escapeshellarg($key['fingerprint']);
-        }
-
-        $this->engine->reset();
-        $this->engine->addStatusHandler(array($this, 'handleSignStatus'));
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->setOperation('--encrypt --sign', $arguments);
-        $this->engine->run();
-
-        if ($isFile) {
-            fclose($input);
-        }
-
-        if ($outputFile !== null) {
-            fclose($output);
-        }
-
-        $code = $this->engine->getErrorCode();
-
-        switch ($code) {
-        case Crypt_GPG::ERROR_NONE:
-            break;
-        case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Cannot sign encrypted data. Private key not found. Import '.
-                'the private key before trying to sign the encrypted data.',
-                $code, $this->engine->getErrorKeyId());
-        case Crypt_GPG::ERROR_BAD_PASSPHRASE:
-            throw new Crypt_GPG_BadPassphraseException(
-                'Cannot sign encrypted data. Incorrect passphrase provided.',
-                $code);
-        case Crypt_GPG::ERROR_MISSING_PASSPHRASE:
-            throw new Crypt_GPG_BadPassphraseException(
-                'Cannot sign encrypted data. No passphrase provided.', $code);
-        default:
-            throw new Crypt_GPG_Exception(
-                'Unknown error encrypting and signing data. Please use the ' .
-                '\'debug\' option when creating the Crypt_GPG object, and ' .
-                'file a bug report at ' . self::BUG_URI, $code);
-        }
-
-        if ($outputFile === null) {
-            return $output;
-        }
-    }
-
-    // }}}
-    // {{{ _verify()
-
-    /**
-     * Verifies data
-     *
-     * @param string  $data      the signed data to be verified.
-     * @param boolean $isFile    whether or not the data is a filename.
-     * @param string  $signature if verifying a file signed using a detached
-     *                           signature, this must be the detached signature
-     *                           data. Otherwise, specify ''.
-     *
-     * @return array an array of {@link Crypt_GPG_Signature} objects for the
-     *               signed data.
-     *
-     * @throws Crypt_GPG_NoDataException if the provided data is not signed
-     *         data.
-     *
-     * @throws Crypt_GPG_FileException if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Signature
-     */
-    private function _verify($data, $isFile, $signature)
-    {
-        if ($signature == '') {
-            $operation = '--verify';
-            $arguments = array();
-        } else {
-            // Signed data goes in FD_MESSAGE, detached signature data goes in
-            // FD_INPUT.
-            $operation = '--verify - "-&' . Crypt_GPG_Engine::FD_MESSAGE. '"';
-            $arguments = array('--enable-special-filenames');
-        }
-
-        $handler = new Crypt_GPG_VerifyStatusHandler();
-
-        if ($isFile) {
-            $input = @fopen($data, 'rb');
-            if ($input === false) {
-                throw new Crypt_GPG_FileException('Could not open input ' .
-                    'file "' . $data . '" for verifying.', 0, $data);
-            }
-        } else {
-            $input = strval($data);
-            if ($input == '') {
-                throw new Crypt_GPG_NoDataException(
-                    'No valid signature data found.', Crypt_GPG::ERROR_NO_DATA);
-            }
-        }
-
-        $this->engine->reset();
-        $this->engine->addStatusHandler(array($handler, 'handle'));
-
-        if ($signature == '') {
-            // signed or clearsigned data
-            $this->engine->setInput($input);
-        } else {
-            // detached signature
-            $this->engine->setInput($signature);
-            $this->engine->setMessage($input);
-        }
-
-        $this->engine->setOperation($operation, $arguments);
-        $this->engine->run();
-
-        if ($isFile) {
-            fclose($input);
-        }
-
-        $code = $this->engine->getErrorCode();
-
-        switch ($code) {
-        case Crypt_GPG::ERROR_NONE:
-        case Crypt_GPG::ERROR_BAD_SIGNATURE:
-            break;
-        case Crypt_GPG::ERROR_NO_DATA:
-            throw new Crypt_GPG_NoDataException(
-                'No valid signature data found.', $code);
-        case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Public key required for data verification not in keyring.',
-                $code, $this->engine->getErrorKeyId());
-        default:
-            throw new Crypt_GPG_Exception(
-                'Unknown error validating signature details. Please use the ' .
-                '\'debug\' option when creating the Crypt_GPG object, and ' .
-                'file a bug report at ' . self::BUG_URI, $code);
-        }
-
-        return $handler->getSignatures();
-    }
-
-    // }}}
-    // {{{ _decryptAndVerify()
-
-    /**
-     * Decrypts and verifies encrypted, signed data
-     *
-     * @param string  $data       the encrypted signed data to be decrypted and
-     *                            verified.
-     * @param boolean $isFile     whether or not the data is a filename.
-     * @param string  $outputFile the name of the file to which the decrypted
-     *                            data should be written. If null, the decrypted
-     *                            data is returned in the results array.
-     *
-     * @return array two element array. The array has an element 'data'
-     *               containing the decrypted data and an element
-     *               'signatures' containing an array of
-     *               {@link Crypt_GPG_Signature} objects for the signed data.
-     *               If the decrypted data is written to a file, the 'data'
-     *               element is null.
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring or it the public
-     *         key needed for verification is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG signed, encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_FileException if the output file is not writeable or
-     *         if the input file is not readable.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @see Crypt_GPG_Signature
-     */
-    private function _decryptAndVerify($data, $isFile, $outputFile)
-    {
-        if ($isFile) {
-            $input = @fopen($data, 'rb');
-            if ($input === false) {
-                throw new Crypt_GPG_FileException('Could not open input ' .
-                    'file "' . $data . '" for decrypting and verifying.', 0,
-                    $data);
-            }
-        } else {
-            $input = strval($data);
-            if ($input == '') {
-                throw new Crypt_GPG_NoDataException(
-                    'No valid encrypted signed data found.',
-                    Crypt_GPG::ERROR_NO_DATA);
-            }
-        }
-
-        if ($outputFile === null) {
-            $output = '';
-        } else {
-            $output = @fopen($outputFile, 'wb');
-            if ($output === false) {
-                if ($isFile) {
-                    fclose($input);
-                }
-                throw new Crypt_GPG_FileException('Could not open output ' .
-                    'file "' . $outputFile . '" for storing decrypted data.',
-                    0, $outputFile);
-            }
-        }
-
-        $verifyHandler = new Crypt_GPG_VerifyStatusHandler();
-
-        $decryptHandler = new Crypt_GPG_DecryptStatusHandler($this->engine,
-            $this->decryptKeys);
-
-        $this->engine->reset();
-        $this->engine->addStatusHandler(array($verifyHandler, 'handle'));
-        $this->engine->addStatusHandler(array($decryptHandler, 'handle'));
-        $this->engine->setInput($input);
-        $this->engine->setOutput($output);
-        $this->engine->setOperation('--decrypt');
-        $this->engine->run();
-
-        if ($isFile) {
-            fclose($input);
-        }
-
-        if ($outputFile !== null) {
-            fclose($output);
-        }
-
-        $return = array(
-            'data'       => null,
-            'signatures' => $verifyHandler->getSignatures()
-        );
-
-        // if there was any problem decrypting the data, the handler will
-        // deal with it here.
-        try {
-            $decryptHandler->throwException();
-        } catch (Exception $e) {
-            if ($e instanceof Crypt_GPG_KeyNotFoundException) {
-                throw new Crypt_GPG_KeyNotFoundException(
-                    'Public key required for data verification not in ',
-                    'the keyring. Either no suitable private decryption key ' .
-                    'is in the keyring or the public key required for data ' .
-                    'verification is not in the keyring. Import a suitable ' .
-                    'key before trying to decrypt and verify this data.',
-                    self::ERROR_KEY_NOT_FOUND, $this->engine->getErrorKeyId());
-            }
-
-            if ($e instanceof Crypt_GPG_NoDataException) {
-                throw new Crypt_GPG_NoDataException(
-                    'Cannot decrypt and verify data. No PGP encrypted data ' .
-                    'was found in the provided data.', self::ERROR_NO_DATA);
-            }
-
-            throw $e;
-        }
-
-        if ($outputFile === null) {
-            $return['data'] = $output;
-        }
-
-        return $return;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
diff --git a/plugins/enigma/lib/Crypt/GPG/DecryptStatusHandler.php b/plugins/enigma/lib/Crypt/GPG/DecryptStatusHandler.php
deleted file mode 100644
index 40e8d50..0000000
--- a/plugins/enigma/lib/Crypt/GPG/DecryptStatusHandler.php
+++ /dev/null
@@ -1,336 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Crypt_GPG is a package to use GPG from PHP
- *
- * This file contains an object that handles GPG's status output for the
- * decrypt operation.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008-2009 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @version   CVS: $Id: DecryptStatusHandler.php 302814 2010-08-26 15:43:07Z gauthierm $
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-
-/**
- * Crypt_GPG base class
- */
-require_once 'Crypt/GPG.php';
-
-/**
- * GPG exception classes
- */
-require_once 'Crypt/GPG/Exceptions.php';
-
-
-/**
- * Status line handler for the decrypt operation
- *
- * This class is used internally by Crypt_GPG and does not need be used
- * directly. See the {@link Crypt_GPG} class for end-user API.
- *
- * This class is responsible for sending the passphrase commands when required
- * by the {@link Crypt_GPG::decrypt()} method. See <b>doc/DETAILS</b> in the
- * {@link http://www.gnupg.org/download/ GPG distribution} for detailed
- * information on GPG's status output for the decrypt operation.
- *
- * This class is also responsible for parsing error status and throwing a
- * meaningful exception in the event that decryption fails.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-class Crypt_GPG_DecryptStatusHandler
-{
-    // {{{ protected properties
-
-    /**
-     * Keys used to decrypt
-     *
-     * The array is of the form:
-     * <code>
-     * array(
-     *   $key_id => array(
-     *     'fingerprint' => $fingerprint,
-     *     'passphrase'  => $passphrase
-     *   )
-     * );
-     * </code>
-     *
-     * @var array
-     */
-    protected $keys = array();
-
-    /**
-     * Engine used to which passphrases are passed
-     *
-     * @var Crypt_GPG_Engine
-     */
-    protected $engine = null;
-
-    /**
-     * The id of the current sub-key used for decryption
-     *
-     * @var string
-     */
-    protected $currentSubKey = '';
-
-    /**
-     * Whether or not decryption succeeded
-     *
-     * If the message is only signed (compressed) and not encrypted, this is
-     * always true. If the message is encrypted, this flag is set to false
-     * until we know the decryption succeeded.
-     *
-     * @var boolean
-     */
-    protected $decryptionOkay = true;
-
-    /**
-     * Whether or not there was no data for decryption
-     *
-     * @var boolean
-     */
-    protected $noData = false;
-
-    /**
-     * Keys for which the passhprase is missing
-     *
-     * This contains primary user ids indexed by sub-key id and is used to
-     * create helpful exception messages.
-     *
-     * @var array
-     */
-    protected $missingPassphrases = array();
-
-    /**
-     * Keys for which the passhprase is incorrect
-     *
-     * This contains primary user ids indexed by sub-key id and is used to
-     * create helpful exception messages.
-     *
-     * @var array
-     */
-    protected $badPassphrases = array();
-
-    /**
-     * Keys that can be used to decrypt the data but are missing from the
-     * keychain
-     *
-     * This is an array with both the key and value being the sub-key id of
-     * the missing keys.
-     *
-     * @var array
-     */
-    protected $missingKeys = array();
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new decryption status handler
-     *
-     * @param Crypt_GPG_Engine $engine the GPG engine to which passphrases are
-     *                                 passed.
-     * @param array            $keys   the decryption keys to use.
-     */
-    public function __construct(Crypt_GPG_Engine $engine, array $keys)
-    {
-        $this->engine = $engine;
-        $this->keys   = $keys;
-    }
-
-    // }}}
-    // {{{ handle()
-
-    /**
-     * Handles a status line
-     *
-     * @param string $line the status line to handle.
-     *
-     * @return void
-     */
-    public function handle($line)
-    {
-        $tokens = explode(' ', $line);
-        switch ($tokens[0]) {
-        case 'ENC_TO':
-            // Now we know the message is encrypted. Set flag to check if
-            // decryption succeeded.
-            $this->decryptionOkay = false;
-
-            // this is the new key message
-            $this->currentSubKeyId = $tokens[1];
-            break;
-
-        case 'NEED_PASSPHRASE':
-            // send passphrase to the GPG engine
-            $subKeyId = $tokens[1];
-            if (array_key_exists($subKeyId, $this->keys)) {
-                $passphrase = $this->keys[$subKeyId]['passphrase'];
-                $this->engine->sendCommand($passphrase);
-            } else {
-                $this->engine->sendCommand('');
-            }
-            break;
-
-        case 'USERID_HINT':
-            // remember the user id for pretty exception messages
-            $this->badPassphrases[$tokens[1]]
-                = implode(' ', array_splice($tokens, 2));
-
-            break;
-
-        case 'GOOD_PASSPHRASE':
-            // if we got a good passphrase, remove the key from the list of
-            // bad passphrases.
-            unset($this->badPassphrases[$this->currentSubKeyId]);
-            break;
-
-        case 'MISSING_PASSPHRASE':
-            $this->missingPassphrases[$this->currentSubKeyId]
-                = $this->currentSubKeyId;
-
-            break;
-
-        case 'NO_SECKEY':
-            // note: this message is also received if there are multiple
-            // recipients and a previous key had a correct passphrase.
-            $this->missingKeys[$tokens[1]] = $tokens[1];
-            break;
-
-        case 'NODATA':
-            $this->noData = true;
-            break;
-
-        case 'DECRYPTION_OKAY':
-            // If the message is encrypted, this is the all-clear signal.
-            $this->decryptionOkay = true;
-            break;
-        }
-    }
-
-    // }}}
-    // {{{ throwException()
-
-    /**
-     * Takes the final status of the decrypt operation and throws an
-     * appropriate exception
-     *
-     * If decryption was successful, no exception is thrown.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_KeyNotFoundException if the private key needed to
-     *         decrypt the data is not in the user's keyring.
-     *
-     * @throws Crypt_GPG_NoDataException if specified data does not contain
-     *         GPG encrypted data.
-     *
-     * @throws Crypt_GPG_BadPassphraseException if a required passphrase is
-     *         incorrect or if a required passphrase is not specified. See
-     *         {@link Crypt_GPG::addDecryptKey()}.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <i>debug</i> option and file a bug report if these
-     *         exceptions occur.
-     */
-    public function throwException()
-    {
-        $code = Crypt_GPG::ERROR_NONE;
-
-        if (!$this->decryptionOkay) {
-            if (count($this->badPassphrases) > 0) {
-                $code = Crypt_GPG::ERROR_BAD_PASSPHRASE;
-            } elseif (count($this->missingKeys) > 0) {
-                $code = Crypt_GPG::ERROR_KEY_NOT_FOUND;
-            } else {
-                $code = Crypt_GPG::ERROR_UNKNOWN;
-            }
-        } elseif ($this->noData) {
-            $code = Crypt_GPG::ERROR_NO_DATA;
-        }
-
-        switch ($code) {
-        case Crypt_GPG::ERROR_NONE:
-            break;
-
-        case Crypt_GPG::ERROR_KEY_NOT_FOUND:
-            if (count($this->missingKeys) > 0) {
-                $keyId = reset($this->missingKeys);
-            } else {
-                $keyId = '';
-            }
-            throw new Crypt_GPG_KeyNotFoundException(
-                'Cannot decrypt data. No suitable private key is in the ' .
-                'keyring. Import a suitable private key before trying to ' .
-                'decrypt this data.', $code, $keyId);
-
-        case Crypt_GPG::ERROR_BAD_PASSPHRASE:
-            $badPassphrases = array_diff_key(
-                $this->badPassphrases,
-                $this->missingPassphrases
-            );
-
-            $missingPassphrases = array_intersect_key(
-                $this->badPassphrases,
-                $this->missingPassphrases
-            );
-
-            $message =  'Cannot decrypt data.';
-            if (count($badPassphrases) > 0) {
-                $message = ' Incorrect passphrase provided for keys: "' .
-                    implode('", "', $badPassphrases) . '".';
-            }
-            if (count($missingPassphrases) > 0) {
-                $message = ' No passphrase provided for keys: "' .
-                    implode('", "', $badPassphrases) . '".';
-            }
-
-            throw new Crypt_GPG_BadPassphraseException($message, $code,
-                $badPassphrases, $missingPassphrases);
-
-        case Crypt_GPG::ERROR_NO_DATA:
-            throw new Crypt_GPG_NoDataException(
-                'Cannot decrypt data. No PGP encrypted data was found in '.
-                'the provided data.', $code);
-
-        default:
-            throw new Crypt_GPG_Exception(
-                'Unknown error decrypting data.', $code);
-        }
-    }
-
-    // }}}
-}
-
-?>
diff --git a/plugins/enigma/lib/Crypt/GPG/Engine.php b/plugins/enigma/lib/Crypt/GPG/Engine.php
deleted file mode 100644
index 081be8e..0000000
--- a/plugins/enigma/lib/Crypt/GPG/Engine.php
+++ /dev/null
@@ -1,1758 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Crypt_GPG is a package to use GPG from PHP
- *
- * This file contains an engine that handles GPG subprocess control and I/O.
- * PHP's process manipulation functions are used to handle the GPG subprocess.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @version   CVS: $Id: Engine.php 302822 2010-08-26 17:30:57Z gauthierm $
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-
-/**
- * Crypt_GPG base class.
- */
-require_once 'Crypt/GPG.php';
-
-/**
- * GPG exception classes.
- */
-require_once 'Crypt/GPG/Exceptions.php';
-
-/**
- * Standard PEAR exception is used if GPG binary is not found.
- */
-require_once 'PEAR/Exception.php';
-
-// {{{ class Crypt_GPG_Engine
-
-/**
- * Native PHP Crypt_GPG I/O engine
- *
- * This class is used internally by Crypt_GPG and does not need be used
- * directly. See the {@link Crypt_GPG} class for end-user API.
- *
- * This engine uses PHP's native process control functions to directly control
- * the GPG process. The GPG executable is required to be on the system.
- *
- * All data is passed to the GPG subprocess using file descriptors. This is the
- * most secure method of passing data to the GPG subprocess.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-class Crypt_GPG_Engine
-{
-    // {{{ constants
-
-    /**
-     * Size of data chunks that are sent to and retrieved from the IPC pipes.
-     *
-     * PHP reads 8192 bytes. If this is set to less than 8192, PHP reads 8192
-     * and buffers the rest so we might as well just read 8192.
-     *
-     * Using values other than 8192 also triggers PHP bugs.
-     *
-     * @see http://bugs.php.net/bug.php?id=35224
-     */
-    const CHUNK_SIZE = 8192;
-
-    /**
-     * Standard input file descriptor. This is used to pass data to the GPG
-     * process.
-     */
-    const FD_INPUT = 0;
-
-    /**
-     * Standard output file descriptor. This is used to receive normal output
-     * from the GPG process.
-     */
-    const FD_OUTPUT = 1;
-
-    /**
-     * Standard output file descriptor. This is used to receive error output
-     * from the GPG process.
-     */
-    const FD_ERROR = 2;
-
-    /**
-     * GPG status output file descriptor. The status file descriptor outputs
-     * detailed information for many GPG commands. See the second section of
-     * the file <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG package} for a detailed
-     * description of GPG's status output.
-     */
-    const FD_STATUS = 3;
-
-    /**
-     * Command input file descriptor. This is used for methods requiring
-     * passphrases.
-     */
-    const FD_COMMAND = 4;
-
-    /**
-     * Extra message input file descriptor. This is used for passing signed
-     * data when verifying a detached signature.
-     */
-    const FD_MESSAGE = 5;
-
-    /**
-     * Minimum version of GnuPG that is supported.
-     */
-    const MIN_VERSION = '1.0.2';
-
-    // }}}
-    // {{{ private class properties
-
-    /**
-     * Whether or not to use debugging mode
-     *
-     * When set to true, every GPG command is echoed before it is run. Sensitive
-     * data is always handled using pipes and is not specified as part of the
-     * command. As a result, sensitive data is never displayed when debug is
-     * enabled. Sensitive data includes private key data and passphrases.
-     *
-     * Debugging is off by default.
-     *
-     * @var boolean
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_debug = false;
-
-    /**
-     * Location of GPG binary
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     * @see Crypt_GPG_Engine::_getBinary()
-     */
-    private $_binary = '';
-
-    /**
-     * Directory containing the GPG key files
-     *
-     * This property only contains the path when the <i>homedir</i> option
-     * is specified in the constructor.
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_homedir = '';
-
-    /**
-     * File path of the public keyring
-     *
-     * This property only contains the file path when the <i>public_keyring</i>
-     * option is specified in the constructor.
-     *
-     * If the specified file path starts with <kbd>~/</kbd>, the path is
-     * relative to the <i>homedir</i> if specified, otherwise to
-     * <kbd>~/.gnupg</kbd>.
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_publicKeyring = '';
-
-    /**
-     * File path of the private (secret) keyring
-     *
-     * This property only contains the file path when the <i>private_keyring</i>
-     * option is specified in the constructor.
-     *
-     * If the specified file path starts with <kbd>~/</kbd>, the path is
-     * relative to the <i>homedir</i> if specified, otherwise to
-     * <kbd>~/.gnupg</kbd>.
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_privateKeyring = '';
-
-    /**
-     * File path of the trust database
-     *
-     * This property only contains the file path when the <i>trust_db</i>
-     * option is specified in the constructor.
-     *
-     * If the specified file path starts with <kbd>~/</kbd>, the path is
-     * relative to the <i>homedir</i> if specified, otherwise to
-     * <kbd>~/.gnupg</kbd>.
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::__construct()
-     */
-    private $_trustDb = '';
-
-    /**
-     * Array of pipes used for communication with the GPG binary
-     *
-     * This is an array of file descriptor resources.
-     *
-     * @var array
-     */
-    private $_pipes = array();
-
-    /**
-     * Array of currently opened pipes
-     *
-     * This array is used to keep track of remaining opened pipes so they can
-     * be closed when the GPG subprocess is finished. This array is a subset of
-     * the {@link Crypt_GPG_Engine::$_pipes} array and contains opened file
-     * descriptor resources.
-     *
-     * @var array
-     * @see Crypt_GPG_Engine::_closePipe()
-     */
-    private $_openPipes = array();
-
-    /**
-     * A handle for the GPG process
-     *
-     * @var resource
-     */
-    private $_process = null;
-
-    /**
-     * Whether or not the operating system is Darwin (OS X)
-     *
-     * @var boolean
-     */
-    private $_isDarwin = false;
-
-    /**
-     * Commands to be sent to GPG's command input stream
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::sendCommand()
-     */
-    private $_commandBuffer = '';
-
-    /**
-     * Array of status line handlers
-     *
-     * @var array
-     * @see Crypt_GPG_Engine::addStatusHandler()
-     */
-    private $_statusHandlers = array();
-
-    /**
-     * Array of error line handlers
-     *
-     * @var array
-     * @see Crypt_GPG_Engine::addErrorHandler()
-     */
-    private $_errorHandlers = array();
-
-    /**
-     * The error code of the current operation
-     *
-     * @var integer
-     * @see Crypt_GPG_Engine::getErrorCode()
-     */
-    private $_errorCode = Crypt_GPG::ERROR_NONE;
-
-    /**
-     * File related to the error code of the current operation
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::getErrorFilename()
-     */
-    private $_errorFilename = '';
-
-    /**
-     * Key id related to the error code of the current operation
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::getErrorKeyId()
-     */
-    private $_errorkeyId = '';
-
-    /**
-     * The number of currently needed passphrases
-     *
-     * If this is not zero when the GPG command is completed, the error code is
-     * set to {@link Crypt_GPG::ERROR_MISSING_PASSPHRASE}.
-     *
-     * @var integer
-     */
-    private $_needPassphrase = 0;
-
-    /**
-     * The input source
-     *
-     * This is data to send to GPG. Either a string or a stream resource.
-     *
-     * @var string|resource
-     * @see Crypt_GPG_Engine::setInput()
-     */
-    private $_input = null;
-
-    /**
-     * The extra message input source
-     *
-     * Either a string or a stream resource.
-     *
-     * @var string|resource
-     * @see Crypt_GPG_Engine::setMessage()
-     */
-    private $_message = null;
-
-    /**
-     * The output location
-     *
-     * This is where the output from GPG is sent. Either a string or a stream
-     * resource.
-     *
-     * @var string|resource
-     * @see Crypt_GPG_Engine::setOutput()
-     */
-    private $_output = '';
-
-    /**
-     * The GPG operation to execute
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::setOperation()
-     */
-    private $_operation;
-
-    /**
-     * Arguments for the current operation
-     *
-     * @var array
-     * @see Crypt_GPG_Engine::setOperation()
-     */
-    private $_arguments = array();
-
-    /**
-     * The version number of the GPG binary
-     *
-     * @var string
-     * @see Crypt_GPG_Engine::getVersion()
-     */
-    private $_version = '';
-
-    /**
-     * Cached value indicating whether or not mbstring function overloading is
-     * on for strlen
-     *
-     * This is cached for optimal performance inside the I/O loop.
-     *
-     * @var boolean
-     * @see Crypt_GPG_Engine::_byteLength()
-     * @see Crypt_GPG_Engine::_byteSubstring()
-     */
-    private static $_mbStringOverload = null;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new GPG engine
-     *
-     * Available options are:
-     *
-     * - <kbd>string  homedir</kbd>        - the directory where the GPG
-     *                                       keyring files are stored. If not
-     *                                       specified, Crypt_GPG uses the
-     *                                       default of <kbd>~/.gnupg</kbd>.
-     * - <kbd>string  publicKeyring</kbd>  - the file path of the public
-     *                                       keyring. Use this if the public
-     *                                       keyring is not in the homedir, or
-     *                                       if the keyring is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       keyring with this option
-     *                                       (/foo/bar/pubring.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  privateKeyring</kbd> - the file path of the private
-     *                                       keyring. Use this if the private
-     *                                       keyring is not in the homedir, or
-     *                                       if the keyring is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       keyring with this option
-     *                                       (/foo/bar/secring.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  trustDb</kbd>        - the file path of the web-of-trust
-     *                                       database. Use this if the trust
-     *                                       database is not in the homedir, or
-     *                                       if the database is in a directory
-     *                                       not writable by the process
-     *                                       invoking GPG (like Apache). Then
-     *                                       you can specify the path to the
-     *                                       trust database with this option
-     *                                       (/foo/bar/trustdb.gpg), and specify
-     *                                       a writable directory (like /tmp)
-     *                                       using the <i>homedir</i> option.
-     * - <kbd>string  binary</kbd>         - the location of the GPG binary. If
-     *                                       not specified, the driver attempts
-     *                                       to auto-detect the GPG binary
-     *                                       location using a list of known
-     *                                       default locations for the current
-     *                                       operating system. The option
-     *                                       <kbd>gpgBinary</kbd> is a
-     *                                       deprecated alias for this option.
-     * - <kbd>boolean debug</kbd>          - whether or not to use debug mode.
-     *                                       When debug mode is on, all
-     *                                       communication to and from the GPG
-     *                                       subprocess is logged. This can be
-     *                                       useful to diagnose errors when
-     *                                       using Crypt_GPG.
-     *
-     * @param array $options optional. An array of options used to create the
-     *                       GPG object. All options are optional and are
-     *                       represented as key-value pairs.
-     *
-     * @throws Crypt_GPG_FileException if the <kbd>homedir</kbd> does not exist
-     *         and cannot be created. This can happen if <kbd>homedir</kbd> is
-     *         not specified, Crypt_GPG is run as the web user, and the web
-     *         user has no home directory. This exception is also thrown if any
-     *         of the options <kbd>publicKeyring</kbd>,
-     *         <kbd>privateKeyring</kbd> or <kbd>trustDb</kbd> options are
-     *         specified but the files do not exist or are are not readable.
-     *         This can happen if the user running the Crypt_GPG process (for
-     *         example, the Apache user) does not have permission to read the
-     *         files.
-     *
-     * @throws PEAR_Exception if the provided <kbd>binary</kbd> is invalid, or
-     *         if no <kbd>binary</kbd> is provided and no suitable binary could
-     *         be found.
-     */
-    public function __construct(array $options = array())
-    {
-        $this->_isDarwin = (strncmp(strtoupper(PHP_OS), 'DARWIN', 6) === 0);
-
-        // populate mbstring overloading cache if not set
-        if (self::$_mbStringOverload === null) {
-            self::$_mbStringOverload = (extension_loaded('mbstring')
-                && (ini_get('mbstring.func_overload') & 0x02) === 0x02);
-        }
-
-        // get homedir
-        if (array_key_exists('homedir', $options)) {
-            $this->_homedir = (string)$options['homedir'];
-        } else {
-            // note: this requires the package OS dep exclude 'windows'
-            $info = posix_getpwuid(posix_getuid());
-            $this->_homedir = $info['dir'].'/.gnupg';
-        }
-
-        // attempt to create homedir if it does not exist
-        if (!is_dir($this->_homedir)) {
-            if (@mkdir($this->_homedir, 0777, true)) {
-                // Set permissions on homedir. Parent directories are created
-                // with 0777, homedir is set to 0700.
-                chmod($this->_homedir, 0700);
-            } else {
-                throw new Crypt_GPG_FileException('The \'homedir\' "' .
-                    $this->_homedir . '" is not readable or does not exist '.
-                    'and cannot be created. This can happen if \'homedir\' '.
-                    'is not specified in the Crypt_GPG options, Crypt_GPG is '.
-                    'run as the web user, and the web user has no home '.
-                    'directory.',
-                    0, $this->_homedir);
-            }
-        }
-
-        // get binary
-        if (array_key_exists('binary', $options)) {
-            $this->_binary = (string)$options['binary'];
-        } elseif (array_key_exists('gpgBinary', $options)) {
-            // deprecated alias
-            $this->_binary = (string)$options['gpgBinary'];
-        } else {
-            $this->_binary = $this->_getBinary();
-        }
-
-        if ($this->_binary == '' || !is_executable($this->_binary)) {
-            throw new PEAR_Exception('GPG binary not found. If you are sure '.
-                'the GPG binary is installed, please specify the location of '.
-                'the GPG binary using the \'binary\' driver option.');
-        }
-
-        /*
-         * Note:
-         *
-         * Normally, GnuPG expects keyrings to be in the homedir and expects
-         * to be able to write temporary files in the homedir. Sometimes,
-         * keyrings are not in the homedir, or location of the keyrings does
-         * not allow writing temporary files. In this case, the <i>homedir</i>
-         * option by itself is not enough to specify the keyrings because GnuPG
-         * can not write required temporary files. Additional options are
-         * provided so you can specify the location of the keyrings separately
-         * from the homedir.
-         */
-
-        // get public keyring
-        if (array_key_exists('publicKeyring', $options)) {
-            $this->_publicKeyring = (string)$options['publicKeyring'];
-            if (!is_readable($this->_publicKeyring)) {
-                 throw new Crypt_GPG_FileException('The \'publicKeyring\' "' .
-                    $this->_publicKeyring . '" does not exist or is ' .
-                    'not readable. Check the location and ensure the file ' .
-                    'permissions are correct.', 0, $this->_publicKeyring);
-            }
-        }
-
-        // get private keyring
-        if (array_key_exists('privateKeyring', $options)) {
-            $this->_privateKeyring = (string)$options['privateKeyring'];
-            if (!is_readable($this->_privateKeyring)) {
-                 throw new Crypt_GPG_FileException('The \'privateKeyring\' "' .
-                    $this->_privateKeyring . '" does not exist or is ' .
-                    'not readable. Check the location and ensure the file ' .
-                    'permissions are correct.', 0, $this->_privateKeyring);
-            }
-        }
-
-        // get trust database
-        if (array_key_exists('trustDb', $options)) {
-            $this->_trustDb = (string)$options['trustDb'];
-            if (!is_readable($this->_trustDb)) {
-                 throw new Crypt_GPG_FileException('The \'trustDb\' "' .
-                    $this->_trustDb . '" does not exist or is not readable. ' .
-                    'Check the location and ensure the file permissions are ' .
-                    'correct.', 0, $this->_trustDb);
-            }
-        }
-
-        if (array_key_exists('debug', $options)) {
-            $this->_debug = (boolean)$options['debug'];
-        }
-    }
-
-    // }}}
-    // {{{ __destruct()
-
-    /**
-     * Closes open GPG subprocesses when this object is destroyed
-     *
-     * Subprocesses should never be left open by this class unless there is
-     * an unknown error and unexpected script termination occurs.
-     */
-    public function __destruct()
-    {
-        $this->_closeSubprocess();
-    }
-
-    // }}}
-    // {{{ addErrorHandler()
-
-    /**
-     * Adds an error handler method
-     *
-     * The method is run every time a new error line is received from the GPG
-     * subprocess. The handler method must accept the error line to be handled
-     * as its first parameter.
-     *
-     * @param callback $callback the callback method to use.
-     * @param array    $args     optional. Additional arguments to pass as
-     *                           parameters to the callback method.
-     *
-     * @return void
-     */
-    public function addErrorHandler($callback, array $args = array())
-    {
-        $this->_errorHandlers[] = array(
-            'callback' => $callback,
-            'args'     => $args
-        );
-    }
-
-    // }}}
-    // {{{ addStatusHandler()
-
-    /**
-     * Adds a status handler method
-     *
-     * The method is run every time a new status line is received from the
-     * GPG subprocess. The handler method must accept the status line to be
-     * handled as its first parameter.
-     *
-     * @param callback $callback the callback method to use.
-     * @param array    $args     optional. Additional arguments to pass as
-     *                           parameters to the callback method.
-     *
-     * @return void
-     */
-    public function addStatusHandler($callback, array $args = array())
-    {
-        $this->_statusHandlers[] = array(
-            'callback' => $callback,
-            'args'     => $args
-        );
-    }
-
-    // }}}
-    // {{{ sendCommand()
-
-    /**
-     * Sends a command to the GPG subprocess over the command file-descriptor
-     * pipe
-     *
-     * @param string $command the command to send.
-     *
-     * @return void
-     *
-     * @sensitive $command
-     */
-    public function sendCommand($command)
-    {
-        if (array_key_exists(self::FD_COMMAND, $this->_openPipes)) {
-            $this->_commandBuffer .= $command . PHP_EOL;
-        }
-    }
-
-    // }}}
-    // {{{ reset()
-
-    /**
-     * Resets the GPG engine, preparing it for a new operation
-     *
-     * @return void
-     *
-     * @see Crypt_GPG_Engine::run()
-     * @see Crypt_GPG_Engine::setOperation()
-     */
-    public function reset()
-    {
-        $this->_operation      = '';
-        $this->_arguments      = array();
-        $this->_input          = null;
-        $this->_message        = null;
-        $this->_output         = '';
-        $this->_errorCode      = Crypt_GPG::ERROR_NONE;
-        $this->_needPassphrase = 0;
-        $this->_commandBuffer  = '';
-
-        $this->_statusHandlers = array();
-        $this->_errorHandlers  = array();
-
-        $this->addStatusHandler(array($this, '_handleErrorStatus'));
-        $this->addErrorHandler(array($this, '_handleErrorError'));
-
-        if ($this->_debug) {
-            $this->addStatusHandler(array($this, '_handleDebugStatus'));
-            $this->addErrorHandler(array($this, '_handleDebugError'));
-        }
-    }
-
-    // }}}
-    // {{{ run()
-
-    /**
-     * Runs the current GPG operation
-     *
-     * This creates and manages the GPG subprocess.
-     *
-     * The operation must be set with {@link Crypt_GPG_Engine::setOperation()}
-     * before this method is called.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_InvalidOperationException if no operation is specified.
-     *
-     * @see Crypt_GPG_Engine::reset()
-     * @see Crypt_GPG_Engine::setOperation()
-     */
-    public function run()
-    {
-        if ($this->_operation === '') {
-            throw new Crypt_GPG_InvalidOperationException('No GPG operation ' .
-                'specified. Use Crypt_GPG_Engine::setOperation() before ' .
-                'calling Crypt_GPG_Engine::run().');
-        }
-
-        $this->_openSubprocess();
-        $this->_process();
-        $this->_closeSubprocess();
-    }
-
-    // }}}
-    // {{{ getErrorCode()
-
-    /**
-     * Gets the error code of the last executed operation
-     *
-     * This value is only meaningful after {@link Crypt_GPG_Engine::run()} has
-     * been executed.
-     *
-     * @return integer the error code of the last executed operation.
-     */
-    public function getErrorCode()
-    {
-        return $this->_errorCode;
-    }
-
-    // }}}
-    // {{{ getErrorFilename()
-
-    /**
-     * Gets the file related to the error code of the last executed operation
-     *
-     * This value is only meaningful after {@link Crypt_GPG_Engine::run()} has
-     * been executed. If there is no file related to the error, an empty string
-     * is returned.
-     *
-     * @return string the file related to the error code of the last executed
-     *                operation.
-     */
-    public function getErrorFilename()
-    {
-        return $this->_errorFilename;
-    }
-
-    // }}}
-    // {{{ getErrorKeyId()
-
-    /**
-     * Gets the key id related to the error code of the last executed operation
-     *
-     * This value is only meaningful after {@link Crypt_GPG_Engine::run()} has
-     * been executed. If there is no key id related to the error, an empty
-     * string is returned.
-     *
-     * @return string the key id related to the error code of the last executed
-     *                operation.
-     */
-    public function getErrorKeyId()
-    {
-        return $this->_errorKeyId;
-    }
-
-    // }}}
-    // {{{ setInput()
-
-    /**
-     * Sets the input source for the current GPG operation
-     *
-     * @param string|resource &$input either a reference to the string
-     *                                containing the input data or an open
-     *                                stream resource containing the input
-     *                                data.
-     *
-     * @return void
-     */
-    public function setInput(&$input)
-    {
-        $this->_input =& $input;
-    }
-
-    // }}}
-    // {{{ setMessage()
-
-    /**
-     * Sets the message source for the current GPG operation
-     *
-     * Detached signature data should be specified here.
-     *
-     * @param string|resource &$message either a reference to the string
-     *                                  containing the message data or an open
-     *                                  stream resource containing the message
-     *                                  data.
-     *
-     * @return void
-     */
-    public function setMessage(&$message)
-    {
-        $this->_message =& $message;
-    }
-
-    // }}}
-    // {{{ setOutput()
-
-    /**
-     * Sets the output destination for the current GPG operation
-     *
-     * @param string|resource &$output either a reference to the string in
-     *                                 which to store GPG output or an open
-     *                                 stream resource to which the output data
-     *                                 should be written.
-     *
-     * @return void
-     */
-    public function setOutput(&$output)
-    {
-        $this->_output =& $output;
-    }
-
-    // }}}
-    // {{{ setOperation()
-
-    /**
-     * Sets the operation to perform
-     *
-     * @param string $operation the operation to perform. This should be one
-     *                          of GPG's operations. For example,
-     *                          <kbd>--encrypt</kbd>, <kbd>--decrypt</kbd>,
-     *                          <kbd>--sign</kbd>, etc.
-     * @param array  $arguments optional. Additional arguments for the GPG
-     *                          subprocess. See the GPG manual for specific
-     *                          values.
-     *
-     * @return void
-     *
-     * @see Crypt_GPG_Engine::reset()
-     * @see Crypt_GPG_Engine::run()
-     */
-    public function setOperation($operation, array $arguments = array())
-    {
-        $this->_operation = $operation;
-        $this->_arguments = $arguments;
-    }
-
-    // }}}
-    // {{{ getVersion()
-
-    /**
-     * Gets the version of the GnuPG binary
-     *
-     * @return string a version number string containing the version of GnuPG
-     *                being used. This value is suitable to use with PHP's
-     *                version_compare() function.
-     *
-     * @throws Crypt_GPG_Exception if an unknown or unexpected error occurs.
-     *         Use the <kbd>debug</kbd> option and file a bug report if these
-     *         exceptions occur.
-     *
-     * @throws Crypt_GPG_UnsupportedException if the provided binary is not
-     *         GnuPG or if the GnuPG version is less than 1.0.2.
-     */
-    public function getVersion()
-    {
-        if ($this->_version == '') {
-
-            $options = array(
-                'homedir' => $this->_homedir,
-                'binary'  => $this->_binary,
-                'debug'   => $this->_debug
-            );
-
-            $engine = new self($options);
-            $info   = '';
-
-            // Set a garbage version so we do not end up looking up the version
-            // recursively.
-            $engine->_version = '1.0.0';
-
-            $engine->reset();
-            $engine->setOutput($info);
-            $engine->setOperation('--version');
-            $engine->run();
-
-            $code = $this->getErrorCode();
-
-            if ($code !== Crypt_GPG::ERROR_NONE) {
-                throw new Crypt_GPG_Exception(
-                    'Unknown error getting GnuPG version information. Please ' .
-                    'use the \'debug\' option when creating the Crypt_GPG ' .
-                    'object, and file a bug report at ' . Crypt_GPG::BUG_URI,
-                    $code);
-            }
-
-            $matches    = array();
-            $expression = '/gpg \(GnuPG\) (\S+)/';
-
-            if (preg_match($expression, $info, $matches) === 1) {
-                $this->_version = $matches[1];
-            } else {
-                throw new Crypt_GPG_Exception(
-                    'No GnuPG version information provided by the binary "' .
-                    $this->_binary . '". Are you sure it is GnuPG?');
-            }
-
-            if (version_compare($this->_version, self::MIN_VERSION, 'lt')) {
-                throw new Crypt_GPG_Exception(
-                    'The version of GnuPG being used (' . $this->_version .
-                    ') is not supported by Crypt_GPG. The minimum version ' .
-                    'required by Crypt_GPG is ' . self::MIN_VERSION);
-            }
-        }
-
-
-        return $this->_version;
-    }
-
-    // }}}
-    // {{{ _handleErrorStatus()
-
-    /**
-     * Handles error values in the status output from GPG
-     *
-     * This method is responsible for setting the
-     * {@link Crypt_GPG_Engine::$_errorCode}. See <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG distribution} for detailed
-     * information on GPG's status output.
-     *
-     * @param string $line the status line to handle.
-     *
-     * @return void
-     */
-    private function _handleErrorStatus($line)
-    {
-        $tokens = explode(' ', $line);
-        switch ($tokens[0]) {
-        case 'BAD_PASSPHRASE':
-            $this->_errorCode = Crypt_GPG::ERROR_BAD_PASSPHRASE;
-            break;
-
-        case 'MISSING_PASSPHRASE':
-            $this->_errorCode = Crypt_GPG::ERROR_MISSING_PASSPHRASE;
-            break;
-
-        case 'NODATA':
-            $this->_errorCode = Crypt_GPG::ERROR_NO_DATA;
-            break;
-
-        case 'DELETE_PROBLEM':
-            if ($tokens[1] == '1') {
-                $this->_errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND;
-                break;
-            } elseif ($tokens[1] == '2') {
-                $this->_errorCode = Crypt_GPG::ERROR_DELETE_PRIVATE_KEY;
-                break;
-            }
-            break;
-
-        case 'IMPORT_RES':
-            if ($tokens[12] > 0) {
-                $this->_errorCode = Crypt_GPG::ERROR_DUPLICATE_KEY;
-            }
-            break;
-
-        case 'NO_PUBKEY':
-        case 'NO_SECKEY':
-            $this->_errorKeyId = $tokens[1];
-            $this->_errorCode  = Crypt_GPG::ERROR_KEY_NOT_FOUND;
-            break;
-
-        case 'NEED_PASSPHRASE':
-            $this->_needPassphrase++;
-            break;
-
-        case 'GOOD_PASSPHRASE':
-            $this->_needPassphrase--;
-            break;
-
-        case 'EXPSIG':
-        case 'EXPKEYSIG':
-        case 'REVKEYSIG':
-        case 'BADSIG':
-            $this->_errorCode = Crypt_GPG::ERROR_BAD_SIGNATURE;
-            break;
-
-        }
-    }
-
-    // }}}
-    // {{{ _handleErrorError()
-
-    /**
-     * Handles error values in the error output from GPG
-     *
-     * This method is responsible for setting the
-     * {@link Crypt_GPG_Engine::$_errorCode}.
-     *
-     * @param string $line the error line to handle.
-     *
-     * @return void
-     */
-    private function _handleErrorError($line)
-    {
-        if ($this->_errorCode === Crypt_GPG::ERROR_NONE) {
-            $pattern = '/no valid OpenPGP data found/';
-            if (preg_match($pattern, $line) === 1) {
-                $this->_errorCode = Crypt_GPG::ERROR_NO_DATA;
-            }
-        }
-
-        if ($this->_errorCode === Crypt_GPG::ERROR_NONE) {
-            $pattern = '/No secret key|secret key not available/';
-            if (preg_match($pattern, $line) === 1) {
-                $this->_errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND;
-            }
-        }
-
-        if ($this->_errorCode === Crypt_GPG::ERROR_NONE) {
-            $pattern = '/No public key|public key not found/';
-            if (preg_match($pattern, $line) === 1) {
-                $this->_errorCode = Crypt_GPG::ERROR_KEY_NOT_FOUND;
-            }
-        }
-
-        if ($this->_errorCode === Crypt_GPG::ERROR_NONE) {
-            $matches = array();
-            $pattern = '/can\'t (?:access|open) `(.*?)\'/';
-            if (preg_match($pattern, $line, $matches) === 1) {
-                $this->_errorFilename = $matches[1];
-                $this->_errorCode = Crypt_GPG::ERROR_FILE_PERMISSIONS;
-            }
-        }
-    }
-
-    // }}}
-    // {{{ _handleDebugStatus()
-
-    /**
-     * Displays debug output for status lines
-     *
-     * @param string $line the status line to handle.
-     *
-     * @return void
-     */
-    private function _handleDebugStatus($line)
-    {
-        $this->_debug('STATUS: ' . $line);
-    }
-
-    // }}}
-    // {{{ _handleDebugError()
-
-    /**
-     * Displays debug output for error lines
-     *
-     * @param string $line the error line to handle.
-     *
-     * @return void
-     */
-    private function _handleDebugError($line)
-    {
-        $this->_debug('ERROR: ' . $line);
-    }
-
-    // }}}
-    // {{{ _process()
-
-    /**
-     * Performs internal streaming operations for the subprocess using either
-     * strings or streams as input / output points
-     *
-     * This is the main I/O loop for streaming to and from the GPG subprocess.
-     *
-     * The implementation of this method is verbose mainly for performance
-     * reasons. Adding streams to a lookup array and looping the array inside
-     * the main I/O loop would be siginficantly slower for large streams.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_Exception if there is an error selecting streams for
-     *         reading or writing. If this occurs, please file a bug report at
-     *         http://pear.php.net/bugs/report.php?package=Crypt_GPG.
-     */
-    private function _process()
-    {
-        $this->_debug('BEGIN PROCESSING');
-
-        $this->_commandBuffer = '';    // buffers input to GPG
-        $messageBuffer        = '';    // buffers input to GPG
-        $inputBuffer          = '';    // buffers input to GPG
-        $outputBuffer         = '';    // buffers output from GPG
-        $statusBuffer         = '';    // buffers output from GPG
-        $errorBuffer          = '';    // buffers output from GPG
-        $inputComplete        = false; // input stream is completely buffered
-        $messageComplete      = false; // message stream is completely buffered
-
-        if (is_string($this->_input)) {
-            $inputBuffer   = $this->_input;
-            $inputComplete = true;
-        }
-
-        if (is_string($this->_message)) {
-            $messageBuffer   = $this->_message;
-            $messageComplete = true;
-        }
-
-        if (is_string($this->_output)) {
-            $outputBuffer =& $this->_output;
-        }
-
-        // convenience variables
-        $fdInput   = $this->_pipes[self::FD_INPUT];
-        $fdOutput  = $this->_pipes[self::FD_OUTPUT];
-        $fdError   = $this->_pipes[self::FD_ERROR];
-        $fdStatus  = $this->_pipes[self::FD_STATUS];
-        $fdCommand = $this->_pipes[self::FD_COMMAND];
-        $fdMessage = $this->_pipes[self::FD_MESSAGE];
-
-        while (true) {
-
-            $inputStreams     = array();
-            $outputStreams    = array();
-            $exceptionStreams = array();
-
-            // set up input streams
-            if (is_resource($this->_input) && !$inputComplete) {
-                if (feof($this->_input)) {
-                    $inputComplete = true;
-                } else {
-                    $inputStreams[] = $this->_input;
-                }
-            }
-
-            // close GPG input pipe if there is no more data
-            if ($inputBuffer == '' && $inputComplete) {
-                $this->_debug('=> closing GPG input pipe');
-                $this->_closePipe(self::FD_INPUT);
-            }
-
-            if (is_resource($this->_message) && !$messageComplete) {
-                if (feof($this->_message)) {
-                    $messageComplete = true;
-                } else {
-                    $inputStreams[] = $this->_message;
-                }
-            }
-
-            // close GPG message pipe if there is no more data
-            if ($messageBuffer == '' && $messageComplete) {
-                $this->_debug('=> closing GPG message pipe');
-                $this->_closePipe(self::FD_MESSAGE);
-            }
-
-            if (!feof($fdOutput)) {
-                $inputStreams[] = $fdOutput;
-            }
-
-            if (!feof($fdStatus)) {
-                $inputStreams[] = $fdStatus;
-            }
-
-            if (!feof($fdError)) {
-                $inputStreams[] = $fdError;
-            }
-
-            // set up output streams
-            if ($outputBuffer != '' && is_resource($this->_output)) {
-                $outputStreams[] = $this->_output;
-            }
-
-            if ($this->_commandBuffer != '') {
-                $outputStreams[] = $fdCommand;
-            }
-
-            if ($messageBuffer != '') {
-                $outputStreams[] = $fdMessage;
-            }
-
-            if ($inputBuffer != '') {
-                $outputStreams[] = $fdInput;
-            }
-
-            // no streams left to read or write, we're all done
-            if (count($inputStreams) === 0 && count($outputStreams) === 0) {
-                break;
-            }
-
-            $this->_debug('selecting streams');
-
-            $ready = stream_select(
-                $inputStreams,
-                $outputStreams,
-                $exceptionStreams,
-                null
-            );
-
-            $this->_debug('=> got ' . $ready);
-
-            if ($ready === false) {
-                throw new Crypt_GPG_Exception(
-                    'Error selecting stream for communication with GPG ' .
-                    'subprocess. Please file a bug report at: ' .
-                    'http://pear.php.net/bugs/report.php?package=Crypt_GPG');
-            }
-
-            if ($ready === 0) {
-                throw new Crypt_GPG_Exception(
-                    'stream_select() returned 0. This can not happen! Please ' .
-                    'file a bug report at: ' .
-                    'http://pear.php.net/bugs/report.php?package=Crypt_GPG');
-            }
-
-            // write input (to GPG)
-            if (in_array($fdInput, $outputStreams)) {
-                $this->_debug('GPG is ready for input');
-
-                $chunk = self::_byteSubstring(
-                    $inputBuffer,
-                    0,
-                    self::CHUNK_SIZE
-                );
-
-                $length = self::_byteLength($chunk);
-
-                $this->_debug(
-                    '=> about to write ' . $length . ' bytes to GPG input'
-                );
-
-                $length = fwrite($fdInput, $chunk, $length);
-
-                $this->_debug('=> wrote ' . $length . ' bytes');
-
-                $inputBuffer = self::_byteSubstring(
-                    $inputBuffer,
-                    $length
-                );
-            }
-
-            // read input (from PHP stream)
-            if (in_array($this->_input, $inputStreams)) {
-                $this->_debug('input stream is ready for reading');
-                $this->_debug(
-                    '=> about to read ' . self::CHUNK_SIZE .
-                    ' bytes from input stream'
-                );
-
-                $chunk        = fread($this->_input, self::CHUNK_SIZE);
-                $length       = self::_byteLength($chunk);
-                $inputBuffer .= $chunk;
-
-                $this->_debug('=> read ' . $length . ' bytes');
-            }
-
-            // write message (to GPG)
-            if (in_array($fdMessage, $outputStreams)) {
-                $this->_debug('GPG is ready for message data');
-
-                $chunk = self::_byteSubstring(
-                    $messageBuffer,
-                    0,
-                    self::CHUNK_SIZE
-                );
-
-                $length = self::_byteLength($chunk);
-
-                $this->_debug(
-                    '=> about to write ' . $length . ' bytes to GPG message'
-                );
-
-                $length = fwrite($fdMessage, $chunk, $length);
-                $this->_debug('=> wrote ' . $length . ' bytes');
-
-                $messageBuffer = self::_byteSubstring($messageBuffer, $length);
-            }
-
-            // read message (from PHP stream)
-            if (in_array($this->_message, $inputStreams)) {
-                $this->_debug('message stream is ready for reading');
-                $this->_debug(
-                    '=> about to read ' . self::CHUNK_SIZE .
-                    ' bytes from message stream'
-                );
-
-                $chunk          = fread($this->_message, self::CHUNK_SIZE);
-                $length         = self::_byteLength($chunk);
-                $messageBuffer .= $chunk;
-
-                $this->_debug('=> read ' . $length . ' bytes');
-            }
-
-            // read output (from GPG)
-            if (in_array($fdOutput, $inputStreams)) {
-                $this->_debug('GPG output stream ready for reading');
-                $this->_debug(
-                    '=> about to read ' . self::CHUNK_SIZE .
-                    ' bytes from GPG output'
-                );
-
-                $chunk         = fread($fdOutput, self::CHUNK_SIZE);
-                $length        = self::_byteLength($chunk);
-                $outputBuffer .= $chunk;
-
-                $this->_debug('=> read ' . $length . ' bytes');
-            }
-
-            // write output (to PHP stream)
-            if (in_array($this->_output, $outputStreams)) {
-                $this->_debug('output stream is ready for data');
-
-                $chunk = self::_byteSubstring(
-                    $outputBuffer,
-                    0,
-                    self::CHUNK_SIZE
-                );
-
-                $length = self::_byteLength($chunk);
-
-                $this->_debug(
-                    '=> about to write ' . $length . ' bytes to output stream'
-                );
-
-                $length = fwrite($this->_output, $chunk, $length);
-
-                $this->_debug('=> wrote ' . $length . ' bytes');
-
-                $outputBuffer = self::_byteSubstring($outputBuffer, $length);
-            }
-
-            // read error (from GPG)
-            if (in_array($fdError, $inputStreams)) {
-                $this->_debug('GPG error stream ready for reading');
-                $this->_debug(
-                    '=> about to read ' . self::CHUNK_SIZE .
-                    ' bytes from GPG error'
-                );
-
-                $chunk        = fread($fdError, self::CHUNK_SIZE);
-                $length       = self::_byteLength($chunk);
-                $errorBuffer .= $chunk;
-
-                $this->_debug('=> read ' . $length . ' bytes');
-
-                // pass lines to error handlers
-                while (($pos = strpos($errorBuffer, PHP_EOL)) !== false) {
-                    $line = self::_byteSubstring($errorBuffer, 0, $pos);
-                    foreach ($this->_errorHandlers as $handler) {
-                        array_unshift($handler['args'], $line);
-                        call_user_func_array(
-                            $handler['callback'],
-                            $handler['args']
-                        );
-
-                        array_shift($handler['args']);
-                    }
-                    $errorBuffer = self::_byteSubString(
-                        $errorBuffer,
-                        $pos + self::_byteLength(PHP_EOL)
-                    );
-                }
-            }
-
-            // read status (from GPG)
-            if (in_array($fdStatus, $inputStreams)) {
-                $this->_debug('GPG status stream ready for reading');
-                $this->_debug(
-                    '=> about to read ' . self::CHUNK_SIZE .
-                    ' bytes from GPG status'
-                );
-
-                $chunk         = fread($fdStatus, self::CHUNK_SIZE);
-                $length        = self::_byteLength($chunk);
-                $statusBuffer .= $chunk;
-
-                $this->_debug('=> read ' . $length . ' bytes');
-
-                // pass lines to status handlers
-                while (($pos = strpos($statusBuffer, PHP_EOL)) !== false) {
-                    $line = self::_byteSubstring($statusBuffer, 0, $pos);
-                    // only pass lines beginning with magic prefix
-                    if (self::_byteSubstring($line, 0, 9) == '[GNUPG:] ') {
-                        $line = self::_byteSubstring($line, 9);
-                        foreach ($this->_statusHandlers as $handler) {
-                            array_unshift($handler['args'], $line);
-                            call_user_func_array(
-                                $handler['callback'],
-                                $handler['args']
-                            );
-
-                            array_shift($handler['args']);
-                        }
-                    }
-                    $statusBuffer = self::_byteSubString(
-                        $statusBuffer,
-                        $pos + self::_byteLength(PHP_EOL)
-                    );
-                }
-            }
-
-            // write command (to GPG)
-            if (in_array($fdCommand, $outputStreams)) {
-                $this->_debug('GPG is ready for command data');
-
-                // send commands
-                $chunk = self::_byteSubstring(
-                    $this->_commandBuffer,
-                    0,
-                    self::CHUNK_SIZE
-                );
-
-                $length = self::_byteLength($chunk);
-
-                $this->_debug(
-                    '=> about to write ' . $length . ' bytes to GPG command'
-                );
-
-                $length = fwrite($fdCommand, $chunk, $length);
-
-                $this->_debug('=> wrote ' . $length);
-
-                $this->_commandBuffer = self::_byteSubstring(
-                    $this->_commandBuffer,
-                    $length
-                );
-            }
-
-        } // end loop while streams are open
-
-        $this->_debug('END PROCESSING');
-    }
-
-    // }}}
-    // {{{ _openSubprocess()
-
-    /**
-     * Opens an internal GPG subprocess for the current operation
-     *
-     * Opens a GPG subprocess, then connects the subprocess to some pipes. Sets
-     * the private class property {@link Crypt_GPG_Engine::$_process} to
-     * the new subprocess.
-     *
-     * @return void
-     *
-     * @throws Crypt_GPG_OpenSubprocessException if the subprocess could not be
-     *         opened.
-     *
-     * @see Crypt_GPG_Engine::setOperation()
-     * @see Crypt_GPG_Engine::_closeSubprocess()
-     * @see Crypt_GPG_Engine::$_process
-     */
-    private function _openSubprocess()
-    {
-        $version = $this->getVersion();
-
-        $env = $_ENV;
-
-        // Newer versions of GnuPG return localized results. Crypt_GPG only
-        // works with English, so set the locale to 'C' for the subprocess.
-        $env['LC_ALL'] = 'C';
-
-        $commandLine = $this->_binary;
-
-        $defaultArguments = array(
-            '--status-fd ' . escapeshellarg(self::FD_STATUS),
-            '--command-fd ' . escapeshellarg(self::FD_COMMAND),
-            '--no-secmem-warning',
-            '--no-tty',
-            '--no-default-keyring', // ignored if keying files are not specified
-            '--no-options'          // prevent creation of ~/.gnupg directory
-        );
-
-        if (version_compare($version, '1.0.7', 'ge')) {
-            if (version_compare($version, '2.0.0', 'lt')) {
-                $defaultArguments[] = '--no-use-agent';
-            }
-            $defaultArguments[] = '--no-permission-warning';
-        }
-
-        if (version_compare($version, '1.4.2', 'ge')) {
-            $defaultArguments[] = '--exit-on-status-write-error';
-        }
-
-        if (version_compare($version, '1.3.2', 'ge')) {
-            $defaultArguments[] = '--trust-model always';
-        } else {
-            $defaultArguments[] = '--always-trust';
-        }
-
-        $arguments = array_merge($defaultArguments, $this->_arguments);
-
-        if ($this->_homedir) {
-            $arguments[] = '--homedir ' . escapeshellarg($this->_homedir);
-
-            // the random seed file makes subsequent actions faster so only
-            // disable it if we have to.
-            if (!is_writeable($this->_homedir)) {
-                $arguments[] = '--no-random-seed-file';
-            }
-        }
-
-        if ($this->_publicKeyring) {
-            $arguments[] = '--keyring ' . escapeshellarg($this->_publicKeyring);
-        }
-
-        if ($this->_privateKeyring) {
-            $arguments[] = '--secret-keyring ' .
-                escapeshellarg($this->_privateKeyring);
-        }
-
-        if ($this->_trustDb) {
-            $arguments[] = '--trustdb-name ' . escapeshellarg($this->_trustDb);
-        }
-
-        $commandLine .= ' ' . implode(' ', $arguments) . ' ' .
-            $this->_operation;
-
-        // Binary operations will not work on Windows with PHP < 5.2.6. This is
-        // in case stream_select() ever works on Windows.
-        $rb = (version_compare(PHP_VERSION, '5.2.6') < 0) ? 'r' : 'rb';
-        $wb = (version_compare(PHP_VERSION, '5.2.6') < 0) ? 'w' : 'wb';
-
-        $descriptorSpec = array(
-            self::FD_INPUT   => array('pipe', $rb), // stdin
-            self::FD_OUTPUT  => array('pipe', $wb), // stdout
-            self::FD_ERROR   => array('pipe', $wb), // stderr
-            self::FD_STATUS  => array('pipe', $wb), // status
-            self::FD_COMMAND => array('pipe', $rb), // command
-            self::FD_MESSAGE => array('pipe', $rb)  // message
-        );
-
-        $this->_debug('OPENING SUBPROCESS WITH THE FOLLOWING COMMAND:');
-        $this->_debug($commandLine);
-
-        $this->_process = proc_open(
-            $commandLine,
-            $descriptorSpec,
-            $this->_pipes,
-            null,
-            $env,
-            array('binary_pipes' => true)
-        );
-
-        if (!is_resource($this->_process)) {
-            throw new Crypt_GPG_OpenSubprocessException(
-                'Unable to open GPG subprocess.', 0, $commandLine);
-        }
-
-        $this->_openPipes = $this->_pipes;
-        $this->_errorCode = Crypt_GPG::ERROR_NONE;
-    }
-
-    // }}}
-    // {{{ _closeSubprocess()
-
-    /**
-     * Closes a the internal GPG subprocess
-     *
-     * Closes the internal GPG subprocess. Sets the private class property
-     * {@link Crypt_GPG_Engine::$_process} to null.
-     *
-     * @return void
-     *
-     * @see Crypt_GPG_Engine::_openSubprocess()
-     * @see Crypt_GPG_Engine::$_process
-     */
-    private function _closeSubprocess()
-    {
-        if (is_resource($this->_process)) {
-            $this->_debug('CLOSING SUBPROCESS');
-
-            // close remaining open pipes
-            foreach (array_keys($this->_openPipes) as $pipeNumber) {
-                $this->_closePipe($pipeNumber);
-            }
-
-            $exitCode = proc_close($this->_process);
-
-            if ($exitCode != 0) {
-                $this->_debug(
-                    '=> subprocess returned an unexpected exit code: ' .
-                    $exitCode
-                );
-
-                if ($this->_errorCode === Crypt_GPG::ERROR_NONE) {
-                    if ($this->_needPassphrase > 0) {
-                        $this->_errorCode = Crypt_GPG::ERROR_MISSING_PASSPHRASE;
-                    } else {
-                        $this->_errorCode = Crypt_GPG::ERROR_UNKNOWN;
-                    }
-                }
-            }
-
-            $this->_process = null;
-            $this->_pipes   = array();
-        }
-    }
-
-    // }}}
-    // {{{ _closePipe()
-
-    /**
-     * Closes an opened pipe used to communicate with the GPG subprocess
-     *
-     * If the pipe is already closed, it is ignored. If the pipe is open, it
-     * is flushed and then closed.
-     *
-     * @param integer $pipeNumber the file descriptor number of the pipe to
-     *                            close.
-     *
-     * @return void
-     */
-    private function _closePipe($pipeNumber)
-    {
-        $pipeNumber = intval($pipeNumber);
-        if (array_key_exists($pipeNumber, $this->_openPipes)) {
-            fflush($this->_openPipes[$pipeNumber]);
-            fclose($this->_openPipes[$pipeNumber]);
-            unset($this->_openPipes[$pipeNumber]);
-        }
-    }
-
-    // }}}
-    // {{{ _getBinary()
-
-    /**
-     * Gets the name of the GPG binary for the current operating system
-     *
-     * This method is called if the '<kbd>binary</kbd>' option is <i>not</i>
-     * specified when creating this driver.
-     *
-     * @return string the name of the GPG binary for the current operating
-     *                system. If no suitable binary could be found, an empty
-     *                string is returned.
-     */
-    private function _getBinary()
-    {
-        $binary = '';
-
-        if ($this->_isDarwin) {
-            $binaryFiles = array(
-                '/opt/local/bin/gpg', // MacPorts
-                '/usr/local/bin/gpg', // Mac GPG
-                '/sw/bin/gpg',        // Fink
-                '/usr/bin/gpg'
-            );
-        } else {
-            $binaryFiles = array(
-                '/usr/bin/gpg',
-                '/usr/local/bin/gpg'
-            );
-        }
-
-        foreach ($binaryFiles as $binaryFile) {
-            if (is_executable($binaryFile)) {
-                $binary = $binaryFile;
-                break;
-            }
-        }
-
-        return $binary;
-    }
-
-    // }}}
-    // {{{ _debug()
-
-    /**
-     * Displays debug text if debugging is turned on
-     *
-     * Debugging text is prepended with a debug identifier and echoed to stdout.
-     *
-     * @param string $text the debugging text to display.
-     *
-     * @return void
-     */
-    private function _debug($text)
-    {
-        if ($this->_debug) {
-            if (array_key_exists('SHELL', $_ENV)) {
-                foreach (explode(PHP_EOL, $text) as $line) {
-                    echo "Crypt_GPG DEBUG: ", $line, PHP_EOL;
-                }
-            } else {
-                // running on a web server, format debug output nicely
-                foreach (explode(PHP_EOL, $text) as $line) {
-                    echo "Crypt_GPG DEBUG: <strong>", $line,
-                        '</strong><br />', PHP_EOL;
-                }
-            }
-        }
-    }
-
-    // }}}
-    // {{{ _byteLength()
-
-    /**
-     * Gets the length of a string in bytes even if mbstring function
-     * overloading is turned on
-     *
-     * This is used for stream-based communication with the GPG subprocess.
-     *
-     * @param string $string the string for which to get the length.
-     *
-     * @return integer the length of the string in bytes.
-     *
-     * @see Crypt_GPG_Engine::$_mbStringOverload
-     */
-    private static function _byteLength($string)
-    {
-        if (self::$_mbStringOverload) {
-            return mb_strlen($string, '8bit');
-        }
-
-        return strlen((binary)$string);
-    }
-
-    // }}}
-    // {{{ _byteSubstring()
-
-    /**
-     * Gets the substring of a string in bytes even if mbstring function
-     * overloading is turned on
-     *
-     * This is used for stream-based communication with the GPG subprocess.
-     *
-     * @param string  $string the input string.
-     * @param integer $start  the starting point at which to get the substring.
-     * @param integer $length optional. The length of the substring.
-     *
-     * @return string the extracted part of the string. Unlike the default PHP
-     *                <kbd>substr()</kbd> function, the returned value is
-     *                always a string and never false.
-     *
-     * @see Crypt_GPG_Engine::$_mbStringOverload
-     */
-    private static function _byteSubstring($string, $start, $length = null)
-    {
-        if (self::$_mbStringOverload) {
-            if ($length === null) {
-                return mb_substr(
-                    $string,
-                    $start,
-                    self::_byteLength($string) - $start, '8bit'
-                );
-            }
-
-            return mb_substr($string, $start, $length, '8bit');
-        }
-
-        if ($length === null) {
-            return (string)substr((binary)$string, $start);
-        }
-
-        return (string)substr((binary)$string, $start, $length);
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
diff --git a/plugins/enigma/lib/Crypt/GPG/Exceptions.php b/plugins/enigma/lib/Crypt/GPG/Exceptions.php
deleted file mode 100644
index 744acf5..0000000
--- a/plugins/enigma/lib/Crypt/GPG/Exceptions.php
+++ /dev/null
@@ -1,473 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Various exception handling classes for Crypt_GPG
- *
- * Crypt_GPG provides an object oriented interface to GNU Privacy
- * Guard (GPG). It requires the GPG executable to be on the system.
- *
- * This file contains various exception classes used by the Crypt_GPG package.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @version   CVS: $Id: Exceptions.php 273745 2009-01-18 05:24:25Z gauthierm $
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-/**
- * PEAR Exception handler and base class
- */
-require_once 'PEAR/Exception.php';
-
-// {{{ class Crypt_GPG_Exception
-
-/**
- * An exception thrown by the Crypt_GPG package
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_Exception extends PEAR_Exception
-{
-}
-
-// }}}
-// {{{ class Crypt_GPG_FileException
-
-/**
- * An exception thrown when a file is used in ways it cannot be used
- *
- * For example, if an output file is specified and the file is not writeable, or
- * if an input file is specified and the file is not readable, this exception
- * is thrown.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2007-2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_FileException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The name of the file that caused this exception
-     *
-     * @var string
-     */
-    private $_filename = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_FileException
-     *
-     * @param string  $message  an error message.
-     * @param integer $code     a user defined error code.
-     * @param string  $filename the name of the file that caused this exception.
-     */
-    public function __construct($message, $code = 0, $filename = '')
-    {
-        $this->_filename = $filename;
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getFilename()
-
-    /**
-     * Returns the filename of the file that caused this exception
-     *
-     * @return string the filename of the file that caused this exception.
-     *
-     * @see Crypt_GPG_FileException::$_filename
-     */
-    public function getFilename()
-    {
-        return $this->_filename;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_OpenSubprocessException
-
-/**
- * An exception thrown when the GPG subprocess cannot be opened
- *
- * This exception is thrown when the {@link Crypt_GPG_Engine} tries to open a
- * new subprocess and fails.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_OpenSubprocessException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The command used to try to open the subprocess
-     *
-     * @var string
-     */
-    private $_command = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_OpenSubprocessException
-     *
-     * @param string  $message an error message.
-     * @param integer $code    a user defined error code.
-     * @param string  $command the command that was called to open the
-     *                         new subprocess.
-     *
-     * @see Crypt_GPG::_openSubprocess()
-     */
-    public function __construct($message, $code = 0, $command = '')
-    {
-        $this->_command = $command;
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getCommand()
-
-    /**
-     * Returns the contents of the internal _command property
-     *
-     * @return string the command used to open the subprocess.
-     *
-     * @see Crypt_GPG_OpenSubprocessException::$_command
-     */
-    public function getCommand()
-    {
-        return $this->_command;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_InvalidOperationException
-
-/**
- * An exception thrown when an invalid GPG operation is attempted
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_InvalidOperationException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The attempted operation
-     *
-     * @var string
-     */
-    private $_operation = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_OpenSubprocessException
-     *
-     * @param string  $message   an error message.
-     * @param integer $code      a user defined error code.
-     * @param string  $operation the operation.
-     */
-    public function __construct($message, $code = 0, $operation = '')
-    {
-        $this->_operation = $operation;
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getOperation()
-
-    /**
-     * Returns the contents of the internal _operation property
-     *
-     * @return string the attempted operation.
-     *
-     * @see Crypt_GPG_InvalidOperationException::$_operation
-     */
-    public function getOperation()
-    {
-        return $this->_operation;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_KeyNotFoundException
-
-/**
- * An exception thrown when Crypt_GPG fails to find the key for various
- * operations
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_KeyNotFoundException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The key identifier that was searched for
-     *
-     * @var string
-     */
-    private $_keyId = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_KeyNotFoundException
-     *
-     * @param string  $message an error message.
-     * @param integer $code    a user defined error code.
-     * @param string  $keyId   the key identifier of the key.
-     */
-    public function __construct($message, $code = 0, $keyId= '')
-    {
-        $this->_keyId = $keyId;
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getKeyId()
-
-    /**
-     * Gets the key identifier of the key that was not found
-     *
-     * @return string the key identifier of the key that was not found.
-     */
-    public function getKeyId()
-    {
-        return $this->_keyId;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_NoDataException
-
-/**
- * An exception thrown when Crypt_GPG cannot find valid data for various
- * operations
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2006 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_NoDataException extends Crypt_GPG_Exception
-{
-}
-
-// }}}
-// {{{ class Crypt_GPG_BadPassphraseException
-
-/**
- * An exception thrown when a required passphrase is incorrect or missing
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2006-2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_BadPassphraseException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * Keys for which the passhprase is missing
-     *
-     * This contains primary user ids indexed by sub-key id.
-     *
-     * @var array
-     */
-    private $_missingPassphrases = array();
-
-    /**
-     * Keys for which the passhprase is incorrect
-     *
-     * This contains primary user ids indexed by sub-key id.
-     *
-     * @var array
-     */
-    private $_badPassphrases = array();
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_BadPassphraseException
-     *
-     * @param string  $message            an error message.
-     * @param integer $code               a user defined error code.
-     * @param string  $badPassphrases     an array containing user ids of keys
-     *                                    for which the passphrase is incorrect.
-     * @param string  $missingPassphrases an array containing user ids of keys
-     *                                    for which the passphrase is missing.
-     */
-    public function __construct($message, $code = 0,
-        array $badPassphrases = array(), array $missingPassphrases = array()
-    ) {
-        $this->_badPassphrases     = $badPassphrases;
-        $this->_missingPassphrases = $missingPassphrases;
-
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getBadPassphrases()
-
-    /**
-     * Gets keys for which the passhprase is incorrect
-     *
-     * @return array an array of keys for which the passphrase is incorrect.
-     *               The array contains primary user ids indexed by the sub-key
-     *               id.
-     */
-    public function getBadPassphrases()
-    {
-        return $this->_badPassphrases;
-    }
-
-    // }}}
-    // {{{ getMissingPassphrases()
-
-    /**
-     * Gets keys for which the passhprase is missing 
-     *
-     * @return array an array of keys for which the passphrase is missing.
-     *               The array contains primary user ids indexed by the sub-key
-     *               id.
-     */
-    public function getMissingPassphrases()
-    {
-        return $this->_missingPassphrases;
-    }
-
-    // }}}
-}
-
-// }}}
-// {{{ class Crypt_GPG_DeletePrivateKeyException
-
-/**
- * An exception thrown when an attempt is made to delete public key that has an
- * associated private key on the keyring
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-class Crypt_GPG_DeletePrivateKeyException extends Crypt_GPG_Exception
-{
-    // {{{ private class properties
-
-    /**
-     * The key identifier the deletion attempt was made upon
-     *
-     * @var string
-     */
-    private $_keyId = '';
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new Crypt_GPG_DeletePrivateKeyException
-     *
-     * @param string  $message an error message.
-     * @param integer $code    a user defined error code.
-     * @param string  $keyId   the key identifier of the public key that was
-     *                         attempted to delete.
-     *
-     * @see Crypt_GPG::deletePublicKey()
-     */
-    public function __construct($message, $code = 0, $keyId = '')
-    {
-        $this->_keyId = $keyId;
-        parent::__construct($message, $code);
-    }
-
-    // }}}
-    // {{{ getKeyId()
-
-    /**
-     * Gets the key identifier of the key that was not found
-     *
-     * @return string the key identifier of the key that was not found.
-     */
-    public function getKeyId()
-    {
-        return $this->_keyId;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
diff --git a/plugins/enigma/lib/Crypt/GPG/Key.php b/plugins/enigma/lib/Crypt/GPG/Key.php
deleted file mode 100644
index 67a4b9c..0000000
--- a/plugins/enigma/lib/Crypt/GPG/Key.php
+++ /dev/null
@@ -1,223 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Contains a class representing GPG keys
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @version   CVS: $Id: Key.php 295621 2010-03-01 04:18:54Z gauthierm $
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-/**
- * Sub-key class definition
- */
-require_once 'Crypt/GPG/SubKey.php';
-
-/**
- * User id class definition
- */
-require_once 'Crypt/GPG/UserId.php';
-
-// {{{ class Crypt_GPG_Key
-
-/**
- * A data class for GPG key information
- *
- * This class is used to store the results of the {@link Crypt_GPG::getKeys()}
- * method.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @see       Crypt_GPG::getKeys()
- */
-class Crypt_GPG_Key
-{
-    // {{{ class properties
-
-    /**
-     * The user ids associated with this key
-     *
-     * This is an array of {@link Crypt_GPG_UserId} objects.
-     *
-     * @var array
-     *
-     * @see Crypt_GPG_Key::addUserId()
-     * @see Crypt_GPG_Key::getUserIds()
-     */
-    private $_userIds = array();
-
-    /**
-     * The subkeys of this key
-     *
-     * This is an array of {@link Crypt_GPG_SubKey} objects.
-     *
-     * @var array
-     *
-     * @see Crypt_GPG_Key::addSubKey()
-     * @see Crypt_GPG_Key::getSubKeys()
-     */
-    private $_subKeys = array();
-
-    // }}}
-    // {{{ getSubKeys()
-
-    /**
-     * Gets the sub-keys of this key
-     *
-     * @return array the sub-keys of this key.
-     *
-     * @see Crypt_GPG_Key::addSubKey()
-     */
-    public function getSubKeys()
-    {
-        return $this->_subKeys;
-    }
-
-    // }}}
-    // {{{ getUserIds()
-
-    /**
-     * Gets the user ids of this key
-     *
-     * @return array the user ids of this key.
-     *
-     * @see Crypt_GPG_Key::addUserId()
-     */
-    public function getUserIds()
-    {
-        return $this->_userIds;
-    }
-
-    // }}}
-    // {{{ getPrimaryKey()
-
-    /**
-     * Gets the primary sub-key of this key
-     *
-     * The primary key is the first added sub-key.
-     *
-     * @return Crypt_GPG_SubKey the primary sub-key of this key.
-     */
-    public function getPrimaryKey()
-    {
-        $primary_key = null;
-        if (count($this->_subKeys) > 0) {
-            $primary_key = $this->_subKeys[0];
-        }
-        return $primary_key;
-    }
-
-    // }}}
-    // {{{ canSign()
-
-    /**
-     * Gets whether or not this key can sign data
-     *
-     * This key can sign data if any sub-key of this key can sign data.
-     *
-     * @return boolean true if this key can sign data and false if this key
-     *                 cannot sign data.
-     */
-    public function canSign()
-    {
-        $canSign = false;
-        foreach ($this->_subKeys as $subKey) {
-            if ($subKey->canSign()) {
-                $canSign = true;
-                break;
-            }
-        }
-        return $canSign;
-    }
-
-    // }}}
-    // {{{ canEncrypt()
-
-    /**
-     * Gets whether or not this key can encrypt data
-     *
-     * This key can encrypt data if any sub-key of this key can encrypt data.
-     *
-     * @return boolean true if this key can encrypt data and false if this
-     *                 key cannot encrypt data.
-     */
-    public function canEncrypt()
-    {
-        $canEncrypt = false;
-        foreach ($this->_subKeys as $subKey) {
-            if ($subKey->canEncrypt()) {
-                $canEncrypt = true;
-                break;
-            }
-        }
-        return $canEncrypt;
-    }
-
-    // }}}
-    // {{{ addSubKey()
-
-    /**
-     * Adds a sub-key to this key
-     *
-     * The first added sub-key will be the primary key of this key.
-     *
-     * @param Crypt_GPG_SubKey $subKey the sub-key to add.
-     *
-     * @return Crypt_GPG_Key the current object, for fluent interface.
-     */
-    public function addSubKey(Crypt_GPG_SubKey $subKey)
-    {
-        $this->_subKeys[] = $subKey;
-        return $this;
-    }
-
-    // }}}
-    // {{{ addUserId()
-
-    /**
-     * Adds a user id to this key
-     *
-     * @param Crypt_GPG_UserId $userId the user id to add.
-     *
-     * @return Crypt_GPG_Key the current object, for fluent interface.
-     */
-    public function addUserId(Crypt_GPG_UserId $userId)
-    {
-        $this->_userIds[] = $userId;
-        return $this;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
diff --git a/plugins/enigma/lib/Crypt/GPG/Signature.php b/plugins/enigma/lib/Crypt/GPG/Signature.php
deleted file mode 100644
index 03ab44c..0000000
--- a/plugins/enigma/lib/Crypt/GPG/Signature.php
+++ /dev/null
@@ -1,428 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A class representing GPG signatures
- *
- * This file contains a data class representing a GPG signature.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @copyright 2005-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @version   CVS: $Id: Signature.php 302773 2010-08-25 14:16:28Z gauthierm $
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-/**
- * User id class definition
- */
-require_once 'Crypt/GPG/UserId.php';
-
-// {{{ class Crypt_GPG_Signature
-
-/**
- * A class for GPG signature information
- *
- * This class is used to store the results of the Crypt_GPG::verify() method.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2005-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @see       Crypt_GPG::verify()
- */
-class Crypt_GPG_Signature
-{
-    // {{{ class properties
-
-    /**
-     * A base64-encoded string containing a unique id for this signature if
-     * this signature has been verified as ok
-     *
-     * This id is used to prevent replay attacks and is not present for all
-     * types of signatures.
-     *
-     * @var string
-     */
-    private $_id = '';
-
-    /**
-     * The fingerprint of the key used to create the signature
-     *
-     * @var string
-     */
-    private $_keyFingerprint = '';
-
-    /**
-     * The id of the key used to create the signature
-     *
-     * @var string
-     */
-    private $_keyId = '';
-
-    /**
-     * The creation date of this signature
-     *
-     * This is a Unix timestamp.
-     *
-     * @var integer
-     */
-    private $_creationDate = 0;
-
-    /**
-     * The expiration date of the signature
-     *
-     * This is a Unix timestamp. If this signature does not expire, this will
-     * be zero.
-     *
-     * @var integer
-     */
-    private $_expirationDate = 0;
-
-    /**
-     * The user id associated with this signature
-     *
-     * @var Crypt_GPG_UserId
-     */
-    private $_userId = null;
-
-    /**
-     * Whether or not this signature is valid
-     *
-     * @var boolean
-     */
-    private $_isValid = false;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new signature
-     *
-     * Signatures can be initialized from an array of named values. Available
-     * names are:
-     *
-     * - <kbd>string  id</kbd>          - the unique id of this signature.
-     * - <kbd>string  fingerprint</kbd> - the fingerprint of the key used to
-     *                                    create the signature. The fingerprint
-     *                                    should not contain formatting
-     *                                    characters.
-     * - <kbd>string  keyId</kbd>       - the id of the key used to create the
-     *                                    the signature.
-     * - <kbd>integer creation</kbd>    - the date the signature was created.
-     *                                    This is a UNIX timestamp.
-     * - <kbd>integer expiration</kbd>  - the date the signature expired. This
-     *                                    is a UNIX timestamp. If the signature
-     *                                    does not expire, use 0.
-     * - <kbd>boolean valid</kbd>       - whether or not the signature is valid.
-     * - <kbd>string  userId</kbd>      - the user id associated with the
-     *                                    signature. This may also be a
-     *                                    {@link Crypt_GPG_UserId} object.
-     *
-     * @param Crypt_GPG_Signature|array $signature optional. Either an existing
-     *        signature object, which is copied; or an array of initial values.
-     */
-    public function __construct($signature = null)
-    {
-        // copy from object
-        if ($signature instanceof Crypt_GPG_Signature) {
-            $this->_id             = $signature->_id;
-            $this->_keyFingerprint = $signature->_keyFingerprint;
-            $this->_keyId          = $signature->_keyId;
-            $this->_creationDate   = $signature->_creationDate;
-            $this->_expirationDate = $signature->_expirationDate;
-            $this->_isValid        = $signature->_isValid;
-
-            if ($signature->_userId instanceof Crypt_GPG_UserId) {
-                $this->_userId = clone $signature->_userId;
-            } else {
-                $this->_userId = $signature->_userId;
-            }
-        }
-
-        // initialize from array
-        if (is_array($signature)) {
-            if (array_key_exists('id', $signature)) {
-                $this->setId($signature['id']);
-            }
-
-            if (array_key_exists('fingerprint', $signature)) {
-                $this->setKeyFingerprint($signature['fingerprint']);
-            }
-
-            if (array_key_exists('keyId', $signature)) {
-                $this->setKeyId($signature['keyId']);
-            }
-
-            if (array_key_exists('creation', $signature)) {
-                $this->setCreationDate($signature['creation']);
-            }
-
-            if (array_key_exists('expiration', $signature)) {
-                $this->setExpirationDate($signature['expiration']);
-            }
-
-            if (array_key_exists('valid', $signature)) {
-                $this->setValid($signature['valid']);
-            }
-
-            if (array_key_exists('userId', $signature)) {
-                $userId = new Crypt_GPG_UserId($signature['userId']);
-                $this->setUserId($userId);
-            }
-        }
-    }
-
-    // }}}
-    // {{{ getId()
-
-    /**
-     * Gets the id of this signature
-     *
-     * @return string a base64-encoded string containing a unique id for this
-     *                signature. This id is used to prevent replay attacks and
-     *                is not present for all types of signatures.
-     */
-    public function getId()
-    {
-        return $this->_id;
-    }
-
-    // }}}
-    // {{{ getKeyFingerprint()
-
-    /**
-     * Gets the fingerprint of the key used to create this signature
-     *
-     * @return string the fingerprint of the key used to create this signature.
-     */
-    public function getKeyFingerprint()
-    {
-        return $this->_keyFingerprint;
-    }
-
-    // }}}
-    // {{{ getKeyId()
-
-    /**
-     * Gets the id of the key used to create this signature
-     *
-     * Whereas the fingerprint of the signing key may not always be available
-     * (for example if the signature is bad), the id should always be
-     * available.
-     *
-     * @return string the id of the key used to create this signature.
-     */
-    public function getKeyId()
-    {
-        return $this->_keyId;
-    }
-
-    // }}}
-    // {{{ getCreationDate()
-
-    /**
-     * Gets the creation date of this signature
-     *
-     * @return integer the creation date of this signature. This is a Unix
-     *                 timestamp.
-     */
-    public function getCreationDate()
-    {
-        return $this->_creationDate;
-    }
-
-    // }}}
-    // {{{ getExpirationDate()
-
-    /**
-     * Gets the expiration date of the signature
-     *
-     * @return integer the expiration date of this signature. This is a Unix
-     *                 timestamp. If this signature does not expire, this will
-     *                 be zero.
-     */
-    public function getExpirationDate()
-    {
-        return $this->_expirationDate;
-    }
-
-    // }}}
-    // {{{ getUserId()
-
-    /**
-     * Gets the user id associated with this signature
-     *
-     * @return Crypt_GPG_UserId the user id associated with this signature.
-     */
-    public function getUserId()
-    {
-        return $this->_userId;
-    }
-
-    // }}}
-    // {{{ isValid()
-
-    /**
-     * Gets whether or no this signature is valid
-     *
-     * @return boolean true if this signature is valid and false if it is not.
-     */
-    public function isValid()
-    {
-        return $this->_isValid;
-    }
-
-    // }}}
-    // {{{ setId()
-
-    /**
-     * Sets the id of this signature
-     *
-     * @param string $id a base64-encoded string containing a unique id for
-     *                   this signature.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     *
-     * @see Crypt_GPG_Signature::getId()
-     */
-    public function setId($id)
-    {
-        $this->_id = strval($id);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setKeyFingerprint()
-
-    /**
-     * Sets the key fingerprint of this signature
-     *
-     * @param string $fingerprint the key fingerprint of this signature. This
-     *                            is the fingerprint of the primary key used to
-     *                            create this signature.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setKeyFingerprint($fingerprint)
-    {
-        $this->_keyFingerprint = strval($fingerprint);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setKeyId()
-
-    /**
-     * Sets the key id of this signature
-     *
-     * @param string $id the key id of this signature. This is the id of the
-     *                   primary key used to create this signature.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setKeyId($id)
-    {
-        $this->_keyId = strval($id);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setCreationDate()
-
-    /**
-     * Sets the creation date of this signature
-     *
-     * @param integer $creationDate the creation date of this signature. This
-     *                              is a Unix timestamp.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setCreationDate($creationDate)
-    {
-        $this->_creationDate = intval($creationDate);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setExpirationDate()
-
-    /**
-     * Sets the expiration date of this signature
-     *
-     * @param integer $expirationDate the expiration date of this signature.
-     *                                This is a Unix timestamp. Specify zero if
-     *                                this signature does not expire.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setExpirationDate($expirationDate)
-    {
-        $this->_expirationDate = intval($expirationDate);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setUserId()
-
-    /**
-     * Sets the user id associated with this signature
-     *
-     * @param Crypt_GPG_UserId $userId the user id associated with this
-     *                                 signature.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setUserId(Crypt_GPG_UserId $userId)
-    {
-        $this->_userId = $userId;
-        return $this;
-    }
-
-    // }}}
-    // {{{ setValid()
-
-    /**
-     * Sets whether or not this signature is valid
-     *
-     * @param boolean $isValid true if this signature is valid and false if it
-     *                         is not.
-     *
-     * @return Crypt_GPG_Signature the current object, for fluent interface.
-     */
-    public function setValid($isValid)
-    {
-        $this->_isValid = ($isValid) ? true : false;
-        return $this;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
diff --git a/plugins/enigma/lib/Crypt/GPG/SubKey.php b/plugins/enigma/lib/Crypt/GPG/SubKey.php
deleted file mode 100644
index b6316e9..0000000
--- a/plugins/enigma/lib/Crypt/GPG/SubKey.php
+++ /dev/null
@@ -1,649 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Contains a class representing GPG sub-keys and constants for GPG algorithms
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @copyright 2005-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @version   CVS: $Id: SubKey.php 302768 2010-08-25 13:45:52Z gauthierm $
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-// {{{ class Crypt_GPG_SubKey
-
-/**
- * A class for GPG sub-key information
- *
- * This class is used to store the results of the {@link Crypt_GPG::getKeys()}
- * method. Sub-key objects are members of a {@link Crypt_GPG_Key} object.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @author    Nathan Fredrickson <nathan@silverorange.com>
- * @copyright 2005-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @see       Crypt_GPG::getKeys()
- * @see       Crypt_GPG_Key::getSubKeys()
- */
-class Crypt_GPG_SubKey
-{
-    // {{{ class constants
-
-    /**
-     * RSA encryption algorithm.
-     */
-    const ALGORITHM_RSA = 1;
-
-    /**
-     * Elgamal encryption algorithm (encryption only).
-     */
-    const ALGORITHM_ELGAMAL_ENC = 16;
-
-    /**
-     * DSA encryption algorithm (sometimes called DH, sign only).
-     */
-    const ALGORITHM_DSA = 17;
-
-    /**
-     * Elgamal encryption algorithm (signage and encryption - should not be
-     * used).
-     */
-    const ALGORITHM_ELGAMAL_ENC_SGN = 20;
-
-    // }}}
-    // {{{ class properties
-
-    /**
-     * The id of this sub-key
-     *
-     * @var string
-     */
-    private $_id = '';
-
-    /**
-     * The algorithm used to create this sub-key
-     *
-     * The value is one of the Crypt_GPG_SubKey::ALGORITHM_* constants.
-     *
-     * @var integer
-     */
-    private $_algorithm = 0;
-
-    /**
-     * The fingerprint of this sub-key
-     *
-     * @var string
-     */
-    private $_fingerprint = '';
-
-    /**
-     * Length of this sub-key in bits
-     *
-     * @var integer
-     */
-    private $_length = 0;
-
-    /**
-     * Date this sub-key was created
-     *
-     * This is a Unix timestamp.
-     *
-     * @var integer
-     */
-    private $_creationDate = 0;
-
-    /**
-     * Date this sub-key expires
-     *
-     * This is a Unix timestamp. If this sub-key does not expire, this will be
-     * zero.
-     *
-     * @var integer
-     */
-    private $_expirationDate = 0;
-
-    /**
-     * Whether or not this sub-key can sign data
-     *
-     * @var boolean
-     */
-    private $_canSign = false;
-
-    /**
-     * Whether or not this sub-key can encrypt data
-     *
-     * @var boolean
-     */
-    private $_canEncrypt = false;
-
-    /**
-     * Whether or not the private key for this sub-key exists in the keyring
-     *
-     * @var boolean
-     */
-    private $_hasPrivate = false;
-
-    /**
-     * Whether or not this sub-key is revoked
-     *
-     * @var boolean
-     */
-    private $_isRevoked = false;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new sub-key object
-     *
-     * Sub-keys can be initialized from an array of named values. Available
-     * names are:
-     *
-     * - <kbd>string  id</kbd>          - the key id of the sub-key.
-     * - <kbd>integer algorithm</kbd>   - the encryption algorithm of the
-     *                                    sub-key.
-     * - <kbd>string  fingerprint</kbd> - the fingerprint of the sub-key. The
-     *                                    fingerprint should not contain
-     *                                    formatting characters.
-     * - <kbd>integer length</kbd>      - the length of the sub-key in bits.
-     * - <kbd>integer creation</kbd>    - the date the sub-key was created.
-     *                                    This is a UNIX timestamp.
-     * - <kbd>integer expiration</kbd>  - the date the sub-key expires. This
-     *                                    is a UNIX timestamp. If the sub-key
-     *                                    does not expire, use 0.
-     * - <kbd>boolean canSign</kbd>     - whether or not the sub-key can be
-     *                                    used to sign data.
-     * - <kbd>boolean canEncrypt</kbd>  - whether or not the sub-key can be
-     *                                    used to encrypt data.
-     * - <kbd>boolean hasPrivate</kbd>  - whether or not the private key for
-     *                                    the sub-key exists in the keyring.
-     * - <kbd>boolean isRevoked</kbd>   - whether or not this sub-key is
-     *                                    revoked.
-     *
-     * @param Crypt_GPG_SubKey|string|array $key optional. Either an existing
-     *        sub-key object, which is copied; a sub-key string, which is
-     *        parsed; or an array of initial values.
-     */
-    public function __construct($key = null)
-    {
-        // parse from string
-        if (is_string($key)) {
-            $key = self::parse($key);
-        }
-
-        // copy from object
-        if ($key instanceof Crypt_GPG_SubKey) {
-            $this->_id             = $key->_id;
-            $this->_algorithm      = $key->_algorithm;
-            $this->_fingerprint    = $key->_fingerprint;
-            $this->_length         = $key->_length;
-            $this->_creationDate   = $key->_creationDate;
-            $this->_expirationDate = $key->_expirationDate;
-            $this->_canSign        = $key->_canSign;
-            $this->_canEncrypt     = $key->_canEncrypt;
-            $this->_hasPrivate     = $key->_hasPrivate;
-            $this->_isRevoked      = $key->_isRevoked;
-        }
-
-        // initialize from array
-        if (is_array($key)) {
-            if (array_key_exists('id', $key)) {
-                $this->setId($key['id']);
-            }
-
-            if (array_key_exists('algorithm', $key)) {
-                $this->setAlgorithm($key['algorithm']);
-            }
-
-            if (array_key_exists('fingerprint', $key)) {
-                $this->setFingerprint($key['fingerprint']);
-            }
-
-            if (array_key_exists('length', $key)) {
-                $this->setLength($key['length']);
-            }
-
-            if (array_key_exists('creation', $key)) {
-                $this->setCreationDate($key['creation']);
-            }
-
-            if (array_key_exists('expiration', $key)) {
-                $this->setExpirationDate($key['expiration']);
-            }
-
-            if (array_key_exists('canSign', $key)) {
-                $this->setCanSign($key['canSign']);
-            }
-
-            if (array_key_exists('canEncrypt', $key)) {
-                $this->setCanEncrypt($key['canEncrypt']);
-            }
-
-            if (array_key_exists('hasPrivate', $key)) {
-                $this->setHasPrivate($key['hasPrivate']);
-            }
-
-            if (array_key_exists('isRevoked', $key)) {
-                $this->setRevoked($key['isRevoked']);
-            }
-        }
-    }
-
-    // }}}
-    // {{{ getId()
-
-    /**
-     * Gets the id of this sub-key
-     *
-     * @return string the id of this sub-key.
-     */
-    public function getId()
-    {
-        return $this->_id;
-    }
-
-    // }}}
-    // {{{ getAlgorithm()
-
-    /**
-     * Gets the algorithm used by this sub-key
-     *
-     * The algorithm should be one of the Crypt_GPG_SubKey::ALGORITHM_*
-     * constants.
-     *
-     * @return integer the algorithm used by this sub-key.
-     */
-    public function getAlgorithm()
-    {
-        return $this->_algorithm;
-    }
-
-    // }}}
-    // {{{ getCreationDate()
-
-    /**
-     * Gets the creation date of this sub-key
-     *
-     * This is a Unix timestamp.
-     *
-     * @return integer the creation date of this sub-key.
-     */
-    public function getCreationDate()
-    {
-        return $this->_creationDate;
-    }
-
-    // }}}
-    // {{{ getExpirationDate()
-
-    /**
-     * Gets the date this sub-key expires
-     *
-     * This is a Unix timestamp. If this sub-key does not expire, this will be
-     * zero.
-     *
-     * @return integer the date this sub-key expires.
-     */
-    public function getExpirationDate()
-    {
-        return $this->_expirationDate;
-    }
-
-    // }}}
-    // {{{ getFingerprint()
-
-    /**
-     * Gets the fingerprint of this sub-key
-     *
-     * @return string the fingerprint of this sub-key.
-     */
-    public function getFingerprint()
-    {
-        return $this->_fingerprint;
-    }
-
-    // }}}
-    // {{{ getLength()
-
-    /**
-     * Gets the length of this sub-key in bits
-     *
-     * @return integer the length of this sub-key in bits.
-     */
-    public function getLength()
-    {
-        return $this->_length;
-    }
-
-    // }}}
-    // {{{ canSign()
-
-    /**
-     * Gets whether or not this sub-key can sign data
-     *
-     * @return boolean true if this sub-key can sign data and false if this
-     *                 sub-key can not sign data.
-     */
-    public function canSign()
-    {
-        return $this->_canSign;
-    }
-
-    // }}}
-    // {{{ canEncrypt()
-
-    /**
-     * Gets whether or not this sub-key can encrypt data
-     *
-     * @return boolean true if this sub-key can encrypt data and false if this
-     *                 sub-key can not encrypt data.
-     */
-    public function canEncrypt()
-    {
-        return $this->_canEncrypt;
-    }
-
-    // }}}
-    // {{{ hasPrivate()
-
-    /**
-     * Gets whether or not the private key for this sub-key exists in the
-     * keyring
-     *
-     * @return boolean true the private key for this sub-key exists in the
-     *                 keyring and false if it does not.
-     */
-    public function hasPrivate()
-    {
-        return $this->_hasPrivate;
-    }
-
-    // }}}
-    // {{{ isRevoked()
-
-    /**
-     * Gets whether or not this sub-key is revoked
-     *
-     * @return boolean true if this sub-key is revoked and false if it is not.
-     */
-    public function isRevoked()
-    {
-        return $this->_isRevoked;
-    }
-
-    // }}}
-    // {{{ setCreationDate()
-
-    /**
-     * Sets the creation date of this sub-key
-     *
-     * The creation date is a Unix timestamp.
-     *
-     * @param integer $creationDate the creation date of this sub-key.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setCreationDate($creationDate)
-    {
-        $this->_creationDate = intval($creationDate);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setExpirationDate()
-
-    /**
-     * Sets the expiration date of this sub-key
-     *
-     * The expiration date is a Unix timestamp. Specify zero if this sub-key
-     * does not expire.
-     *
-     * @param integer $expirationDate the expiration date of this sub-key.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setExpirationDate($expirationDate)
-    {
-        $this->_expirationDate = intval($expirationDate);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setId()
-
-    /**
-     * Sets the id of this sub-key
-     *
-     * @param string $id the id of this sub-key.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setId($id)
-    {
-        $this->_id = strval($id);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setAlgorithm()
-
-    /**
-     * Sets the algorithm used by this sub-key
-     *
-     * @param integer $algorithm the algorithm used by this sub-key.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setAlgorithm($algorithm)
-    {
-        $this->_algorithm = intval($algorithm);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setFingerprint()
-
-    /**
-     * Sets the fingerprint of this sub-key
-     *
-     * @param string $fingerprint the fingerprint of this sub-key.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setFingerprint($fingerprint)
-    {
-        $this->_fingerprint = strval($fingerprint);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setLength()
-
-    /**
-     * Sets the length of this sub-key in bits
-     *
-     * @param integer $length the length of this sub-key in bits.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setLength($length)
-    {
-        $this->_length = intval($length);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setCanSign()
-
-    /**
-     * Sets whether of not this sub-key can sign data
-     *
-     * @param boolean $canSign true if this sub-key can sign data and false if
-     *                         it can not.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setCanSign($canSign)
-    {
-        $this->_canSign = ($canSign) ? true : false;
-        return $this;
-    }
-
-    // }}}
-    // {{{ setCanEncrypt()
-
-    /**
-     * Sets whether of not this sub-key can encrypt data
-     *
-     * @param boolean $canEncrypt true if this sub-key can encrypt data and
-     *                            false if it can not.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setCanEncrypt($canEncrypt)
-    {
-        $this->_canEncrypt = ($canEncrypt) ? true : false;
-        return $this;
-    }
-
-    // }}}
-    // {{{ setHasPrivate()
-
-    /**
-     * Sets whether of not the private key for this sub-key exists in the
-     * keyring
-     *
-     * @param boolean $hasPrivate true if the private key for this sub-key
-     *                            exists in the keyring and false if it does
-     *                            not.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setHasPrivate($hasPrivate)
-    {
-        $this->_hasPrivate = ($hasPrivate) ? true : false;
-        return $this;
-    }
-
-    // }}}
-    // {{{ setRevoked()
-
-    /**
-     * Sets whether or not this sub-key is revoked
-     *
-     * @param boolean $isRevoked whether or not this sub-key is revoked.
-     *
-     * @return Crypt_GPG_SubKey the current object, for fluent interface.
-     */
-    public function setRevoked($isRevoked)
-    {
-        $this->_isRevoked = ($isRevoked) ? true : false;
-        return $this;
-    }
-
-    // }}}
-    // {{{ parse()
-
-    /**
-     * Parses a sub-key object from a sub-key string
-     *
-     * See <b>doc/DETAILS</b> in the
-     * {@link http://www.gnupg.org/download/ GPG distribution} for information
-     * on how the sub-key string is parsed.
-     *
-     * @param string $string the string containing the sub-key.
-     *
-     * @return Crypt_GPG_SubKey the sub-key object parsed from the string.
-     */
-    public static function parse($string)
-    {
-        $tokens = explode(':', $string);
-
-        $subKey = new Crypt_GPG_SubKey();
-
-        $subKey->setId($tokens[4]);
-        $subKey->setLength($tokens[2]);
-        $subKey->setAlgorithm($tokens[3]);
-        $subKey->setCreationDate(self::_parseDate($tokens[5]));
-        $subKey->setExpirationDate(self::_parseDate($tokens[6]));
-
-        if ($tokens[1] == 'r') {
-            $subKey->setRevoked(true);
-        }
-
-        if (strpos($tokens[11], 's') !== false) {
-            $subKey->setCanSign(true);
-        }
-
-        if (strpos($tokens[11], 'e') !== false) {
-            $subKey->setCanEncrypt(true);
-        }
-
-        return $subKey;
-    }
-
-    // }}}
-    // {{{ _parseDate()
-
-    /**
-     * Parses a date string as provided by GPG into a UNIX timestamp
-     *
-     * @param string $string the date string.
-     *
-     * @return integer the UNIX timestamp corresponding to the provided date
-     *                 string.
-     */
-    private static function _parseDate($string)
-    {
-        if ($string == '') {
-            $timestamp = 0;
-        } else {
-            // all times are in UTC according to GPG documentation
-            $timeZone = new DateTimeZone('UTC');
-
-            if (strpos($string, 'T') === false) {
-                // interpret as UNIX timestamp
-                $string = '@' . $string;
-            }
-
-            $date = new DateTime($string, $timeZone);
-
-            // convert to UNIX timestamp
-            $timestamp = intval($date->format('U'));
-        }
-
-        return $timestamp;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
diff --git a/plugins/enigma/lib/Crypt/GPG/UserId.php b/plugins/enigma/lib/Crypt/GPG/UserId.php
deleted file mode 100644
index 0443570..0000000
--- a/plugins/enigma/lib/Crypt/GPG/UserId.php
+++ /dev/null
@@ -1,373 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Contains a data class representing a GPG user id
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @version   CVS: $Id: UserId.php 295621 2010-03-01 04:18:54Z gauthierm $
- * @link      http://pear.php.net/package/Crypt_GPG
- */
-
-// {{{ class Crypt_GPG_UserId
-
-/**
- * A class for GPG user id information
- *
- * This class is used to store the results of the {@link Crypt_GPG::getKeys()}
- * method. User id objects are members of a {@link Crypt_GPG_Key} object.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008-2010 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @see       Crypt_GPG::getKeys()
- * @see       Crypt_GPG_Key::getUserIds()
- */
-class Crypt_GPG_UserId
-{
-    // {{{ class properties
-
-    /**
-     * The name field of this user id
-     *
-     * @var string
-     */
-    private $_name = '';
-
-    /**
-     * The comment field of this user id
-     *
-     * @var string
-     */
-    private $_comment = '';
-
-    /**
-     * The email field of this user id
-     *
-     * @var string
-     */
-    private $_email = '';
-
-    /**
-     * Whether or not this user id is revoked
-     *
-     * @var boolean
-     */
-    private $_isRevoked = false;
-
-    /**
-     * Whether or not this user id is valid
-     *
-     * @var boolean
-     */
-    private $_isValid = true;
-
-    // }}}
-    // {{{ __construct()
-
-    /**
-     * Creates a new user id
-     *
-     * User ids can be initialized from an array of named values. Available
-     * names are:
-     *
-     * - <kbd>string  name</kbd>    - the name field of the user id.
-     * - <kbd>string  comment</kbd> - the comment field of the user id.
-     * - <kbd>string  email</kbd>   - the email field of the user id.
-     * - <kbd>boolean valid</kbd>   - whether or not the user id is valid.
-     * - <kbd>boolean revoked</kbd> - whether or not the user id is revoked.
-     *
-     * @param Crypt_GPG_UserId|string|array $userId optional. Either an
-     *        existing user id object, which is copied; a user id string, which
-     *        is parsed; or an array of initial values.
-     */
-    public function __construct($userId = null)
-    {
-        // parse from string
-        if (is_string($userId)) {
-            $userId = self::parse($userId);
-        }
-
-        // copy from object
-        if ($userId instanceof Crypt_GPG_UserId) {
-            $this->_name      = $userId->_name;
-            $this->_comment   = $userId->_comment;
-            $this->_email     = $userId->_email;
-            $this->_isRevoked = $userId->_isRevoked;
-            $this->_isValid   = $userId->_isValid;
-        }
-
-        // initialize from array
-        if (is_array($userId)) {
-            if (array_key_exists('name', $userId)) {
-                $this->setName($userId['name']);
-            }
-
-            if (array_key_exists('comment', $userId)) {
-                $this->setComment($userId['comment']);
-            }
-
-            if (array_key_exists('email', $userId)) {
-                $this->setEmail($userId['email']);
-            }
-
-            if (array_key_exists('revoked', $userId)) {
-                $this->setRevoked($userId['revoked']);
-            }
-
-            if (array_key_exists('valid', $userId)) {
-                $this->setValid($userId['valid']);
-            }
-        }
-    }
-
-    // }}}
-    // {{{ getName()
-
-    /**
-     * Gets the name field of this user id
-     *
-     * @return string the name field of this user id.
-     */
-    public function getName()
-    {
-        return $this->_name;
-    }
-
-    // }}}
-    // {{{ getComment()
-
-    /**
-     * Gets the comments field of this user id
-     *
-     * @return string the comments field of this user id.
-     */
-    public function getComment()
-    {
-        return $this->_comment;
-    }
-
-    // }}}
-    // {{{ getEmail()
-
-    /**
-     * Gets the email field of this user id
-     *
-     * @return string the email field of this user id.
-     */
-    public function getEmail()
-    {
-        return $this->_email;
-    }
-
-    // }}}
-    // {{{ isRevoked()
-
-    /**
-     * Gets whether or not this user id is revoked
-     *
-     * @return boolean true if this user id is revoked and false if it is not.
-     */
-    public function isRevoked()
-    {
-        return $this->_isRevoked;
-    }
-
-    // }}}
-    // {{{ isValid()
-
-    /**
-     * Gets whether or not this user id is valid
-     *
-     * @return boolean true if this user id is valid and false if it is not.
-     */
-    public function isValid()
-    {
-        return $this->_isValid;
-    }
-
-    // }}}
-    // {{{ __toString()
-
-    /**
-     * Gets a string representation of this user id
-     *
-     * The string is formatted as:
-     * <b><kbd>name (comment) <email-address></kbd></b>.
-     *
-     * @return string a string representation of this user id.
-     */
-    public function __toString()
-    {
-        $components = array();
-
-        if (strlen($this->_name) > 0) {
-            $components[] = $this->_name;
-        }
-
-        if (strlen($this->_comment) > 0) {
-            $components[] = '(' . $this->_comment . ')';
-        }
-
-        if (strlen($this->_email) > 0) {
-            $components[] = '<' . $this->_email. '>';
-        }
-
-        return implode(' ', $components);
-    }
-
-    // }}}
-    // {{{ setName()
-
-    /**
-     * Sets the name field of this user id
-     *
-     * @param string $name the name field of this user id.
-     *
-     * @return Crypt_GPG_UserId the current object, for fluent interface.
-     */
-    public function setName($name)
-    {
-        $this->_name = strval($name);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setComment()
-
-    /**
-     * Sets the comment field of this user id
-     *
-     * @param string $comment the comment field of this user id.
-     *
-     * @return Crypt_GPG_UserId the current object, for fluent interface.
-     */
-    public function setComment($comment)
-    {
-        $this->_comment = strval($comment);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setEmail()
-
-    /**
-     * Sets the email field of this user id
-     *
-     * @param string $email the email field of this user id.
-     *
-     * @return Crypt_GPG_UserId the current object, for fluent interface.
-     */
-    public function setEmail($email)
-    {
-        $this->_email = strval($email);
-        return $this;
-    }
-
-    // }}}
-    // {{{ setRevoked()
-
-    /**
-     * Sets whether or not this user id is revoked
-     *
-     * @param boolean $isRevoked whether or not this user id is revoked.
-     *
-     * @return Crypt_GPG_UserId the current object, for fluent interface.
-     */
-    public function setRevoked($isRevoked)
-    {
-        $this->_isRevoked = ($isRevoked) ? true : false;
-        return $this;
-    }
-
-    // }}}
-    // {{{ setValid()
-
-    /**
-     * Sets whether or not this user id is valid
-     *
-     * @param boolean $isValid whether or not this user id is valid.
-     *
-     * @return Crypt_GPG_UserId the current object, for fluent interface.
-     */
-    public function setValid($isValid)
-    {
-        $this->_isValid = ($isValid) ? true : false;
-        return $this;
-    }
-
-    // }}}
-    // {{{ parse()
-
-    /**
-     * Parses a user id object from a user id string
-     *
-     * A user id string is of the form:
-     * <b><kbd>name (comment) <email-address></kbd></b> with the <i>comment</i>
-     * and <i>email-address</i> fields being optional.
-     *
-     * @param string $string the user id string to parse.
-     *
-     * @return Crypt_GPG_UserId the user id object parsed from the string.
-     */
-    public static function parse($string)
-    {
-        $userId  = new Crypt_GPG_UserId();
-        $email   = '';
-        $comment = '';
-
-        // get email address from end of string if it exists
-        $matches = array();
-        if (preg_match('/^(.+?) <([^>]+)>$/', $string, $matches) === 1) {
-            $string = $matches[1];
-            $email  = $matches[2];
-        }
-
-        // get comment from end of string if it exists
-        $matches = array();
-        if (preg_match('/^(.+?) \(([^\)]+)\)$/', $string, $matches) === 1) {
-            $string  = $matches[1];
-            $comment = $matches[2];
-        }
-
-        $name = $string;
-
-        $userId->setName($name);
-        $userId->setComment($comment);
-        $userId->setEmail($email);
-
-        return $userId;
-    }
-
-    // }}}
-}
-
-// }}}
-
-?>
diff --git a/plugins/enigma/lib/Crypt/GPG/VerifyStatusHandler.php b/plugins/enigma/lib/Crypt/GPG/VerifyStatusHandler.php
deleted file mode 100644
index 083bd30..0000000
--- a/plugins/enigma/lib/Crypt/GPG/VerifyStatusHandler.php
+++ /dev/null
@@ -1,216 +0,0 @@
-<?php
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Crypt_GPG is a package to use GPG from PHP
- *
- * This file contains an object that handles GPG's status output for the verify
- * operation.
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @version   CVS: $Id: VerifyStatusHandler.php 302908 2010-08-31 03:56:54Z gauthierm $
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-
-/**
- * Signature object class definition
- */
-require_once 'Crypt/GPG/Signature.php';
-
-/**
- * Status line handler for the verify operation
- *
- * This class is used internally by Crypt_GPG and does not need be used
- * directly. See the {@link Crypt_GPG} class for end-user API.
- *
- * This class is responsible for building signature objects that are returned
- * by the {@link Crypt_GPG::verify()} method. See <b>doc/DETAILS</b> in the
- * {@link http://www.gnupg.org/download/ GPG distribution} for detailed
- * information on GPG's status output for the verify operation.
- *
- * @category  Encryption
- * @package   Crypt_GPG
- * @author    Michael Gauthier <mike@silverorange.com>
- * @copyright 2008 silverorange
- * @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
- * @link      http://pear.php.net/package/Crypt_GPG
- * @link      http://www.gnupg.org/
- */
-class Crypt_GPG_VerifyStatusHandler
-{
-    // {{{ protected properties
-
-    /**
-     * The current signature id
-     *
-     * Ths signature id is emitted by GPG before the new signature line so we
-     * must remember it temporarily.
-     *
-     * @var string
-     */
-    protected $signatureId = '';
-
-    /**
-     * List of parsed {@link Crypt_GPG_Signature} objects
-     *
-     * @var array
-     */
-    protected $signatures = array();
-
-    /**
-     * Array index of the current signature
-     *
-     * @var integer
-     */
-    protected $index = -1;
-
-    // }}}
-    // {{{ handle()
-
-    /**
-     * Handles a status line
-     *
-     * @param string $line the status line to handle.
-     *
-     * @return void
-     */
-    public function handle($line)
-    {
-        $tokens = explode(' ', $line);
-        switch ($tokens[0]) {
-        case 'GOODSIG':
-        case 'EXPSIG':
-        case 'EXPKEYSIG':
-        case 'REVKEYSIG':
-        case 'BADSIG':
-            $signature = new Crypt_GPG_Signature();
-
-            // if there was a signature id, set it on the new signature
-            if ($this->signatureId != '') {
-                $signature->setId($this->signatureId);
-                $this->signatureId = '';
-            }
-
-            // Detect whether fingerprint or key id was returned and set
-            // signature values appropriately. Key ids are strings of either
-            // 16 or 8 hexadecimal characters. Fingerprints are strings of 40
-            // hexadecimal characters. The key id is the last 16 characters of
-            // the key fingerprint.
-            if (strlen($tokens[1]) > 16) {
-                $signature->setKeyFingerprint($tokens[1]);
-                $signature->setKeyId(substr($tokens[1], -16));
-            } else {
-                $signature->setKeyId($tokens[1]);
-            }
-
-            // get user id string
-            $string = implode(' ', array_splice($tokens, 2));
-            $string = rawurldecode($string);
-
-            $signature->setUserId(Crypt_GPG_UserId::parse($string));
-
-            $this->index++;
-            $this->signatures[$this->index] = $signature;
-            break;
-
-        case 'ERRSIG':
-            $signature = new Crypt_GPG_Signature();
-
-            // if there was a signature id, set it on the new signature
-            if ($this->signatureId != '') {
-                $signature->setId($this->signatureId);
-                $this->signatureId = '';
-            }
-
-            // Detect whether fingerprint or key id was returned and set
-            // signature values appropriately. Key ids are strings of either
-            // 16 or 8 hexadecimal characters. Fingerprints are strings of 40
-            // hexadecimal characters. The key id is the last 16 characters of
-            // the key fingerprint.
-            if (strlen($tokens[1]) > 16) {
-                $signature->setKeyFingerprint($tokens[1]);
-                $signature->setKeyId(substr($tokens[1], -16));
-            } else {
-                $signature->setKeyId($tokens[1]);
-            }
-
-            $this->index++;
-            $this->signatures[$this->index] = $signature;
-
-            break;
-
-        case 'VALIDSIG':
-            if (!array_key_exists($this->index, $this->signatures)) {
-                break;
-            }
-
-            $signature = $this->signatures[$this->index];
-
-            $signature->setValid(true);
-            $signature->setKeyFingerprint($tokens[1]);
-
-            if (strpos($tokens[3], 'T') === false) {
-                $signature->setCreationDate($tokens[3]);
-            } else {
-                $signature->setCreationDate(strtotime($tokens[3]));
-            }
-
-            if (array_key_exists(4, $tokens)) {
-                if (strpos($tokens[4], 'T') === false) {
-                    $signature->setExpirationDate($tokens[4]);
-                } else {
-                    $signature->setExpirationDate(strtotime($tokens[4]));
-                }
-            }
-
-            break;
-
-        case 'SIG_ID':
-            // note: signature id comes before new signature line and may not
-            // exist for some signature types
-            $this->signatureId = $tokens[1];
-            break;
-        }
-    }
-
-    // }}}
-    // {{{ getSignatures()
-
-    /**
-     * Gets the {@link Crypt_GPG_Signature} objects parsed by this handler
-     *
-     * @return array the signature objects parsed by this handler.
-     */
-    public function getSignatures()
-    {
-        return $this->signatures;
-    }
-
-    // }}}
-}
-
-?>
diff --git a/plugins/enigma/lib/enigma_driver.php b/plugins/enigma/lib/enigma_driver.php
deleted file mode 100644
index a9a3e47..0000000
--- a/plugins/enigma/lib/enigma_driver.php
+++ /dev/null
@@ -1,106 +0,0 @@
-<?php
-/*
- +-------------------------------------------------------------------------+
- | Abstract driver for the Enigma Plugin                                   |
- |                                                                         |
- | This program is free software; you can redistribute it and/or modify    |
- | it under the terms of the GNU General Public License version 2          |
- | as published by the Free Software Foundation.                           |
- |                                                                         |
- | 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.             |
- |                                                                         |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                              |
- +-------------------------------------------------------------------------+
-*/
-
-abstract class enigma_driver
-{
-    /**
-     * Class constructor.
-     *
-     * @param string User name (email address)
-     */
-    abstract function __construct($user);
-
-    /**
-     * Driver initialization.
-     *
-     * @return mixed NULL on success, enigma_error on failure
-     */
-    abstract function init();
-
-    /**
-     * Encryption.
-     */
-    abstract function encrypt($text, $keys);
-
-    /**
-     * Decryption..
-     */
-    abstract function decrypt($text, $key, $passwd);
-
-    /**
-     * Signing.
-     */
-    abstract function sign($text, $key, $passwd);
-
-    /**
-     * Signature verification.
-     *
-     * @param string Message body
-     * @param string Signature, if message is of type PGP/MIME and body doesn't contain it
-     *
-     * @return mixed Signature information (enigma_signature) or enigma_error
-     */
-    abstract function verify($text, $signature);
-
-    /**
-     * Key/Cert file import.
-     *
-     * @param string  File name or file content
-     * @param bollean True if first argument is a filename
-     *
-     * @return mixed Import status array or enigma_error
-     */
-    abstract function import($content, $isfile=false);
-
-    /**
-     * Keys listing.
-     *
-     * @param string Optional pattern for key ID, user ID or fingerprint
-     *
-     * @return mixed Array of enigma_key objects or enigma_error
-     */
-    abstract function list_keys($pattern='');
-    
-    /**
-     * Single key information.
-     *
-     * @param string Key ID, user ID or fingerprint
-     *
-     * @return mixed Key (enigma_key) object or enigma_error
-     */
-    abstract function get_key($keyid);
-
-    /**
-     * Key pair generation.
-     *
-     * @param array Key/User data
-     *
-     * @return mixed Key (enigma_key) object or enigma_error
-     */
-    abstract function gen_key($data);
-    
-    /**
-     * Key deletion.
-     */
-    abstract function del_key($keyid);
-}
diff --git a/plugins/enigma/lib/enigma_driver_gnupg.php b/plugins/enigma/lib/enigma_driver_gnupg.php
deleted file mode 100644
index 5aa3221..0000000
--- a/plugins/enigma/lib/enigma_driver_gnupg.php
+++ /dev/null
@@ -1,305 +0,0 @@
-<?php
-/*
- +-------------------------------------------------------------------------+
- | GnuPG (PGP) driver for the Enigma Plugin                                |
- |                                                                         |
- | This program is free software; you can redistribute it and/or modify    |
- | it under the terms of the GNU General Public License version 2          |
- | as published by the Free Software Foundation.                           |
- |                                                                         |
- | 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.             |
- |                                                                         |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                              |
- +-------------------------------------------------------------------------+
-*/
-
-require_once 'Crypt/GPG.php';
-
-class enigma_driver_gnupg extends enigma_driver
-{
-    private $rc;
-    private $gpg;
-    private $homedir;
-    private $user;
-
-    function __construct($user)
-    {
-        $rcmail = rcmail::get_instance();
-        $this->rc = $rcmail;
-        $this->user = $user;
-    }
-
-    /**
-     * Driver initialization and environment checking.
-     * Should only return critical errors.
-     *
-     * @return mixed NULL on success, enigma_error on failure
-     */
-    function init()
-    {
-        $homedir = $this->rc->config->get('enigma_pgp_homedir', INSTALL_PATH . '/plugins/enigma/home');
-
-        if (!$homedir)
-            return new enigma_error(enigma_error::E_INTERNAL,
-                "Option 'enigma_pgp_homedir' not specified");
-
-        // check if homedir exists (create it if not) and is readable
-        if (!file_exists($homedir))
-            return new enigma_error(enigma_error::E_INTERNAL,
-                "Keys directory doesn't exists: $homedir");
-        if (!is_writable($homedir))
-            return new enigma_error(enigma_error::E_INTERNAL,
-                "Keys directory isn't writeable: $homedir");
-
-        $homedir = $homedir . '/' . $this->user;
-
-        // check if user's homedir exists (create it if not) and is readable
-        if (!file_exists($homedir))
-            mkdir($homedir, 0700);
-
-        if (!file_exists($homedir))
-            return new enigma_error(enigma_error::E_INTERNAL,
-                "Unable to create keys directory: $homedir");
-        if (!is_writable($homedir))
-            return new enigma_error(enigma_error::E_INTERNAL,
-                "Unable to write to keys directory: $homedir");
-
-        $this->homedir = $homedir;
-
-        // Create Crypt_GPG object
-        try {
-	        $this->gpg = new Crypt_GPG(array(
-                'homedir'   => $this->homedir,
-//                'debug'     => true,
-          ));
-        }
-        catch (Exception $e) {
-            return $this->get_error_from_exception($e);
-        }
-    }
-
-    function encrypt($text, $keys)
-    {
-/*
-	    foreach ($keys as $key) {
-		    $this->gpg->addEncryptKey($key);
-	    }
-	    $enc = $this->gpg->encrypt($text);
-	    return $enc;
-*/
-    }
-
-    function decrypt($text, $key, $passwd)
-    {
-//	    $this->gpg->addDecryptKey($key, $passwd);
-        try {
-    	    $dec = $this->gpg->decrypt($text);
-    	    return $dec;
-        }
-        catch (Exception $e) {
-            return $this->get_error_from_exception($e);
-        }
-    }
-
-    function sign($text, $key, $passwd)
-    {
-/*
-	    $this->gpg->addSignKey($key, $passwd);
-	    $signed = $this->gpg->sign($text, Crypt_GPG::SIGN_MODE_DETACHED);
-	    return $signed;
-*/
-    }
-
-    function verify($text, $signature)
-    {
-        try {
-    	    $verified = $this->gpg->verify($text, $signature);
-      	    return $this->parse_signature($verified[0]);
-        }
-        catch (Exception $e) {
-            return $this->get_error_from_exception($e);
-        }
-    }
-
-    public function import($content, $isfile=false)
-    {
-        try {
-            if ($isfile)
-                return $this->gpg->importKeyFile($content);
-            else
-                return $this->gpg->importKey($content);
-        }
-        catch (Exception $e) {
-            return $this->get_error_from_exception($e);
-        }
-    }
-    
-    public function list_keys($pattern='')
-    {
-        try {
-    	    $keys = $this->gpg->getKeys($pattern);
-            $result = array();
-//print_r($keys);
-            foreach ($keys as $idx => $key) {
-                $result[] = $this->parse_key($key);
-                unset($keys[$idx]);
-            }
-//print_r($result);
-      	    return $result;
-        }
-        catch (Exception $e) {
-            return $this->get_error_from_exception($e);
-        }
-    }
-    
-    public function get_key($keyid)
-    {
-        $list = $this->list_keys($keyid);
-
-        if (is_array($list))
-            return array_shift($list);
-
-        // error        
-        return $list;
-    }
-
-    public function gen_key($data)
-    {
-    }
-
-    public function del_key($keyid)
-    {
-//        $this->get_key($keyid);
-        
-        
-    }
-    
-    public function del_privkey($keyid)
-    {
-        try {
-    	    $this->gpg->deletePrivateKey($keyid);
-            return true;
-        }
-        catch (Exception $e) {
-            return $this->get_error_from_exception($e);
-        }
-    }
-
-    public function del_pubkey($keyid)
-    {
-        try {
-    	    $this->gpg->deletePublicKey($keyid);
-            return true;
-        }
-        catch (Exception $e) {
-            return $this->get_error_from_exception($e);
-        }
-    }
-    
-    /**
-     * Converts Crypt_GPG exception into Enigma's error object
-     *
-     * @param mixed Exception object
-     *
-     * @return enigma_error Error object
-     */
-    private function get_error_from_exception($e)
-    {
-        $data = array();
-
-        if ($e instanceof Crypt_GPG_KeyNotFoundException) {
-            $error = enigma_error::E_KEYNOTFOUND;
-            $data['id'] = $e->getKeyId();
-        }
-        else if ($e instanceof Crypt_GPG_BadPassphraseException) {
-            $error = enigma_error::E_BADPASS;
-            $data['bad']     = $e->getBadPassphrases();
-            $data['missing'] = $e->getMissingPassphrases();
-        }
-        else if ($e instanceof Crypt_GPG_NoDataException)
-            $error = enigma_error::E_NODATA;
-        else if ($e instanceof Crypt_GPG_DeletePrivateKeyException)
-            $error = enigma_error::E_DELKEY;
-        else
-            $error = enigma_error::E_INTERNAL;
-
-        $msg = $e->getMessage();
-
-        return new enigma_error($error, $msg, $data);
-    }
-
-    /**
-     * Converts Crypt_GPG_Signature object into Enigma's signature object
-     *
-     * @param Crypt_GPG_Signature Signature object
-     *
-     * @return enigma_signature Signature object
-     */
-    private function parse_signature($sig)
-    {
-        $user = $sig->getUserId();
-
-        $data = new enigma_signature();
-        $data->id          = $sig->getId();
-        $data->valid       = $sig->isValid();
-        $data->fingerprint = $sig->getKeyFingerprint();
-        $data->created     = $sig->getCreationDate();
-        $data->expires     = $sig->getExpirationDate();
-        $data->name        = $user->getName();
-        $data->comment     = $user->getComment();
-        $data->email       = $user->getEmail();
-
-        return $data;
-    }
-
-    /**
-     * Converts Crypt_GPG_Key object into Enigma's key object
-     *
-     * @param Crypt_GPG_Key Key object
-     *
-     * @return enigma_key Key object
-     */
-    private function parse_key($key)
-    {
-        $ekey = new enigma_key();
-
-        foreach ($key->getUserIds() as $idx => $user) {
-            $id = new enigma_userid();
-            $id->name    = $user->getName();
-            $id->comment = $user->getComment();
-            $id->email   = $user->getEmail();
-            $id->valid   = $user->isValid();
-            $id->revoked = $user->isRevoked();
-
-            $ekey->users[$idx] = $id;
-        }
-        
-        $ekey->name = trim($ekey->users[0]->name . ' <' . $ekey->users[0]->email . '>');
-
-        foreach ($key->getSubKeys() as $idx => $subkey) {
-                $skey = new enigma_subkey();
-                $skey->id          = $subkey->getId();
-                $skey->revoked     = $subkey->isRevoked();
-                $skey->created     = $subkey->getCreationDate();
-                $skey->expires     = $subkey->getExpirationDate();
-                $skey->fingerprint = $subkey->getFingerprint();
-                $skey->has_private = $subkey->hasPrivate();
-                $skey->can_sign    = $subkey->canSign();
-                $skey->can_encrypt = $subkey->canEncrypt();
-
-                $ekey->subkeys[$idx] = $skey;
-        };
-        
-        $ekey->id = $ekey->subkeys[0]->id;
-        
-        return $ekey;
-    }
-}
diff --git a/plugins/enigma/lib/enigma_engine.php b/plugins/enigma/lib/enigma_engine.php
deleted file mode 100644
index 59ae120..0000000
--- a/plugins/enigma/lib/enigma_engine.php
+++ /dev/null
@@ -1,547 +0,0 @@
-<?php
-/*
- +-------------------------------------------------------------------------+
- | Engine of the Enigma Plugin                                             |
- |                                                                         |
- | This program is free software; you can redistribute it and/or modify    |
- | it under the terms of the GNU General Public License version 2          |
- | as published by the Free Software Foundation.                           |
- |                                                                         |
- | 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.             |
- |                                                                         |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                              |
- +-------------------------------------------------------------------------+
-
-*/
-
-/*
-    RFC2440: OpenPGP Message Format
-    RFC3156: MIME Security with OpenPGP
-    RFC3851: S/MIME
-*/
-
-class enigma_engine
-{
-    private $rc;
-    private $enigma;
-    private $pgp_driver;
-    private $smime_driver;
-
-    public $decryptions = array();
-    public $signatures = array();
-    public $signed_parts = array();
-
-
-    /**
-     * Plugin initialization.
-     */
-    function __construct($enigma)
-    {
-        $rcmail = rcmail::get_instance();
-        $this->rc = $rcmail;    
-        $this->enigma = $enigma;
-    }
-
-    /**
-     * PGP driver initialization.
-     */
-    function load_pgp_driver()
-    {
-        if ($this->pgp_driver)
-            return;
-
-        $driver = 'enigma_driver_' . $this->rc->config->get('enigma_pgp_driver', 'gnupg');
-        $username = $this->rc->user->get_username();
-
-        // Load driver
-        $this->pgp_driver = new $driver($username);
-
-        if (!$this->pgp_driver) {
-            raise_error(array(
-                'code' => 600, 'type' => 'php',
-                'file' => __FILE__, 'line' => __LINE__,
-                'message' => "Enigma plugin: Unable to load PGP driver: $driver"
-            ), true, true);
-        }
-
-        // Initialise driver
-        $result = $this->pgp_driver->init();
-
-        if ($result instanceof enigma_error) {
-            raise_error(array(
-                'code' => 600, 'type' => 'php',
-                'file' => __FILE__, 'line' => __LINE__,
-                'message' => "Enigma plugin: ".$result->getMessage()
-            ), true, true);
-        }
-    }
-
-    /**
-     * S/MIME driver initialization.
-     */
-    function load_smime_driver()
-    {
-        if ($this->smime_driver)
-            return;
-
-        // NOT IMPLEMENTED!
-        return;
-
-        $driver = 'enigma_driver_' . $this->rc->config->get('enigma_smime_driver', 'phpssl');
-        $username = $this->rc->user->get_username();
-
-        // Load driver
-        $this->smime_driver = new $driver($username);
-
-        if (!$this->smime_driver) {
-            raise_error(array(
-                'code' => 600, 'type' => 'php',
-                'file' => __FILE__, 'line' => __LINE__,
-                'message' => "Enigma plugin: Unable to load S/MIME driver: $driver"
-            ), true, true);
-        }
-
-        // Initialise driver
-        $result = $this->smime_driver->init();
-
-        if ($result instanceof enigma_error) {
-            raise_error(array(
-                'code' => 600, 'type' => 'php',
-                'file' => __FILE__, 'line' => __LINE__,
-                'message' => "Enigma plugin: ".$result->getMessage()
-            ), true, true);
-        }
-    }
-
-    /**
-     * Handler for plain/text message.
-     *
-     * @param array Reference to hook's parameters
-     */
-    function parse_plain(&$p)
-    {
-        $part = $p['structure'];
-
-        // Get message body from IMAP server
-        $this->set_part_body($part, $p['object']->uid);
-
-        // @TODO: big message body can be a file resource
-        // PGP signed message
-        if (preg_match('/^-----BEGIN PGP SIGNED MESSAGE-----/', $part->body)) {
-            $this->parse_plain_signed($p);
-        }
-        // PGP encrypted message
-        else if (preg_match('/^-----BEGIN PGP MESSAGE-----/', $part->body)) {
-            $this->parse_plain_encrypted($p);
-        }
-    }
-
-    /**
-     * Handler for multipart/signed message.
-     *
-     * @param array Reference to hook's parameters
-     */
-    function parse_signed(&$p)
-    {
-        $struct = $p['structure'];
-
-        // S/MIME
-        if ($struct->parts[1] && $struct->parts[1]->mimetype == 'application/pkcs7-signature') {
-            $this->parse_smime_signed($p);
-        }
-        // PGP/MIME:
-        // The multipart/signed body MUST consist of exactly two parts.
-        // The first part contains the signed data in MIME canonical format,
-        // including a set of appropriate content headers describing the data.
-        // The second body MUST contain the PGP digital signature.  It MUST be
-        // labeled with a content type of "application/pgp-signature".
-        else if ($struct->parts[1] && $struct->parts[1]->mimetype == 'application/pgp-signature') {
-            $this->parse_pgp_signed($p);
-        }
-    }
-
-    /**
-     * Handler for multipart/encrypted message.
-     *
-     * @param array Reference to hook's parameters
-     */
-    function parse_encrypted(&$p)
-    {
-        $struct = $p['structure'];
-
-        // S/MIME
-        if ($struct->mimetype == 'application/pkcs7-mime') {
-            $this->parse_smime_encrypted($p);
-        }
-        // PGP/MIME:
-        // The multipart/encrypted MUST consist of exactly two parts.  The first
-        // MIME body part must have a content type of "application/pgp-encrypted".
-        // This body contains the control information.
-        // The second MIME body part MUST contain the actual encrypted data.  It
-        // must be labeled with a content type of "application/octet-stream".
-        else if ($struct->parts[0] && $struct->parts[0]->mimetype == 'application/pgp-encrypted' &&
-            $struct->parts[1] && $struct->parts[1]->mimetype == 'application/octet-stream'
-        ) {
-            $this->parse_pgp_encrypted($p);
-        }
-    }
-
-    /**
-     * Handler for plain signed message.
-     * Excludes message and signature bodies and verifies signature.
-     *
-     * @param array Reference to hook's parameters
-     */
-    private function parse_plain_signed(&$p)
-    {
-        $this->load_pgp_driver();
-        $part = $p['structure'];
-
-        // Verify signature
-        if ($this->rc->action == 'show' || $this->rc->action == 'preview') {
-            $sig = $this->pgp_verify($part->body);
-        }
-
-        // @TODO: Handle big bodies using (temp) files
-
-        // In this way we can use fgets on string as on file handle
-        $fh = fopen('php://memory', 'br+');
-        // @TODO: fopen/fwrite errors handling
-        if ($fh) {
-            fwrite($fh, $part->body);
-            rewind($fh);
-        }
-        $part->body = null;
-
-        // Extract body (and signature?)
-        while (!feof($fh)) {
-            $line = fgets($fh, 1024);
-
-            if ($part->body === null)
-                $part->body = '';
-            else if (preg_match('/^-----BEGIN PGP SIGNATURE-----/', $line))
-                break;
-            else
-                $part->body .= $line;
-        }
-
-        // Remove "Hash" Armor Headers
-        $part->body = preg_replace('/^.*\r*\n\r*\n/', '', $part->body);
-        // de-Dash-Escape (RFC2440)
-        $part->body = preg_replace('/(^|\n)- -/', '\\1-', $part->body);
-
-        // Store signature data for display
-        if (!empty($sig)) {
-            $this->signed_parts[$part->mime_id] = $part->mime_id;
-            $this->signatures[$part->mime_id] = $sig;
-        }
-
-        fclose($fh);
-    }
-    
-    /**
-     * Handler for PGP/MIME signed message.
-     * Verifies signature.
-     *
-     * @param array Reference to hook's parameters
-     */
-    private function parse_pgp_signed(&$p)
-    {
-        $this->load_pgp_driver();
-        $struct = $p['structure'];
-        
-        // Verify signature
-        if ($this->rc->action == 'show' || $this->rc->action == 'preview') {
-            $msg_part = $struct->parts[0];
-            $sig_part = $struct->parts[1];
-        
-            // Get bodies
-            $this->set_part_body($msg_part, $p['object']->uid);
-            $this->set_part_body($sig_part, $p['object']->uid);
-
-            // Verify
-            $sig = $this->pgp_verify($msg_part->body, $sig_part->body);
-
-            // Store signature data for display
-            $this->signatures[$struct->mime_id] = $sig;
-
-            // Message can be multipart (assign signature to each subpart)
-            if (!empty($msg_part->parts)) {
-                foreach ($msg_part->parts as $part)
-                    $this->signed_parts[$part->mime_id] = $struct->mime_id;
-            }
-            else
-                $this->signed_parts[$msg_part->mime_id] = $struct->mime_id;
-
-            // Remove signature file from attachments list
-            unset($struct->parts[1]);
-        }
-    }
-
-    /**
-     * Handler for S/MIME signed message.
-     * Verifies signature.
-     *
-     * @param array Reference to hook's parameters
-     */
-    private function parse_smime_signed(&$p)
-    {
-        $this->load_smime_driver();
-    }
-
-    /**
-     * Handler for plain encrypted message.
-     *
-     * @param array Reference to hook's parameters
-     */
-    private function parse_plain_encrypted(&$p)
-    {
-        $this->load_pgp_driver();
-        $part = $p['structure'];
-        
-        // Get body
-        $this->set_part_body($part, $p['object']->uid);
-
-        // Decrypt 
-        $result = $this->pgp_decrypt($part->body);
-        
-        // Store decryption status
-        $this->decryptions[$part->mime_id] = $result;
-        
-        // Parse decrypted message
-        if ($result === true) {
-            // @TODO
-        }
-    }
-    
-    /**
-     * Handler for PGP/MIME encrypted message.
-     *
-     * @param array Reference to hook's parameters
-     */
-    private function parse_pgp_encrypted(&$p)
-    {
-        $this->load_pgp_driver();
-        $struct = $p['structure'];
-        $part = $struct->parts[1];
-        
-        // Get body
-        $this->set_part_body($part, $p['object']->uid);
-
-        // Decrypt
-        $result = $this->pgp_decrypt($part->body);
-
-        $this->decryptions[$part->mime_id] = $result;
-//print_r($part);
-        // Parse decrypted message
-        if ($result === true) {
-            // @TODO
-        }
-        else {
-            // Make sure decryption status message will be displayed
-            $part->type = 'content';
-            $p['object']->parts[] = $part;
-        }
-    }
-
-    /**
-     * Handler for S/MIME encrypted message.
-     *
-     * @param array Reference to hook's parameters
-     */
-    private function parse_smime_encrypted(&$p)
-    {
-        $this->load_smime_driver();
-    }
-
-    /**
-     * PGP signature verification.
-     *
-     * @param mixed Message body
-     * @param mixed Signature body (for MIME messages)
-     *
-     * @return mixed enigma_signature or enigma_error
-     */
-    private function pgp_verify(&$msg_body, $sig_body=null)
-    {
-        // @TODO: Handle big bodies using (temp) files
-        // @TODO: caching of verification result
-        
-         $sig = $this->pgp_driver->verify($msg_body, $sig_body);
-
-         if (($sig instanceof enigma_error) && $sig->getCode() != enigma_error::E_KEYNOTFOUND)
-             raise_error(array(
-                'code' => 600, 'type' => 'php',
-                'file' => __FILE__, 'line' => __LINE__,
-                'message' => "Enigma plugin: " . $error->getMessage()
-                ), true, false);
-
-//print_r($sig);
-        return $sig;
-    }
-
-    /**
-     * PGP message decryption.
-     *
-     * @param mixed Message body
-     *
-     * @return mixed True or enigma_error
-     */
-    private function pgp_decrypt(&$msg_body)
-    {
-        // @TODO: Handle big bodies using (temp) files
-        // @TODO: caching of verification result
-        
-        $result = $this->pgp_driver->decrypt($msg_body, $key, $pass);
-
-//print_r($result);
-
-        if ($result instanceof enigma_error) {
-            $err_code = $result->getCode();
-            if (!in_array($err_code, array(enigma_error::E_KEYNOTFOUND, enigma_error::E_BADPASS)))
-                raise_error(array(
-                    'code' => 600, 'type' => 'php',
-                    'file' => __FILE__, 'line' => __LINE__,
-                    'message' => "Enigma plugin: " . $result->getMessage()
-                    ), true, false);
-            return $result;
-        }
-
-//        $msg_body = $result;
-        return true;
-    }
-
-    /**
-     * PGP keys listing.
-     *
-     * @param mixed Key ID/Name pattern
-     *
-     * @return mixed Array of keys or enigma_error
-     */
-    function list_keys($pattern='')
-    {
-        $this->load_pgp_driver();
-        $result = $this->pgp_driver->list_keys($pattern);
-    
-        if ($result instanceof enigma_error) {
-            raise_error(array(
-                'code' => 600, 'type' => 'php',
-                'file' => __FILE__, 'line' => __LINE__,
-                'message' => "Enigma plugin: " . $result->getMessage()
-                ), true, false);
-        }
-        
-        return $result;
-    }
-
-    /**
-     * PGP key details.
-     *
-     * @param mixed Key ID
-     *
-     * @return mixed enigma_key or enigma_error
-     */
-    function get_key($keyid)
-    {
-        $this->load_pgp_driver();
-        $result = $this->pgp_driver->get_key($keyid);
-    
-        if ($result instanceof enigma_error) {
-            raise_error(array(
-                'code' => 600, 'type' => 'php',
-                'file' => __FILE__, 'line' => __LINE__,
-                'message' => "Enigma plugin: " . $result->getMessage()
-                ), true, false);
-        }
-        
-        return $result;
-    }
-
-    /**
-     * PGP keys/certs importing.
-     *
-     * @param mixed   Import file name or content
-     * @param boolean True if first argument is a filename
-     *
-     * @return mixed Import status data array or enigma_error
-     */
-    function import_key($content, $isfile=false)
-    {
-        $this->load_pgp_driver();
-        $result = $this->pgp_driver->import($content, $isfile);
-
-        if ($result instanceof enigma_error) {
-            raise_error(array(
-                'code' => 600, 'type' => 'php',
-                'file' => __FILE__, 'line' => __LINE__,
-                'message' => "Enigma plugin: " . $result->getMessage()
-                ), true, false);
-        }
-        else {
-            $result['imported'] = $result['public_imported'] + $result['private_imported'];
-            $result['unchanged'] = $result['public_unchanged'] + $result['private_unchanged'];
-        }
-
-        return $result;
-    }
-
-    /**
-     * Handler for keys/certs import request action
-     */
-    function import_file()
-    {
-        $uid = get_input_value('_uid', RCUBE_INPUT_POST);
-        $mbox = get_input_value('_mbox', RCUBE_INPUT_POST);
-        $mime_id = get_input_value('_part', RCUBE_INPUT_POST);
-
-        if ($uid && $mime_id) {
-            $part = $this->rc->imap->get_message_part($uid, $mime_id);
-        }
-
-        if ($part && is_array($result = $this->import_key($part))) {
-            $this->rc->output->show_message('enigma.keysimportsuccess', 'confirmation',
-                array('new' => $result['imported'], 'old' => $result['unchanged']));
-        }
-        else
-            $this->rc->output->show_message('enigma.keysimportfailed', 'error');
-    
-        $this->rc->output->send();
-    }
-
-    /**
-     * Checks if specified message part contains body data.
-     * If body is not set it will be fetched from IMAP server.
-     *
-     * @param rcube_message_part Message part object
-     * @param integer            Message UID
-     */
-    private function set_part_body($part, $uid)
-    {
-        // @TODO: Create such function in core
-        // @TODO: Handle big bodies using file handles
-        if (!isset($part->body)) {
-            $part->body = $this->rc->imap->get_message_part(
-                $uid, $part->mime_id, $part);
-        }
-    }
-
-    /**
-     * Adds CSS style file to the page header.
-     */
-    private function add_css()
-    {
-        $skin = $this->rc->config->get('skin');
-        if (!file_exists($this->home . "/skins/$skin/enigma.css"))
-            $skin = 'default';
-
-        $this->include_stylesheet("skins/$skin/enigma.css");                                                
-    }
-}
diff --git a/plugins/enigma/lib/enigma_error.php b/plugins/enigma/lib/enigma_error.php
deleted file mode 100644
index 9f424dc..0000000
--- a/plugins/enigma/lib/enigma_error.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-/*
- +-------------------------------------------------------------------------+
- | Error class for the Enigma Plugin                                       |
- |                                                                         |
- | This program is free software; you can redistribute it and/or modify    |
- | it under the terms of the GNU General Public License version 2          |
- | as published by the Free Software Foundation.                           |
- |                                                                         |
- | 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.             |
- |                                                                         |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                              |
- +-------------------------------------------------------------------------+
-*/
-
-class enigma_error
-{
-    private $code;
-    private $message;
-    private $data = array();
-
-    // error codes
-    const E_OK = 0;
-    const E_INTERNAL = 1;
-    const E_NODATA = 2;
-    const E_KEYNOTFOUND = 3;
-    const E_DELKEY = 4;
-    const E_BADPASS = 5;
-    
-    function __construct($code = null, $message = '', $data = array())
-    {
-        $this->code = $code;
-        $this->message = $message;
-        $this->data = $data;
-    }
-
-    function getCode()
-    {
-        return $this->code;
-    }
-
-    function getMessage()
-    {
-        return $this->message;
-    }
-
-    function getData($name)
-    {
-        if ($name)
-            return $this->data[$name];
-        else
-            return $this->data;
-    }
-}
diff --git a/plugins/enigma/lib/enigma_key.php b/plugins/enigma/lib/enigma_key.php
deleted file mode 100644
index 520c36b..0000000
--- a/plugins/enigma/lib/enigma_key.php
+++ /dev/null
@@ -1,129 +0,0 @@
-<?php
-/*
- +-------------------------------------------------------------------------+
- | Key class for the Enigma Plugin                                         |
- |                                                                         |
- | This program is free software; you can redistribute it and/or modify    |
- | it under the terms of the GNU General Public License version 2          |
- | as published by the Free Software Foundation.                           |
- |                                                                         |
- | 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.             |
- |                                                                         |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                              |
- +-------------------------------------------------------------------------+
-*/
-
-class enigma_key
-{
-    public $id;
-    public $name;
-    public $users = array();
-    public $subkeys = array();
-
-    const TYPE_UNKNOWN = 0;
-    const TYPE_KEYPAIR = 1;
-    const TYPE_PUBLIC = 2;
-
-    /**
-     * Keys list sorting callback for usort()
-     */
-    static function cmp($a, $b)
-    {
-        return strcmp($a->name, $b->name);
-    }
-
-    /**
-     * Returns key type
-     */
-    function get_type()
-    {
-        if ($this->subkeys[0]->has_private)
-            return enigma_key::TYPE_KEYPAIR;
-        else if (!empty($this->subkeys[0]))
-            return enigma_key::TYPE_PUBLIC;
-
-        return enigma_key::TYPE_UNKNOWN;
-    }
-
-    /**
-     * Returns true if all user IDs are revoked
-     */    
-    function is_revoked()
-    {
-        foreach ($this->subkeys as $subkey)
-            if (!$subkey->revoked)
-                return false;
-
-        return true;
-    }
-
-    /**
-     * Returns true if any user ID is valid
-     */    
-    function is_valid()
-    {
-        foreach ($this->users as $user)
-            if ($user->valid)
-                return true;
-
-        return false;
-    }
-    
-    /**
-     * Returns true if any of subkeys is not expired
-     */    
-    function is_expired()
-    {
-        $now = time();
-        
-        foreach ($this->subkeys as $subkey)
-            if (!$subkey->expires || $subkey->expires > $now)
-                return true;
-    
-        return false;
-    }
-
-    /**
-     * Converts long ID or Fingerprint to short ID
-     * Crypt_GPG uses internal, but e.g. Thunderbird's Enigmail displays short ID
-     *
-     * @param string Key ID or fingerprint
-     * @return string Key short ID
-     */
-    static function format_id($id)
-    {
-        // E.g. 04622F2089E037A5 => 89E037A5
-        
-        return substr($id, -8);
-    }
-
-    /**
-     * Formats fingerprint string
-     *
-     * @param string Key fingerprint
-     *
-     * @return string Formatted fingerprint (with spaces)
-     */
-    static function format_fingerprint($fingerprint)
-    {
-        if (!$fingerprint)
-            return '';
-    
-        $result = '';
-        for ($i=0; $i<40; $i++) {
-            if ($i % 4 == 0)
-                $result .= ' ';
-            $result .= $fingerprint[$i];
-        }
-        return $result;
-    }
-
-}
diff --git a/plugins/enigma/lib/enigma_signature.php b/plugins/enigma/lib/enigma_signature.php
deleted file mode 100644
index 6599090..0000000
--- a/plugins/enigma/lib/enigma_signature.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-/*
- +-------------------------------------------------------------------------+
- | Signature class for the Enigma Plugin                                   |
- |                                                                         |
- | This program is free software; you can redistribute it and/or modify    |
- | it under the terms of the GNU General Public License version 2          |
- | as published by the Free Software Foundation.                           |
- |                                                                         |
- | 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.             |
- |                                                                         |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                              |
- +-------------------------------------------------------------------------+
-*/
-
-class enigma_signature
-{
-    public $id;
-    public $valid;
-    public $fingerprint;
-    public $created;
-    public $expires;
-    public $name;
-    public $comment;
-    public $email;
-}
diff --git a/plugins/enigma/lib/enigma_subkey.php b/plugins/enigma/lib/enigma_subkey.php
deleted file mode 100644
index 1b9fb95..0000000
--- a/plugins/enigma/lib/enigma_subkey.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-/*
- +-------------------------------------------------------------------------+
- | SubKey class for the Enigma Plugin                                      |
- |                                                                         |
- | This program is free software; you can redistribute it and/or modify    |
- | it under the terms of the GNU General Public License version 2          |
- | as published by the Free Software Foundation.                           |
- |                                                                         |
- | 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.             |
- |                                                                         |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                              |
- +-------------------------------------------------------------------------+
-*/
-
-class enigma_subkey
-{
-    public $id;
-    public $fingerprint;
-    public $expires;
-    public $created;
-    public $revoked;
-    public $has_private;
-    public $can_sign;
-    public $can_encrypt;
-    
-    /**
-     * Converts internal ID to short ID
-     * Crypt_GPG uses internal, but e.g. Thunderbird's Enigmail displays short ID
-     *
-     * @return string Key ID
-     */
-    function get_short_id()
-    {
-        // E.g. 04622F2089E037A5 => 89E037A5
-        return enigma_key::format_id($this->id);
-    }
-
-    /**
-     * Getter for formatted fingerprint
-     *
-     * @return string Formatted fingerprint
-     */
-    function get_fingerprint()
-    {
-        return enigma_key::format_fingerprint($this->fingerprint);
-    }
-
-}
diff --git a/plugins/enigma/lib/enigma_ui.php b/plugins/enigma/lib/enigma_ui.php
deleted file mode 100644
index b9ccff5..0000000
--- a/plugins/enigma/lib/enigma_ui.php
+++ /dev/null
@@ -1,459 +0,0 @@
-<?php
-/*
- +-------------------------------------------------------------------------+
- | User Interface for the Enigma Plugin                                    |
- |                                                                         |
- | This program is free software; you can redistribute it and/or modify    |
- | it under the terms of the GNU General Public License version 2          |
- | as published by the Free Software Foundation.                           |
- |                                                                         |
- | 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.             |
- |                                                                         |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                              |
- +-------------------------------------------------------------------------+
-*/
-
-class enigma_ui
-{
-    private $rc;
-    private $enigma;
-    private $home;
-    private $css_added;
-    private $data;
-
-
-    function __construct($enigma_plugin, $home='')
-    {
-        $this->enigma = $enigma_plugin;
-        $this->rc = $enigma_plugin->rc;
-        // we cannot use $enigma_plugin->home here
-        $this->home = $home;
-    }
-
-    /**
-     * UI initialization and requests handlers.
-     *
-     * @param string Preferences section
-     */
-    function init($section='')
-    {
-        $this->enigma->include_script('enigma.js');
-
-        // Enigma actions
-        if ($this->rc->action == 'plugin.enigma') {
-            $action = get_input_value('_a', RCUBE_INPUT_GPC);
-
-            switch ($action) {
-                case 'keyedit':
-                    $this->key_edit();
-                    break;
-                case 'keyimport':
-                    $this->key_import();
-                    break;
-                case 'keysearch':
-                case 'keylist':
-                    $this->key_list();
-                    break;
-                case 'keyinfo':
-                default:
-                    $this->key_info();
-            }
-        }
-        // Message composing UI
-        else if ($this->rc->action == 'compose') {
-            $this->compose_ui();
-        }
-        // Preferences UI
-        else { // if ($this->rc->action == 'edit-prefs') {
-            if ($section == 'enigmacerts') {
-                $this->rc->output->add_handlers(array(
-                    'keyslist' => array($this, 'tpl_certs_list'),
-                    'keyframe' => array($this, 'tpl_cert_frame'),
-                    'countdisplay' => array($this, 'tpl_certs_rowcount'),
-                    'searchform' => array($this->rc->output, 'search_form'),
-                ));
-                $this->rc->output->set_pagetitle($this->enigma->gettext('enigmacerts'));
-                $this->rc->output->send('enigma.certs'); 
-            }
-            else {
-                $this->rc->output->add_handlers(array(
-                    'keyslist' => array($this, 'tpl_keys_list'),
-                    'keyframe' => array($this, 'tpl_key_frame'),
-                    'countdisplay' => array($this, 'tpl_keys_rowcount'),
-                    'searchform' => array($this->rc->output, 'search_form'),
-                ));
-                $this->rc->output->set_pagetitle($this->enigma->gettext('enigmakeys'));
-                $this->rc->output->send('enigma.keys'); 
-            }
-        }
-    }
-
-   /**
-     * Adds CSS style file to the page header.
-     */
-    function add_css()
-    {
-        if ($this->css_loaded)
-            return;
-
-        $skin = $this->rc->config->get('skin');
-        if (!file_exists($this->home . "/skins/$skin/enigma.css"))
-            $skin = 'default';
-
-        $this->enigma->include_stylesheet("skins/$skin/enigma.css");
-        $this->css_added = true;
-    }
-
-    /**
-     * Template object for key info/edit frame.
-     *
-     * @param array Object attributes
-     *
-     * @return string HTML output
-     */
-    function tpl_key_frame($attrib)
-    {
-        if (!$attrib['id']) {
-            $attrib['id'] = 'rcmkeysframe';
-        }
-
-        $attrib['name'] = $attrib['id'];
-
-        $this->rc->output->set_env('contentframe', $attrib['name']);
-        $this->rc->output->set_env('blankpage', $attrib['src'] ? 
-            $this->rc->output->abs_url($attrib['src']) : 'program/blank.gif');
-
-        return html::tag('iframe', $attrib);
-    }
-
-    /**
-     * Template object for list of keys.
-     *
-     * @param array Object attributes
-     *
-     * @return string HTML content
-     */
-    function tpl_keys_list($attrib)
-    {
-        // add id to message list table if not specified
-        if (!strlen($attrib['id'])) {
-            $attrib['id'] = 'rcmenigmakeyslist';
-        }
-
-        // define list of cols to be displayed
-        $a_show_cols = array('name');
-
-        // create XHTML table
-        $out = rcube_table_output($attrib, array(), $a_show_cols, 'id');
-
-        // set client env
-        $this->rc->output->add_gui_object('keyslist', $attrib['id']);
-        $this->rc->output->include_script('list.js');
-
-        // add some labels to client
-        $this->rc->output->add_label('enigma.keyconfirmdelete');
-
-        return $out;
-    }
-
-    /**
-     * Key listing (and searching) request handler
-     */
-    private function key_list()
-    {
-        $this->enigma->load_engine();
-
-        $pagesize = $this->rc->config->get('pagesize', 100);
-        $page     = max(intval(get_input_value('_p', RCUBE_INPUT_GPC)), 1);
-        $search   = get_input_value('_q', RCUBE_INPUT_GPC);
-
-        // define list of cols to be displayed
-        $a_show_cols = array('name');
-        $result = array();
-
-        // Get the list
-        $list = $this->enigma->engine->list_keys($search);
-
-        if ($list && ($list instanceof enigma_error))
-            $this->rc->output->show_message('enigma.keylisterror', 'error');
-        else if (empty($list))
-            $this->rc->output->show_message('enigma.nokeysfound', 'notice');
-        else {
-            if (is_array($list)) {
-                // Save the size
-                $listsize = count($list);
-
-                // Sort the list by key (user) name
-                usort($list, array('enigma_key', 'cmp'));
-
-                // Slice current page
-                $list = array_slice($list, ($page - 1) * $pagesize, $pagesize);
-
-                $size = count($list);
-
-                // Add rows
-                foreach($list as $idx => $key) {
-                    $this->rc->output->command('enigma_add_list_row',
-                        array('name' => Q($key->name), 'id' => $key->id));
-                }
-            }
-        }
-
-        $this->rc->output->set_env('search_request', $search);
-        $this->rc->output->set_env('pagecount', ceil($listsize/$pagesize));
-        $this->rc->output->set_env('current_page', $page);
-        $this->rc->output->command('set_rowcount',
-            $this->get_rowcount_text($listsize, $size, $page));
-
-        $this->rc->output->send();
-    }
-
-    /**
-     * Template object for list records counter.
-     *
-     * @param array Object attributes
-     *
-     * @return string HTML output
-     */
-    function tpl_keys_rowcount($attrib)
-    {
-        if (!$attrib['id'])
-            $attrib['id'] = 'rcmcountdisplay';
-
-        $this->rc->output->add_gui_object('countdisplay', $attrib['id']);
-
-        return html::span($attrib, $this->get_rowcount_text());
-    }
-
-    /**
-     * Returns text representation of list records counter
-     */
-    private function get_rowcount_text($all=0, $curr_count=0, $page=1)
-    {
-        if (!$curr_count)
-            $out = $this->enigma->gettext('nokeysfound');
-        else {
-            $pagesize = $this->rc->config->get('pagesize', 100);
-            $first = ($page - 1) * $pagesize;
-
-            $out = $this->enigma->gettext(array(
-                'name' => 'keysfromto',
-                'vars' => array(
-                    'from'  => $first + 1,
-                    'to'    => $first + $curr_count,
-                    'count' => $all)
-            ));
-        }
-
-        return $out;
-    }
-
-    /**
-     * Key information page handler
-     */
-    private function key_info()
-    {
-        $id = get_input_value('_id', RCUBE_INPUT_GET);
-
-        $this->enigma->load_engine();
-        $res = $this->enigma->engine->get_key($id);
-
-        if ($res instanceof enigma_key)
-            $this->data = $res;
-        else { // error
-            $this->rc->output->show_message('enigma.keyopenerror', 'error');
-            $this->rc->output->command('parent.enigma_loadframe');
-            $this->rc->output->send('iframe');
-        }
-
-        $this->rc->output->add_handlers(array(
-            'keyname' => array($this, 'tpl_key_name'),
-            'keydata' => array($this, 'tpl_key_data'),
-        ));
-
-        $this->rc->output->set_pagetitle($this->enigma->gettext('keyinfo'));
-        $this->rc->output->send('enigma.keyinfo');
-    }
-
-    /**
-     * Template object for key name
-     */
-    function tpl_key_name($attrib)
-    {
-        return Q($this->data->name);
-    }
-
-    /**
-     * Template object for key information page content
-     */
-    function tpl_key_data($attrib)
-    {
-        $out = '';
-        $table = new html_table(array('cols' => 2)); 
-
-        // Key user ID
-        $table->add('title', $this->enigma->gettext('keyuserid'));
-        $table->add(null, Q($this->data->name));
-        // Key ID
-        $table->add('title', $this->enigma->gettext('keyid'));
-        $table->add(null, $this->data->subkeys[0]->get_short_id());
-        // Key type
-        $keytype = $this->data->get_type();
-        if ($keytype == enigma_key::TYPE_KEYPAIR)
-            $type = $this->enigma->gettext('typekeypair');
-        else if ($keytype == enigma_key::TYPE_PUBLIC)
-            $type = $this->enigma->gettext('typepublickey');
-        $table->add('title', $this->enigma->gettext('keytype'));
-        $table->add(null, $type);
-        // Key fingerprint
-        $table->add('title', $this->enigma->gettext('fingerprint'));
-        $table->add(null, $this->data->subkeys[0]->get_fingerprint());
-
-        $out .= html::tag('fieldset', null,
-            html::tag('legend', null,
-                $this->enigma->gettext('basicinfo')) . $table->show($attrib));
-
-        // Subkeys
-        $table = new html_table(array('cols' => 6)); 
-        // Columns: Type, ID, Algorithm, Size, Created, Expires
-
-        $out .= html::tag('fieldset', null,
-            html::tag('legend', null, 
-                $this->enigma->gettext('subkeys')) . $table->show($attrib));
-
-        // Additional user IDs
-        $table = new html_table(array('cols' => 2));
-        // Columns: User ID, Validity
-
-        $out .= html::tag('fieldset', null,
-            html::tag('legend', null, 
-                $this->enigma->gettext('userids')) . $table->show($attrib));
-
-        return $out;
-    }
-
-    /**
-     * Key import page handler
-     */
-    private function key_import()
-    {
-        // Import process
-        if ($_FILES['_file']['tmp_name'] && is_uploaded_file($_FILES['_file']['tmp_name'])) {
-            $this->enigma->load_engine();
-            $result = $this->enigma->engine->import_key($_FILES['_file']['tmp_name'], true);
-
-            if (is_array($result)) {
-                // reload list if any keys has been added
-                if ($result['imported']) {
-                    $this->rc->output->command('parent.enigma_list', 1);
-                }
-                else
-                    $this->rc->output->command('parent.enigma_loadframe');
-
-                $this->rc->output->show_message('enigma.keysimportsuccess', 'confirmation',
-                    array('new' => $result['imported'], 'old' => $result['unchanged']));
-
-                $this->rc->output->send('iframe');
-            }
-            else
-                $this->rc->output->show_message('enigma.keysimportfailed', 'error');
-        }
-        else if ($err = $_FILES['_file']['error']) {
-            if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
-                $this->rc->output->show_message('filesizeerror', 'error',
-                    array('size' => show_bytes(parse_bytes(ini_get('upload_max_filesize')))));
-            } else {
-                $this->rc->output->show_message('fileuploaderror', 'error');
-            }
-        }
-
-        $this->rc->output->add_handlers(array(
-            'importform' => array($this, 'tpl_key_import_form'),
-        ));
-
-        $this->rc->output->set_pagetitle($this->enigma->gettext('keyimport'));
-        $this->rc->output->send('enigma.keyimport');
-    }
-
-    /**
-     * Template object for key import (upload) form
-     */
-    function tpl_key_import_form($attrib)
-    {
-        $attrib += array('id' => 'rcmKeyImportForm');
-
-        $upload = new html_inputfield(array('type' => 'file', 'name' => '_file',
-            'id' => 'rcmimportfile', 'size' => 30));
-
-        $form = html::p(null,
-            Q($this->enigma->gettext('keyimporttext'), 'show')
-            . html::br() . html::br() . $upload->show()
-        );
-
-        $this->rc->output->add_label('selectimportfile', 'importwait');
-        $this->rc->output->add_gui_object('importform', $attrib['id']);
-
-        $out = $this->rc->output->form_tag(array(
-            'action' => $this->rc->url(array('action' => 'plugin.enigma', 'a' => 'keyimport')),
-            'method' => 'post',
-            'enctype' => 'multipart/form-data') + $attrib,
-            $form);
-
-        return $out;
-    }
-
-    private function compose_ui()
-    {
-        if (!is_array($_SESSION['compose']) || $_SESSION['compose']['id'] != get_input_value('_id', RCUBE_INPUT_GET))
-            return;
-
-        // Options menu button
-        // @TODO: make this work with non-default skins
-        $this->enigma->add_button(array(
-            'name' => 'enigmamenu',
-            'imagepas' => 'skins/default/enigma.png',
-            'imageact' => 'skins/default/enigma.png',
-            'onclick' => "rcmail_ui.show_popup('enigmamenu', true); return false",
-            'title' => 'securityoptions',
-            'domain' => 'enigma',
-            ), 'toolbar');
-
-        // Options menu contents
-        $this->enigma->add_hook('render_page', array($this, 'compose_menu'));
-    }
-
-    function compose_menu($p)
-    {
-        $menu = new html_table(array('cols' => 2));
-        $chbox = new html_checkbox(array('value' => 1));
-
-        $menu->add(null, html::label(array('for' => 'enigmadefaultopt'),
-            Q($this->enigma->gettext('identdefault'))));
-        $menu->add(null, $chbox->show(1, array('name' => '_enigma_default', 'id' => 'enigmadefaultopt')));
-
-        $menu->add(null, html::label(array('for' => 'enigmasignopt'),
-            Q($this->enigma->gettext('signmsg'))));
-        $menu->add(null, $chbox->show(1, array('name' => '_enigma_sign', 'id' => 'enigmasignopt')));
-
-        $menu->add(null, html::label(array('for' => 'enigmacryptopt'),
-            Q($this->enigma->gettext('encryptmsg'))));
-        $menu->add(null, $chbox->show(1, array('name' => '_enigma_crypt', 'id' => 'enigmacryptopt')));
-
-        $menu = html::div(array('id' => 'enigmamenu', 'class' => 'popupmenu'),
-            $menu->show());
-
-        $p['content'] = preg_replace('/(<form name="form"[^>]+>)/i', '\\1'."\n$menu", $p['content']);
-
-        return $p;
-
-    }
-
-}
diff --git a/plugins/enigma/lib/enigma_userid.php b/plugins/enigma/lib/enigma_userid.php
deleted file mode 100644
index 36185e7..0000000
--- a/plugins/enigma/lib/enigma_userid.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-/*
- +-------------------------------------------------------------------------+
- | User ID class for the Enigma Plugin                                     |
- |                                                                         |
- | This program is free software; you can redistribute it and/or modify    |
- | it under the terms of the GNU General Public License version 2          |
- | as published by the Free Software Foundation.                           |
- |                                                                         |
- | 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.             |
- |                                                                         |
- +-------------------------------------------------------------------------+
- | Author: Aleksander Machniak <alec@alec.pl>                              |
- +-------------------------------------------------------------------------+
-*/
-
-class enigma_userid
-{
-    public $revoked;
-    public $valid;
-    public $name;
-    public $comment;
-    public $email;
-}
diff --git a/plugins/enigma/localization/en_US.inc b/plugins/enigma/localization/en_US.inc
deleted file mode 100644
index e0f03d9..0000000
--- a/plugins/enigma/localization/en_US.inc
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-$labels = array();
-$labels['enigmasettings'] = 'Enigma: Settings';
-$labels['enigmacerts'] = 'Enigma: Certificates (S/MIME)';
-$labels['enigmakeys'] = 'Enigma: Keys (PGP)';
-$labels['keysfromto'] = 'Keys $from to $to of $count';
-$labels['keyname'] = 'Name';
-$labels['keyid'] = 'Key ID';
-$labels['keyuserid'] = 'User ID';
-$labels['keytype'] = 'Key type';
-$labels['fingerprint'] = 'Fingerprint';
-$labels['subkeys'] = 'Subkeys';
-$labels['basicinfo'] = 'Basic Information';
-$labels['userids'] = 'Additional User IDs';
-$labels['typepublickey'] = 'public key';
-$labels['typekeypair'] = 'key pair';
-$labels['keyattfound'] = 'This message contains attached PGP key(s).';
-$labels['keyattimport'] = 'Import key(s)';
-
-$labels['createkeys'] = 'Create a new key pair';
-$labels['importkeys'] = 'Import key(s)';
-$labels['exportkeys'] = 'Export key(s)';
-$labels['deletekeys'] = 'Delete key(s)';
-$labels['keyactions'] = 'Key actions...';
-$labels['keydisable'] = 'Disable key';
-$labels['keyrevoke'] = 'Revoke key';
-$labels['keysend'] = 'Send public key in a message';
-$labels['keychpass'] = 'Change password';
-
-$labels['securityoptions'] = 'Message security options...';
-$labels['identdefault'] = 'Use settings of selected identity';
-$labels['encryptmsg'] = 'Encrypt this message';
-$labels['signmsg'] = 'Digitally sign this message';
-
-$messages = array();
-$messages['sigvalid'] = 'Verified signature from $sender.';
-$messages['siginvalid'] = 'Invalid signature from $sender.';
-$messages['signokey'] = 'Unverified signature. Public key not found. Key ID: $keyid.';
-$messages['sigerror'] = 'Unverified signature. Internal error.';
-$messages['decryptok'] = 'Message decrypted.';
-$messages['decrypterror'] = 'Decryption failed.';
-$messages['decryptnokey'] = 'Decryption failed. Private key not found. Key ID: $keyid.';
-$messages['decryptbadpass'] = 'Decryption failed. Bad password.';
-$messages['nokeysfound'] = 'No keys found';
-$messages['keyopenerror'] = 'Unable to get key information! Internal error.';
-$messages['keylisterror'] = 'Unable to list keys! Internal error.';
-$messages['keysimportfailed'] = 'Unable to import key(s)! Internal error.';
-$messages['keysimportsuccess'] = 'Key(s) imported successfully. Imported: $new, unchanged: $old.';
-$messages['keyconfirmdelete'] = 'Are you sure, you want to delete selected key(s)?';
-$messages['keyimporttext'] = 'You can import private and public key(s) or revocation signatures in ASCII-Armor format.';
-
-?>
diff --git a/plugins/enigma/localization/ja_JP.inc b/plugins/enigma/localization/ja_JP.inc
deleted file mode 100644
index 8820144..0000000
--- a/plugins/enigma/localization/ja_JP.inc
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-//  EN-Revision: 4203
-
-$labels = array();
-$labels['enigmasettings'] = 'Enigma: 設定';
-$labels['enigmacerts'] = 'Enigma: 証明書 (S/MIME)';
-$labels['enigmakeys'] = 'Enigma: 鍵 (PGP)';
-$labels['keysfromto'] = '鍵の一覧 $from ~ $to (合計: $count )';
-$labels['keyname'] = '名前';
-$labels['keyid'] = '鍵 ID';
-$labels['keyuserid'] = 'ユーザー ID';
-$labels['keytype'] = '鍵の種類';
-$labels['fingerprint'] = '指紋';
-$labels['subkeys'] = 'Subkeys';
-$labels['basicinfo'] = '基本情報';
-$labels['userids'] = '追加のユーザー ID';
-$labels['typepublickey'] = '公開鍵';
-$labels['typekeypair'] = '鍵のペア';
-$labels['keyattfound'] = 'このメールは PGP 鍵の添付があります。';
-$labels['keyattimport'] = '鍵のインポート';
-
-$labels['createkeys'] = '新しい鍵のペアを作成する';
-$labels['importkeys'] = '鍵のインポート';
-$labels['exportkeys'] = '鍵のエクスポート';
-$labels['deletekeys'] = '鍵の削除';
-$labels['keyactions'] = '鍵の操作...';
-$labels['keydisable'] = '鍵を無効にする';
-$labels['keyrevoke'] = '鍵を取り消す';
-$labels['keysend'] = 'メッセージに公開鍵を含んで送信する';
-$labels['keychpass'] = 'パスワードの変更';
-
-$labels['securityoptions'] = 'メールのセキュリティ オプション...';
-$labels['identdefault'] = '選択した識別子の設定を使う';
-$labels['encryptmsg'] = 'このメールの暗号化';
-$labels['signmsg'] = 'このメールのデジタル署名';
-
-$messages = array();
-$messages['sigvalid'] = '$sender からの署名を検証しました。';
-$messages['siginvalid'] = '$sender からの署名が正しくありません。';
-$messages['signokey'] = '署名は未検証です。公開鍵が見つかりません。鍵 ID: $keyid';
-$messages['sigerror'] = '署名は未検証です。内部エラーです。';
-$messages['decryptok'] = 'メールを復号しました。';
-$messages['decrypterror'] = '復号に失敗しました。';
-$messages['decryptnokey'] = '復号に失敗しました。秘密鍵が見つかりません。鍵 ID: $keyid.';
-$messages['decryptbadpass'] = '復号に失敗しました。パスワードが正しくありません。';
-$messages['nokeysfound'] = '鍵が見つかりません。';
-$messages['keyopenerror'] = '鍵情報の取得に失敗しました! 内部エラーです。';
-$messages['keylisterror'] = '鍵情報のリストに失敗しました! 内部エラーです。';
-$messages['keysimportfailed'] = '鍵のインポートに失敗しました! 内部エラーです。';
-$messages['keysimportsuccess'] = '鍵をインポートしました。インポート: $new, 未変更: $old';
-$messages['keyconfirmdelete'] = '選択した鍵を本当に削除しますか?';
-$messages['keyimporttext'] = '秘密鍵と公開鍵のインポート、または ASCII 形式の署名を無効にできます。';
-
-?>
diff --git a/plugins/enigma/skins/default/enigma.css b/plugins/enigma/skins/default/enigma.css
deleted file mode 100644
index b1c656f..0000000
--- a/plugins/enigma/skins/default/enigma.css
+++ /dev/null
@@ -1,182 +0,0 @@
-/*** Style for Enigma plugin ***/
-
-/***** Messages displaying *****/
-
-#enigma-message,
-/* fixes border-top */
-#messagebody div #enigma-message
-{
-  margin: 0;
-  margin-bottom: 5px;
-  min-height: 20px;
-  padding: 10px 10px 6px 46px;
-}
-
-div.enigmaerror,
-/* fixes border-top */
-#messagebody div.enigmaerror
-{
-  background: url(enigma_error.png) 6px 1px no-repeat;
-  background-color: #EF9398;
-  border: 1px solid #DC5757;
-}
-
-div.enigmanotice,
-/* fixes border-top */
-#messagebody div.enigmanotice
-{
-  background: url(enigma.png) 6px 1px no-repeat;
-  background-color: #A6EF7B;
-  border: 1px solid #76C83F;
-}
-
-div.enigmawarning,
-/* fixes border-top */
-#messagebody div.enigmawarning
-{
-  background: url(enigma.png) 6px 1px no-repeat;
-  background-color: #F7FDCB;
-  border: 1px solid #C2D071;
-}
-
-#enigma-message a
-{
-  color: #666666;
-  padding-left: 10px;
-}
-
-#enigma-message a:hover
-{
-  color: #333333;
-}
-
-/***** Keys/Certs Management *****/
-
-div.enigmascreen
-{
-  position: absolute;
-  top: 65px;
-  right: 10px;
-  bottom: 10px;
-  left: 10px;
-}
-
-#enigmacontent-box
-{
-  position: absolute;
-  top: 0px;
-  left: 290px;
-  right: 0px;
-  bottom: 0px;
-  border: 1px solid #999999;
-  overflow: hidden;
-}
-
-#enigmakeyslist
-{
-  position: absolute;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  border: 1px solid #999999;
-  background-color: #F9F9F9;
-  overflow: hidden;
-}
-
-#keylistcountbar
-{
-  margin-top: 4px;
-  margin-left: 4px;
-}
-
-#keys-table
-{
-  width: 100%;
-  table-layout: fixed;
-}
-
-#keys-table td
-{
-  cursor: default;
-  text-overflow: ellipsis;
-  -o-text-overflow: ellipsis;
-}
-
-#key-details table td.title
-{
-  font-weight: bold;
-  text-align: right;
-}
-
-#keystoolbar
-{
-  position: absolute;
-  top: 30px;
-  left: 10px;
-  height: 35px;
-}
-
-#keystoolbar a
-{
-  padding-right: 10px;
-}
-
-#keystoolbar a.button,
-#keystoolbar a.buttonPas,
-#keystoolbar span.separator {
-  display: block;
-  float: left;
-  width: 32px;
-  height: 32px;
-  padding: 0;
-  margin-right: 10px;
-  overflow: hidden;
-  background: url(keys_toolbar.png) 0 0 no-repeat transparent;
-  opacity: 0.99; /* this is needed to make buttons appear correctly in Chrome */
-}
-
-#keystoolbar a.buttonPas {
-  opacity: 0.35;
-}
-
-#keystoolbar a.createSel {
-  background-position: 0 -32px;
-}
-
-#keystoolbar a.create {
-  background-position: 0 0;
-}
-
-#keystoolbar a.deleteSel {
-  background-position: -32px -32px;
-}
-
-#keystoolbar a.delete {
-  background-position: -32px 0;
-}
-
-#keystoolbar a.importSel {
-  background-position: -64px -32px;
-}
-
-#keystoolbar a.import {
-  background-position: -64px 0;
-}
-
-#keystoolbar a.exportSel {
-  background-position: -96px -32px;
-}
-
-#keystoolbar a.export {
-  background-position: -96px 0;
-}
-
-#keystoolbar a.keymenu {
-  background-position: -128px 0;
-  width: 36px;
-}
-
-#keystoolbar span.separator {
-  width: 5px;
-  background-position: -166px 0;
-}
diff --git a/plugins/enigma/skins/default/enigma.png b/plugins/enigma/skins/default/enigma.png
deleted file mode 100644
index 3ef106e..0000000
--- a/plugins/enigma/skins/default/enigma.png
+++ /dev/null
Binary files differ
diff --git a/plugins/enigma/skins/default/enigma_error.png b/plugins/enigma/skins/default/enigma_error.png
deleted file mode 100644
index 9bf100e..0000000
--- a/plugins/enigma/skins/default/enigma_error.png
+++ /dev/null
Binary files differ
diff --git a/plugins/enigma/skins/default/key.png b/plugins/enigma/skins/default/key.png
deleted file mode 100644
index ea1cbd1..0000000
--- a/plugins/enigma/skins/default/key.png
+++ /dev/null
Binary files differ
diff --git a/plugins/enigma/skins/default/key_add.png b/plugins/enigma/skins/default/key_add.png
deleted file mode 100644
index f22cc87..0000000
--- a/plugins/enigma/skins/default/key_add.png
+++ /dev/null
Binary files differ
diff --git a/plugins/enigma/skins/default/keys_toolbar.png b/plugins/enigma/skins/default/keys_toolbar.png
deleted file mode 100644
index 7cc258c..0000000
--- a/plugins/enigma/skins/default/keys_toolbar.png
+++ /dev/null
Binary files differ
diff --git a/plugins/enigma/skins/default/templates/keyimport.html b/plugins/enigma/skins/default/templates/keyimport.html
deleted file mode 100644
index 4e0b304..0000000
--- a/plugins/enigma/skins/default/templates/keyimport.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title><roundcube:object name="pagetitle" /></title>
-<roundcube:include file="/includes/links.html" />
-<link rel="stylesheet" type="text/css" href="/this/enigma.css" />
-</head>
-<body class="iframe">
-
-<div id="keyimport-title" class="boxtitle"><roundcube:label name="enigma.importkeys" /></div>
-
-<div id="import-form" class="boxcontent">
-    <roundcube:object name="importform" />
-    <p>
-        <br /><roundcube:button command="plugin.enigma-import" type="input" class="button mainaction" label="import" />
-    </p>
-</div>
-
-</body>
-</html>
diff --git a/plugins/enigma/skins/default/templates/keyinfo.html b/plugins/enigma/skins/default/templates/keyinfo.html
deleted file mode 100644
index 2e8ed61..0000000
--- a/plugins/enigma/skins/default/templates/keyinfo.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title><roundcube:object name="pagetitle" /></title>
-<roundcube:include file="/includes/links.html" />
-<link rel="stylesheet" type="text/css" href="/this/enigma.css" />
-</head>
-<body class="iframe">
-
-<div id="keyinfo-title" class="boxtitle"><roundcube:object name="keyname" part="name" /></div>
-
-<div id="key-details" class="boxcontent">
-    <roundcube:object name="keydata" />
-</div>
-
-</body>
-</html>
diff --git a/plugins/enigma/skins/default/templates/keys.html b/plugins/enigma/skins/default/templates/keys.html
deleted file mode 100644
index 810c4a2..0000000
--- a/plugins/enigma/skins/default/templates/keys.html
+++ /dev/null
@@ -1,76 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title><roundcube:object name="pagetitle" /></title>
-<roundcube:include file="/includes/links.html" />
-<link rel="stylesheet" type="text/css" href="/this/enigma.css" />
-<script type="text/javascript" src="/functions.js"></script>
-<script type="text/javascript" src="/splitter.js"></script>
-<style type="text/css">                                                                                                                      
-#enigmakeyslist { width: <roundcube:exp expression="!empty(cookie:enigmaviewsplitter) ? cookie:enigmaviewsplitter-5 : 210" />px; }
-#enigmacontent-box { left: <roundcube:exp expression="!empty(cookie:enigmaviewsplitter) ? cookie:enigmaviewsplitter+5 : 220" />px;
-<roundcube:exp expression="browser:ie ? ('width:expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:enigmaeviewsplitter) ? cookie:enigmaviewsplitter+5 : 220).')+\\'px\\');') : ''" />
-}
-</style>
-</head>
-<body class="iframe" onload="rcube_init_mail_ui()">
-
-<div id="prefs-title" class="boxtitle"><roundcube:label name="enigma.enigmakeys" /></div>
-<div id="prefs-details" class="boxcontent">
-
-<div id="keystoolbar">
-    <roundcube:button command="plugin.enigma-key-create" type="link" class="buttonPas create" classAct="button create" classSel="button createSel" title="enigma.createkeys" content=" " />
-    <roundcube:button command="plugin.enigma-key-delete" type="link" class="buttonPas delete" classAct="button delete" classSel="button deleteSel" title="enigma.deletekeys" content=" " />
-    <span class="separator">&nbsp;</span>
-    <roundcube:button command="plugin.enigma-key-import" type="link" class="buttonPas import" classAct="button import" classSel="button importSel" title="enigma.importkeys" content=" " />
-    <roundcube:button command="plugin.enigma-key-export" type="link" class="buttonPas export" classAct="button export" classSel="button exportSel" title="enigma.exportkeys" content=" " />
-    <roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="button keymenu" title="enigma.keyactions" onclick="rcmail_ui.show_popup('messagemenu');return false" content=" " />
-</div>
-
-<div id="quicksearchbar" style="top: 35px; right: 10px;">
-    <roundcube:button name="searchmenulink" id="searchmenulink" image="/images/icons/glass.png" />
-    <roundcube:object name="searchform" id="quicksearchbox" />
-    <roundcube:button command="reset-search" id="searchreset" image="/images/icons/reset.gif" title="resetsearch" />
-</div>
-
-<div class="enigmascreen">
-
-<div id="enigmakeyslist">
-<div class="boxtitle"><roundcube:label name="enigma.keyname" /></div>
-<div class="boxlistcontent">
-    <roundcube:object name="keyslist" id="keys-table" class="records-table" cellspacing="0" noheader="true" />
-</div>
-<div class="boxfooter">
-<div id="keylistcountbar" class="pagenav">
-    <roundcube:button command="firstpage" type="link" class="buttonPas firstpage" classAct="button firstpage" classSel="button firstpageSel" title="firstpage" content=" " />
-    <roundcube:button command="previouspage" type="link" class="buttonPas prevpage" classAct="button prevpage" classSel="button prevpageSel" title="previouspage" content=" " />
-    <roundcube:object name="countdisplay" style="padding:0 .5em; float:left" />
-    <roundcube:button command="nextpage" type="link" class="buttonPas nextpage" classAct="button nextpage" classSel="button nextpageSel" title="nextpage" content=" " />
-    <roundcube:button command="lastpage" type="link" class="buttonPas lastpage" classAct="button lastpage" classSel="button lastpageSel" title="lastpage" content=" " />
-</div>
-</div>
-</div>
-
-<script type="text/javascript">
-    var enigmaviewsplit = new rcube_splitter({id:'enigmaviewsplitter', p1: 'enigmakeyslist', p2: 'enigmacontent-box', orientation: 'v', relative: true, start: 215});
-    rcmail.add_onload('enigmaviewsplit.init()');
-</script>
-
-<div id="enigmacontent-box">
-    <roundcube:object name="keyframe" id="keyframe" width="100%" height="100%" frameborder="0" src="/watermark.html" />
-</div>
-
-</div>
-</div>
-
-<div id="messagemenu" class="popupmenu">
-    <ul class="toolbarmenu">
-        <li><roundcube:button class="disablelink" command="enigma.key-disable" label="enigma.keydisable" target="_blank" classAct="disablelink active" /></li>
-        <li><roundcube:button class="revokelink" command="enigma.key-revoke" label="enigma.keyrevoke" classAct="revokelink active" /></li>
-        <li class="separator_below"><roundcube:button class="sendlink" command="enigma.key-send" label="enigma.keysend" classAct="sendlink active" /></li>
-        <li><roundcube:button class="chpasslink" command="enigma.key-chpass" label="enigma.keychpass" classAct="chpasslink active" /></li>
-    </ul>
-</div>
-
-</body>
-</html>
diff --git a/plugins/kolab_addressbook/kolab_addressbook.php b/plugins/kolab_addressbook/kolab_addressbook.php
deleted file mode 100644
index edf8e1f..0000000
--- a/plugins/kolab_addressbook/kolab_addressbook.php
+++ /dev/null
@@ -1,140 +0,0 @@
-<?php
-
-require_once(dirname(__FILE__) . '/rcube_kolab_contacts.php');
-
-/**
- * Kolab address book
- * 
- * Sample plugin to add a new address book source with data from Kolab storage
- * This is work-in-progress for the Roundcube+Kolab integration.
- *
- * @author Thomas Bruederli <roundcube@gmail.com>
- * 
- */
-class kolab_addressbook extends rcube_plugin
-{
-    private $folders;
-    private $sources;
-
-    /**
-     * Required startup method of a Roundcube plugin
-     */
-    public function init()
-    {
-        // load required plugin
-        $this->require_plugin('kolab_core');
-        
-        $this->add_texts('localization');
-        
-        // register hooks
-        $this->add_hook('addressbooks_list', array($this, 'address_sources'));
-        $this->add_hook('addressbook_get', array($this, 'get_address_book'));
-        $this->add_hook('contact_form', array($this, 'contact_form'));
-        
-        // extend list of address sources to be used for autocompletion
-        $rcmail = rcmail::get_instance();
-        if ($rcmail->action == 'autocomplete' || $rcmail->action == 'group-expand') {
-            $sources = (array) $rcmail->config->get('autocomplete_addressbooks', array());
-            foreach ($this->_list_sources() as $abook_id => $abook) {
-                if (!in_array($abook_id, $sources))
-                    $sources[] = $abook_id;
-            }
-            $rcmail->config->set('autocomplete_addressbooks', $sources);
-        }
-    }
-
-    /**
-     * Handler for the addressbooks_list hook.
-     *
-     * This will add all instances of available Kolab-based address books
-     * to the list of address sources of Roundcube.
-     *
-     * @param array Hash array with hook parameters
-     * @return array Hash array with modified hook parameters
-     */
-    public function address_sources($p)
-    {
-        foreach ($this->_list_sources() as $abook_id => $abook) {
-            // register this address source
-            $p['sources'][$abook_id] = array(
-                'id' => $abook_id,
-                'name' => $abook->get_name(),
-                'readonly' => $abook->readonly,
-                'groups' => $abook->groups,
-            );
-        }
-
-        return $p;
-    }
-
-
-    /**
-     * Getter for the rcube_addressbook instance
-     */
-    public function get_address_book($p)
-    {
-        if ($this->sources[$p['id']]) {
-            $p['instance'] = $this->sources[$p['id']];
-        }
-        
-        return $p;
-    }
-    
-    
-    private function _list_sources()
-    {
-        // already read sources
-        if (isset($this->sources))
-            return $this->sources;
-
-        // get all folders that have "contact" type
-        $this->folders = rcube_kolab::get_folders('contact');
-        $this->sources = array();
-
-        if (PEAR::isError($this->folders)) {
-            raise_error(array(
-              'code' => 600, 'type' => 'php',
-              'file' => __FILE__, 'line' => __LINE__,
-              'message' => "Failed to list contact folders from Kolab server:" . $this->folders->getMessage()),
-            true, false);
-        }
-        else {
-            foreach ($this->folders as $c_folder) {
-                // create instance of rcube_contacts
-                $abook_id = strtolower(asciiwords(strtr($c_folder->name, '/.', '--')));
-                $abook = new rcube_kolab_contacts($c_folder->name);
-                $this->sources[$abook_id] = $abook;
-            }
-        }
-        
-        return $this->sources;
-    }
-    
-    
-    /**
-     * Plugin hook called before rendering the contact form or detail view
-     */
-    public function contact_form($p)
-    {
-        // extend the list of contact fields to be displayed in the 'info' section
-        if (is_array($p['form']['info'])) {
-            $p['form']['info']['content']['initials'] = array('size' => 6);
-            $p['form']['info']['content']['anniversary'] = array('size' => 12, 'render_func' => 'rcmail_format_date_col');
-            
-            // TODO: add more Kolab-specific fields
-            
-            // re-order fields according to the coltypes list
-            $block = array();
-            $contacts = reset($this->sources);
-            foreach ($contacts->coltypes as $col => $prop) {
-                if (isset($p['form']['info']['content'][$col]))
-                    $block[$col] = $p['form']['info']['content'][$col];
-            }
-            
-            $p['form']['info']['content'] = $block;
-        }
-        
-        return $p;
-    }
-
-}
diff --git a/plugins/kolab_addressbook/localization/en_US.inc b/plugins/kolab_addressbook/localization/en_US.inc
deleted file mode 100644
index d22318b..0000000
--- a/plugins/kolab_addressbook/localization/en_US.inc
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-
-$labels = array();
-$labels['initials'] = 'Initials';
-$labels['anniversary'] = 'Anniversary';
-
-?>
\ No newline at end of file
diff --git a/plugins/kolab_addressbook/rcube_kolab_contacts.php b/plugins/kolab_addressbook/rcube_kolab_contacts.php
deleted file mode 100644
index 5e5646e..0000000
--- a/plugins/kolab_addressbook/rcube_kolab_contacts.php
+++ /dev/null
@@ -1,829 +0,0 @@
-<?php
-
-
-/**
- * Backend class for a custom address book
- *
- * This part of the Roundcube+Kolab integration and connects the
- * rcube_addressbook interface with the rcube_kolab wrapper for Kolab_Storage
- *
- * @author Thomas Bruederli
- * @see rcube_addressbook
- */
-class rcube_kolab_contacts extends rcube_addressbook
-{
-    public $primary_key = 'ID';
-    public $readonly = false;
-    public $groups = true;
-    public $coltypes = array(
-      'name'         => array('limit' => 1),
-      'firstname'    => array('limit' => 1),
-      'surname'      => array('limit' => 1),
-      'middlename'   => array('limit' => 1),
-      'prefix'       => array('limit' => 1),
-      'suffix'       => array('limit' => 1),
-      'nickname'     => array('limit' => 1),
-      'jobtitle'     => array('limit' => 1),
-      'organization' => array('limit' => 1),
-      'department'   => array('limit' => 1),
-      'gender'       => array('limit' => 1),
-      'initials'     => array('type' => 'text', 'size' => 6, 'limit' => 1, 'label' => 'kolab_addressbook.initials'),
-      'email'        => array('subtypes' => null),
-      'phone'        => array(),
-      'im'           => array('limit' => 1),
-      'website'      => array('limit' => 1, 'subtypes' => null),
-      'address'      => array('limit' => 2, 'subtypes' => array('home','business')),
-      'birthday'     => array('limit' => 1),
-      'anniversary'  => array('type' => 'date', 'size' => 12, 'limit' => 1, 'label' => 'kolab_addressbook.anniversary'),
-      // TODO: define more Kolab-specific fields such as: office-location, profession, manager-name, assistant, spouse-name, children, language, latitude, longitude, pgp-publickey, free-busy-url
-      'notes'        => array(),
-    );
-    
-    private $gid;
-    private $imap;
-    private $kolab;
-    private $folder;
-    private $contactstorage;
-    private $liststorage;
-    private $contacts;
-    private $distlists;
-    private $groupmembers;
-    private $id2uid;
-    private $filter;
-    private $result;
-    private $imap_folder = 'INBOX/Contacts';
-    private $gender_map = array(0 => 'male', 1 => 'female');
-    private $phonetypemap = array('home' => 'home1', 'work' => 'business1', 'work2' => 'business2', 'workfax' => 'businessfax');
-    private $addresstypemap = array('work' => 'business');
-    private $fieldmap = array(
-      // kolab       => roundcube
-      'full-name'    => 'name',
-      'given-name'   => 'firstname',
-      'middle-names' => 'middlename',
-      'last-name'    => 'surname',
-      'prefix'       => 'prefix',
-      'suffix'       => 'suffix',
-      'nick-name'    => 'nickname',
-      'organization' => 'organization',
-      'department'   => 'department',
-      'job-title'    => 'jobtitle',
-      'initials'     => 'initials',
-      'birthday'     => 'birthday',
-      'anniversary'  => 'anniversary',
-      'im-address'   => 'im:aim',
-      'web-page'     => 'website',
-      'body'         => 'notes',
-    );
-
-
-    public function __construct($imap_folder = null)
-    {
-        if ($imap_folder)
-            $this->imap_folder = $imap_folder;
-            
-        // extend coltypes configuration 
-        $format = rcube_kolab::get_format('contact');
-        $this->coltypes['phone']['subtypes'] = $format->_phone_types;
-        $this->coltypes['address']['subtypes'] = $format->_address_types;
-        
-        // set localized labels for proprietary cols
-        foreach ($this->coltypes as $col => $prop) {
-            if (is_string($prop['label']))
-                $this->coltypes[$col]['label'] = rcube_label($prop['label']);
-        }
-        
-        // fetch objects from the given IMAP folder
-        $this->contactstorage = rcube_kolab::get_storage($this->imap_folder);
-        $this->liststorage = rcube_kolab::get_storage($this->imap_folder, 'distributionlist');
-
-        $this->ready = !PEAR::isError($this->contactstorage) && !PEAR::isError($this->liststorage);
-    }
-
-
-    /**
-     * Getter for the address book name to be displayed
-     *
-     * @return string Name of this address book
-     */
-    public function get_name()
-    {
-        return strtr(preg_replace('!^(INBOX|user)/!i', '', $this->imap_folder), '/', ':');
-    }
-
-
-    /**
-     * Setter for the current group
-     */
-    public function set_group($gid)
-    {
-        $this->gid = $gid;
-    }
-
-
-    /**
-     * Save a search string for future listings
-     *
-     * @param mixed Search params to use in listing method, obtained by get_search_set()
-     */
-    public function set_search_set($filter)
-    {
-        $this->filter = $filter;
-    }
-
-
-    /**
-     * Getter for saved search properties
-     *
-     * @return mixed Search properties used by this class
-     */
-    public function get_search_set()
-    {
-        return $this->filter;
-    }
-
-
-    /**
-     * Reset saved results and search parameters
-     */
-    public function reset()
-    {
-        $this->result = null;
-        $this->filter = null;
-    }
-
-
-    /**
-     * List all active contact groups of this source
-     *
-     * @param string  Optional search string to match group name
-     * @return array  Indexed list of contact groups, each a hash array
-     */
-    function list_groups($search = null)
-    {
-        $this->_fetch_groups();
-        $groups = array();
-        foreach ((array)$this->distlists as $group) {
-            if (!$search || strstr(strtolower($group['last-name']), strtolower($search)))
-                $groups[] = array('ID' => $group['ID'], 'name' => $group['last-name']);
-        }
-        return $groups;
-    }
-
-    /**
-     * List the current set of contact records
-     *
-     * @param  array  List of cols to show
-     * @param  int    Only return this number of records, use negative values for tail
-     * @return array  Indexed list of contact records, each a hash array
-     */
-    public function list_records($cols=null, $subset=0)
-    {
-        $this->result = $this->count();
-        
-        // list member of the selected group
-        if ($this->gid) {
-            $seen = array();
-            $this->result->count = 0;
-            foreach ((array)$this->distlists[$this->gid]['member'] as $member) {
-                // skip member that don't match the search filter
-                if ($this->filter && array_search($member['ID'], $this->filter) === false)
-                    continue;
-                if ($this->contacts[$member['ID']] && !$seen[$member['ID']]++)
-                    $this->result->count++;
-            }
-            $ids = array_keys($seen);
-        }
-        else
-            $ids = $this->filter ? $this->filter : array_keys($this->contacts);
-        
-        // fill contact data into the current result set
-        $i = $j = 0;
-        foreach ($ids as $id) {
-            if ($i++ < $this->result->first)
-                continue;
-            $this->result->add($this->contacts[$id]);
-            if (++$j == $this->page_size)
-                break;
-        }
-        
-        return $this->result;
-    }
-
-
-    /**
-     * Search records
-     *
-     * @param array   List of fields to search in
-     * @param string  Search value
-     * @param boolean True if results are requested, False if count only
-     * @param boolean True to skip the count query (select only)
-     * @param array   List of fields that cannot be empty
-     * @return object rcube_result_set List of contact records and 'count' value
-     */
-    public function search($fields, $value, $strict=false, $select=true, $nocount=false, $required=array())
-    {
-        $this->_fetch_contacts();
-        
-        // search by ID
-        if ($fields == $this->primary_key) {
-            return $this->get_record($value);
-        }
-
-        $value = strtolower($value);
-        if (!is_array($fields))
-            $fields = array($fields);
-        if (!is_array($required) && !empty($required))
-            $required = array($required);
-        
-        $this->filter = array();
-        
-        // search be iterating over all records in memory
-        foreach ($this->contacts as $id => $contact) {
-            // check if current contact has required values, otherwise skip it
-            if ($required) {
-                foreach ($required as $f)
-                    if (empty($contact[$f]))
-                        continue 2;
-            }
-            foreach ($fields as $f) {
-                foreach ((array)$contact[$f] as $val) {
-                    $val = strtolower($val);
-                    if (($strict && $val == $value) || (!$strict && strstr($val, $value))) {
-                        $this->filter[] = $id;
-                        break 2;
-                    }
-                }
-            }
-        }
-
-        // list records (now limited by $this->filter)
-        return $this->list_records();
-    }
-
-
-    /**
-     * Count number of available contacts in database
-     *
-     * @return rcube_result_set Result set with values for 'count' and 'first'
-     */
-    public function count()
-    {
-        $this->_fetch_contacts();
-        $this->_fetch_groups();
-        $count = $this->gid ? count($this->distlists[$this->gid]['member']) : ($this->filter ? count($this->filter) : count($this->contacts));
-        return new rcube_result_set($count, ($this->list_page-1) * $this->page_size);
-    }
-
-
-    /**
-     * Return the last result set
-     *
-     * @return rcube_result_set Current result set or NULL if nothing selected yet
-     */
-    public function get_result()
-    {
-        return $this->result;
-    }
-
-    /**
-     * Get a specific contact record
-     *
-     * @param mixed record identifier(s)
-     * @param boolean True to return record as associative array, otherwise a result set is returned
-     * @return mixed Result object with all record fields or False if not found
-     */
-    public function get_record($id, $assoc=false)
-    {
-        $this->_fetch_contacts();
-        if ($this->contacts[$id]) {
-            $this->result = new rcube_result_set(1);
-            $this->result->add($this->contacts[$id]);
-            return $assoc ? $this->contacts[$id] : $this->result;
-        }
-
-        return false;
-    }
-
-
-    /**
-     * Get group assignments of a specific contact record
-     *
-     * @param mixed Record identifier
-     * @return array List of assigned groups as ID=>Name pairs
-     */
-    public function get_record_groups($id)
-    {
-        $out = array();
-        $this->_fetch_groups();
-        
-        foreach ((array)$this->groupmembers[$id] as $gid) {
-            if ($group = $this->distlists[$gid])
-                $out[$gid] = $group['last-name'];
-        }
-        
-        return $out;
-    }
-
-
-    /**
-     * Create a new contact record
-     *
-     * @param array Assoziative array with save data
-     *  Keys:   Field name with optional section in the form FIELD:SECTION
-     *  Values: Field value. Can be either a string or an array of strings for multiple values
-     * @param boolean True to check for duplicates first
-     * @return mixed The created record ID on success, False on error
-     */
-    public function insert($save_data, $check=false)
-    {
-        if (!is_array($save_data))
-            return false;
-
-        $insert_id = $existing = false;
-
-        // check for existing records by e-mail comparison
-        if ($check) {
-            foreach ($this->get_col_values('email', $save_data, true) as $email) {
-                if (($res = $this->search('email', $email, true, false)) && $res->count) {
-                    $existing = true;
-                    break;
-                }
-            }
-        }
-        
-        if (!$existing) {
-            // generate new Kolab contact item
-            $object = $this->_from_rcube_contact($save_data);
-            $object['uid'] = $this->contactstorage->generateUID();
-
-            $saved = $this->contactstorage->save($object);
-
-            if (PEAR::isError($saved)) {
-                raise_error(array(
-                  'code' => 600, 'type' => 'php',
-                  'file' => __FILE__, 'line' => __LINE__,
-                  'message' => "Error saving contact object to Kolab server:" . $saved->getMessage()),
-                true, false);
-            }
-            else {
-                $contact = $this->_to_rcube_contact($object);
-                $id = $contact['ID'];
-                $this->contacts[$id] = $contact;
-                $this->id2uid[$id] = $object['uid'];
-                $insert_id = $id;
-            }
-        }
-        
-        return $insert_id;
-    }
-
-
-    /**
-     * Update a specific contact record
-     *
-     * @param mixed Record identifier
-     * @param array Assoziative array with save data
-     *  Keys:   Field name with optional section in the form FIELD:SECTION
-     *  Values: Field value. Can be either a string or an array of strings for multiple values
-     * @return boolean True on success, False on error
-     */
-    public function update($id, $save_data)
-    {
-        $updated = false;
-        $this->_fetch_contacts();
-        if ($this->contacts[$id] && ($uid = $this->id2uid[$id])) {
-            $old = $this->contactstorage->getObject($uid);
-            $object = array_merge($old, $this->_from_rcube_contact($save_data));
-
-            $saved = $this->contactstorage->save($object, $uid);
-            if (PEAR::isError($saved)) {
-                raise_error(array(
-                  'code' => 600, 'type' => 'php',
-                  'file' => __FILE__, 'line' => __LINE__,
-                  'message' => "Error saving contact object to Kolab server:" . $saved->getMessage()),
-                true, false);
-            }
-            else {
-                $this->contacts[$id] = $this->_to_rcube_contact($object);
-                $updated = true;
-            }
-        }
-        
-        return $updated;
-    }
-
-    /**
-     * Mark one or more contact records as deleted
-     *
-     * @param array  Record identifiers
-     */
-    public function delete($ids)
-    {
-        $this->_fetch_contacts();
-        $this->_fetch_groups();
-        
-        if (!is_array($ids))
-            $ids = explode(',', $ids);
-
-        $count = 0;
-        foreach ($ids as $id) {
-            if ($uid = $this->id2uid[$id]) {
-                $deleted = $this->contactstorage->delete($uid);
-
-                if (PEAR::isError($deleted)) {
-                    raise_error(array(
-                      'code' => 600, 'type' => 'php',
-                      'file' => __FILE__, 'line' => __LINE__,
-                      'message' => "Error deleting a contact object from the Kolab server:" . $deleted->getMessage()),
-                    true, false);
-                }
-                else {
-                    // remove from distribution lists
-                    foreach ((array)$this->groupmembers[$id] as $gid)
-                        $this->remove_from_group($gid, $id);
-                    
-                    // clear internal cache
-                    unset($this->contacts[$id], $this->id2uid[$id], $this->groupmembers[$id]);
-                    $count++;
-                }
-            }
-        }
-        
-        return $count;
-    }
-
-    /**
-     * Remove all records from the database
-     */
-    public function delete_all()
-    {
-        if (!PEAR::isError($this->contactstorage->deleteAll())) {
-            $this->contacts = array();
-            $this->id2uid = array();
-            $this->result = null;
-        }
-    }
-
-    
-    /**
-     * Close connection to source
-     * Called on script shutdown
-     */
-    public function close()
-    {
-        rcube_kolab::shutdown();
-    }
-
-
-    /**
-     * Create a contact group with the given name
-     *
-     * @param string The group name
-     * @return mixed False on error, array with record props in success
-     */
-    function create_group($name)
-    {
-        $this->_fetch_groups();
-        $result = false;
-        
-        $list = array(
-            'uid' => $this->liststorage->generateUID(),
-            'last-name' => $name,
-            'member' => array(),
-        );
-        $saved = $this->liststorage->save($list);
-
-        if (PEAR::isError($saved)) {
-            raise_error(array(
-              'code' => 600, 'type' => 'php',
-              'file' => __FILE__, 'line' => __LINE__,
-              'message' => "Error saving distribution-list object to Kolab server:" . $saved->getMessage()),
-            true, false);
-            return false;
-        }
-        else {
-            $id = md5($list['uid']);
-            $this->distlists[$record['ID']] = $list;
-            $result = array('id' => $id, 'name' => $name);
-        }
-
-        return $result;
-    }
-
-    /**
-     * Delete the given group and all linked group members
-     *
-     * @param string Group identifier
-     * @return boolean True on success, false if no data was changed
-     */
-    function delete_group($gid)
-    {
-        $this->_fetch_groups();
-        $result = false;
-        
-        if ($list = $this->distlists[$gid])
-            $deleted = $this->liststorage->delete($list['uid']);
-
-        if (PEAR::isError($deleted)) {
-            raise_error(array(
-              'code' => 600, 'type' => 'php',
-              'file' => __FILE__, 'line' => __LINE__,
-              'message' => "Error deleting distribution-list object from the Kolab server:" . $deleted->getMessage()),
-            true, false);
-        }
-        else
-            $result = true;
-        
-        return $result;
-    }
-
-    /**
-     * Rename a specific contact group
-     *
-     * @param string Group identifier
-     * @param string New name to set for this group
-     * @return boolean New name on success, false if no data was changed
-     */
-    function rename_group($gid, $newname)
-    {
-        $this->_fetch_groups();
-        $list = $this->distlists[$gid];
-        
-        if ($newname != $list['last-name']) {
-            $list['last-name'] = $newname;
-            $saved = $this->liststorage->save($list, $list['uid']);
-        }
-
-        if (PEAR::isError($saved)) {
-            raise_error(array(
-              'code' => 600, 'type' => 'php',
-              'file' => __FILE__, 'line' => __LINE__,
-              'message' => "Error saving distribution-list object to Kolab server:" . $saved->getMessage()),
-            true, false);
-            return false;
-        }
-
-        return $newname;
-    }
-
-    /**
-     * Add the given contact records the a certain group
-     *
-     * @param string  Group identifier
-     * @param array   List of contact identifiers to be added
-     * @return int    Number of contacts added
-     */
-    function add_to_group($gid, $ids)
-    {
-        if (!is_array($ids))
-            $ids = explode(',', $ids);
-
-        $added = 0;
-        $exists = array();
-        
-        $this->_fetch_groups();
-        $this->_fetch_contacts();
-        $list = $this->distlists[$gid];
-
-        foreach ((array)$list['member'] as $i => $member)
-            $exists[] = $member['ID'];
-        
-        // substract existing assignments from list
-        $ids = array_diff($ids, $exists);
-
-        foreach ($ids as $contact_id) {
-            if ($uid = $this->id2uid[$contact_id]) {
-                $contact = $this->contacts[$contact_id];
-                foreach ($this->get_col_values('email', $contact, true) as $email) {
-                    $list['member'][] = array(
-                        'uid' => $uid,
-                        'display-name' => $contact['name'],
-                        'smtp-address' => $email,
-                    );
-                }
-                $this->groupmembers[$contact_id][] = $gid;
-                $added++;
-            }
-        }
-        
-        if ($added)
-            $saved = $this->liststorage->save($list, $list['uid']);
-        
-        if (PEAR::isError($saved)) {
-            raise_error(array(
-              'code' => 600, 'type' => 'php',
-              'file' => __FILE__, 'line' => __LINE__,
-              'message' => "Error saving distribution-list to Kolab server:" . $saved->getMessage()),
-            true, false);
-            $added = false;
-        }
-        else {
-            $this->distlists[$gid] = $list;
-        }
-        
-        return $added;
-    }
-
-    /**
-     * Remove the given contact records from a certain group
-     *
-     * @param string  Group identifier
-     * @param array   List of contact identifiers to be removed
-     * @return int    Number of deleted group members
-     */
-    function remove_from_group($gid, $ids)
-    {
-        if (!is_array($ids))
-            $ids = explode(',', $ids);
-        
-        $this->_fetch_groups();
-        if (!($list = $this->distlists[$gid]))
-            return false;
-
-        $new_member = array();
-        foreach ((array)$list['member'] as $member) {
-            if (!in_array($member['ID'], $ids))
-                $new_member[] = $member;
-        }
-
-        // write distribution list back to server
-        $list['member'] = $new_member;
-        $saved = $this->liststorage->save($list, $list['uid']);
-        
-        if (PEAR::isError($saved)) {
-            raise_error(array(
-              'code' => 600, 'type' => 'php',
-              'file' => __FILE__, 'line' => __LINE__,
-              'message' => "Error saving distribution-list object to Kolab server:" . $saved->getMessage()),
-            true, false);
-        }
-        else {
-            // remove group assigments in local cache
-            foreach ($ids as $id) {
-                $j = array_search($gid, $this->groupmembers[$id]);
-                unset($this->groupmembers[$id][$j]);
-            }
-            $this->distlists[$gid] = $list;
-            return true;
-        }
-
-        return false;
-    }
-
-
-    /**
-     * Simply fetch all records and store them in private member vars
-     */
-    private function _fetch_contacts()
-    {
-        if (!isset($this->contacts)) {
-            // read contacts
-            $this->contacts = $this->id2uid = array();
-            foreach ((array)$this->contactstorage->getObjects() as $record) {
-                $contact = $this->_to_rcube_contact($record);
-                $id = $contact['ID'];
-                $this->contacts[$id] = $contact;
-                $this->id2uid[$id] = $record['uid'];
-            }
-
-            // TODO: sort data arrays according to desired list sorting
-        }
-    }
-    
-    
-    /**
-     * Read distribution-lists AKA groups from server
-     */
-    private function _fetch_groups()
-    {
-        if (!isset($this->distlists)) {
-            $this->distlists = $this->groupmembers = array();
-            foreach ((array)$this->liststorage->getObjects() as $record) {
-                // FIXME: folders without any distribution-list objects return contacts instead ?!
-                if ($record['__type'] != 'Group')
-                    continue;
-                $record['ID'] = md5($record['uid']);
-                foreach ((array)$record['member'] as $i => $member) {
-                    $mid = md5($member['uid']);
-                    $record['member'][$i]['ID'] = $mid;
-                    $this->groupmembers[$mid][] = $record['ID'];
-                }
-                $this->distlists[$record['ID']] = $record;
-            }
-        }
-    }
-    
-    
-    /**
-     * Map fields from internal Kolab_Format to Roundcube contact format
-     */
-    private function _to_rcube_contact($record)
-    {
-        $out = array(
-          'ID' => md5($record['uid']),
-          'email' => array(),
-          'phone' => array(),
-        );
-        
-        foreach ($this->fieldmap as $kolab => $rcube) {
-          if (strlen($record[$kolab]))
-            $out[$rcube] = $record[$kolab];
-        }
-        
-        if (isset($record['gender']))
-            $out['gender'] = $this->gender_map[$record['gender']];
-
-        foreach ((array)$record['email'] as $i => $email)
-            $out['email'][] = $email['smtp-address'];
-            
-        if (!$record['email'] && $record['emails'])
-            $out['email'] = preg_split('/,\s*/', $record['emails']);
-
-        foreach ((array)$record['phone'] as $i => $phone)
-            $out['phone:'.$phone['type']][] = $phone['number'];
-
-        if (is_array($record['address'])) {
-            foreach ($record['address'] as $i => $adr) {
-                $key = 'address:' . $adr['type'];
-                $out[$key][] = array(
-                    'street' => $adr['street'],
-                    'locality' => $adr['locality'],
-                    'zipcode' => $adr['postal-code'],
-                    'region' => $adr['region'],
-                    'country' => $adr['country'],
-                );
-            }
-        }
-
-        // remove empty fields
-        return array_filter($out);
-    }
-
-    private function _from_rcube_contact($contact)
-    {
-        $object = array();
-
-        foreach (array_flip($this->fieldmap) as $rcube => $kolab) {
-            if (isset($contact[$rcube]))
-                $object[$kolab] = is_array($contact[$rcube]) ? $contact[$rcube][0] : $contact[$rcube];
-            else if ($rcube .= ':home' && isset($contact[$rcube]))
-                $object[$kolab] = is_array($contact[$rcube]) ? $contact[$rcube][0] : $contact[$rcube];
-        }
-
-        // format dates
-        if ($object['birthday'] && ($date = @strtotime($object['birthday'])))
-            $object['birthday'] = date('Y-m-d', $date);
-        if ($object['anniversary'] && ($date = @strtotime($object['anniversary'])))
-            $object['anniversary'] = date('Y-m-d', $date);
-
-        $gendermap = array_flip($this->gender_map);
-        if (isset($contact['gender']))
-            $object['gender'] = $gendermap[$contact['gender']];
-
-        $emails = $this->get_col_values('email', $contact, true);
-        $object['emails'] = join(', ', $emails);
-
-        foreach ($this->get_col_values('phone', $contact) as $type => $values) {
-            if ($this->phonetypemap[$type])
-                $type = $this->phonetypemap[$type];
-            foreach ((array)$values as $phone)
-                $object['phone'][] = array('number' => $phone, 'type' => $type);
-        }
-
-        foreach ($this->get_col_values('address', $contact) as $type => $values) {
-            if ($this->addresstypemap[$type])
-                $type = $this->addresstypemap[$type];
-            
-            $basekey = 'addr-' . $type . '-';
-            foreach ((array)$values as $adr) {
-                // switch type if slot is already taken
-                if (isset($object[$basekey . 'type'])) {
-                    $type = $type == 'home' ? 'business' : 'home';
-                    $basekey = 'addr-' . $type . '-';
-                }
-                
-                if (!isset($object[$basekey . 'type'])) {
-                    $object[$basekey . 'type'] = $type;
-                    $object[$basekey . 'street'] = $adr['street'];
-                    $object[$basekey . 'locality'] = $adr['locality'];
-                    $object[$basekey . 'postal-code'] = $adr['zipcode'];
-                    $object[$basekey . 'region'] = $adr['region'];
-                    $object[$basekey . 'country'] = $adr['country'];
-                }
-                else {
-                    $object['address'][] = array(
-                        'type' => $type,
-                        'street' => $adr['street'],
-                        'locality' => $adr['locality'],
-                        'postal-code' => $adr['zipcode'],
-                        'region' => $adr['region'],
-                        'country' => $adr['country'],
-                    );
-                }
-            }
-        }
-
-        return $object;
-    }
-
-}
diff --git a/plugins/kolab_core/README.txt b/plugins/kolab_core/README.txt
deleted file mode 100644
index 87537c0..0000000
--- a/plugins/kolab_core/README.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Kolab Integration Plugin README
--------------------------------
-
-This plugin relies on classes from the Horde project. In order to have all
-the required files available you need to install the following packages from
-Horde:
-	Horde_Framework
-	Kolab_Format
-	Kolab_Storage
-	Horde_NLS
-	Horde_DOM
-
-This is best done using PEAR. Make sure that the local PEAR directory is in
-the PHP isntall path and execute the following commands to install the
-required packages:
-
-pear channel-discover pear.horde.org
-
-pear install horde/Horde_Framework
-pear install horde/Horde_DOM
-pear install horde/Horde_NLS
-pear install horde/Horde_Share
-pear install horde/Log
-pear install horde/Kolab_Format
-pear install horde/Kolab_Storage
-
-
-Configuration
--------------
-
-Rename the config.inc.php.dist to config.inc.php within this plugin directory
-and add the corresponding values for your local Kolab server.
diff --git a/plugins/kolab_core/config.inc.php.dist b/plugins/kolab_core/config.inc.php.dist
deleted file mode 100644
index b6ac25a..0000000
--- a/plugins/kolab_core/config.inc.php.dist
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-// Sample configuration for Kolab LDAP binding used by Kolab_Storage
-$rcmail_config['kolab']['ldap']['basedn'] = 'dc=kolabserver,dc=local';
-$rcmail_config['kolab']['ldap']['phpdn'] = 'cn=nobody,cn=internal,dc=kolabserver,dc=local';
-$rcmail_config['kolab']['ldap']['phppw'] = '<ldap-pwd-goes-here>';
-
-?>
diff --git a/plugins/kolab_core/kolab_core.php b/plugins/kolab_core/kolab_core.php
deleted file mode 100644
index e98b02d..0000000
--- a/plugins/kolab_core/kolab_core.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-/**
- * Kolab core library
- * 
- * Plugin to setup a basic environment for interaction with a Kolab server.
- * Other Kolab-related plugins will depend on it and can use the static API rcube_core
- *
- * This is work-in-progress for the Roundcube+Kolab integration.
- *
- * @author Thomas Bruederli <roundcube@gmail.com>
- * 
- */
-class kolab_core extends rcube_plugin
-{
-    /**
-     * Required startup method of a Roundcube plugin
-     */
-    public function init()
-    {
-        // load local config
-        $this->load_config();
-        
-        // extend include path to load bundled Horde classes
-        $include_path = $this->home . PATH_SEPARATOR . ini_get('include_path');
-        set_include_path($include_path);
-    }
-    
-}
-
diff --git a/plugins/kolab_core/rcube_kolab.php b/plugins/kolab_core/rcube_kolab.php
deleted file mode 100644
index 94511e5..0000000
--- a/plugins/kolab_core/rcube_kolab.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-
-require_once 'Horde/Kolab/Storage/List.php';
-require_once 'Horde/Kolab/Format.php';
-require_once 'Horde/Auth.php';
-require_once 'Horde/Auth/kolab.php';
-require_once 'Horde/Perms.php';
-
-/**
- * Glue class to handle access to the Kolab data using the Kolab_* classes
- * from the Horde project.
- *
- * @author Thomas Bruederli
- */
-class rcube_kolab
-{
-    private static $horde_auth;
-    
-    
-    /**
-     * Setup the environment needed by the Kolab_* classes to access Kolab data
-     */
-    public static function setup()
-    {
-        global $conf;
-        
-        // setup already done
-        if (self::$horde_auth)
-            return;
-        
-        $rcmail = rcmail::get_instance();
-        
-        // load ldap credentials from local config
-        $conf['kolab'] = $rcmail->config->get('kolab');
-        
-        $conf['kolab']['ldap']['server'] = 'ldap://' . $_SESSION['imap_host'] . ':389';
-        $conf['kolab']['imap']['server'] = $_SESSION['imap_host'];
-        $conf['kolab']['imap']['port'] = $_SESSION['imap_port'];
-        
-        // pass the current IMAP authentication credentials to the Horde auth system
-        self::$horde_auth = Auth::singleton('kolab');
-        if (self::$horde_auth->authenticate($_SESSION['username'], array('password' => ($pwd = $rcmail->decrypt($_SESSION['password']))), false)) {
-            $_SESSION['__auth'] = array(
-                'authenticated' => true,
-                'userId' => $_SESSION['username'],
-                'timestamp' => time(),
-                'remote_addr' => $_SERVER['REMOTE_ADDR'],
-            );
-            Auth::setCredential('password', $pwd);
-        }
-    }
-    
-    
-    /**
-     * Get instance of a Kolab (XML) format object
-     *
-     * @param string Data type (contact,event,task,note)
-     * @return object Horde_Kolab_Format_XML The format object
-     */
-    public static function get_format($type)
-    {
-      self::setup();
-      return Horde_Kolab_Format::factory('XML', $type);
-    }
-
-    /**
-     * Get a list of storage folders for the given data type
-     *
-     * @param string Data type to list folders for (contact,event,task,note)
-     * @return array List of Kolab_Folder objects
-     */
-    public static function get_folders($type)
-    {
-        self::setup();
-        $kolab = Kolab_List::singleton();
-        return $kolab->getByType($type);
-    }
-
-    /**
-     * Get storage object for read/write access to the Kolab backend
-     *
-     * @param string IMAP folder to access
-     * @param string Object type to deal with (leave empty for auto-detection using annotations)
-     * @return object Kolab_Data The data storage object
-     */
-    public static function get_storage($folder, $data_type = null)
-    {
-        self::setup();
-        $kolab = Kolab_List::singleton();
-        return $kolab->getFolder($folder)->getData($data_type);
-    }
-
-    /**
-     * Cleanup session data when done
-     */
-    public static function shutdown()
-    {
-        if (isset($_SESSION['__auth'])) {
-            // unset auth data from session. no need to store it persistantly
-            unset($_SESSION['__auth']);
-            
-            // FIXME: remove strange numeric entries
-            foreach ($_SESSION as $key => $val) {
-                if (!$val && is_numeric($key))
-                    unset($_SESSION[$key]);
-            }
-        }
-    }
-}

--
Gitblit v1.9.1