Aleksander Machniak
2016-01-26 c1a518910aedd6fc622a6d36aa8e3deac943a215
plugins/enigma/lib/enigma_ui.php
@@ -59,6 +59,14 @@
                    $this->key_import();
                    break;
                case 'export':
                    $this->key_export();
                    break;
                case 'generate':
                    $this->key_generate();
                    break;
                case 'create':
                    $this->key_create();
                    break;
@@ -256,6 +264,7 @@
            }
        }
        $this->rc->output->set_env('rowcount', $size);
        $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);
@@ -348,7 +357,7 @@
    function tpl_key_data($attrib)
    {
        $out   = '';
        $table = new html_table(array('cols' => 2));
        $table = new html_table(array('cols' => 2));
        // Key user ID
        $table->add('title', $this->enigma->gettext('keyuserid'));
@@ -376,24 +385,102 @@
        $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
        $table = new html_table(array('cols' => 5, 'id' => 'enigmasubkeytable', 'class' => 'records-table'));
        $table->add_header('id', $this->enigma->gettext('subkeyid'));
        $table->add_header('algo', $this->enigma->gettext('subkeyalgo'));
        $table->add_header('created', $this->enigma->gettext('subkeycreated'));
        $table->add_header('expires', $this->enigma->gettext('subkeyexpires'));
        $table->add_header('usage', $this->enigma->gettext('subkeyusage'));
        $now         = time();
        $date_format = $this->rc->config->get('date_format', 'Y-m-d');
        $usage_map   = array(
            enigma_key::CAN_ENCRYPT      => $this->enigma->gettext('typeencrypt'),
            enigma_key::CAN_SIGN         => $this->enigma->gettext('typesign'),
            enigma_key::CAN_CERTIFY      => $this->enigma->gettext('typecert'),
            enigma_key::CAN_AUTHENTICATE => $this->enigma->gettext('typeauth'),
        );
        foreach ($this->data->subkeys as $subkey) {
            $algo = $subkey->get_algorithm();
            if ($algo && $subkey->length) {
                $algo .= ' (' . $subkey->length . ')';
            }
            $usage = array();
            foreach ($usage_map as $key => $text) {
                if ($subkey->usage & $key) {
                    $usage[] = $text;
                }
            }
            $table->add('id', $subkey->get_short_id());
            $table->add('algo', $algo);
            $table->add('created', $subkey->created ? $this->rc->format_date($subkey->created, $date_format, false) : '');
            $table->add('expires', $subkey->expires ? $this->rc->format_date($subkey->expires, $date_format, false) : $this->enigma->gettext('expiresnever'));
            $table->add('usage', implode(',', $usage));
            $table->set_row_attribs($subkey->revoked || ($subkey->expires && $subkey->expires < $now) ? 'deleted' : '');
        }
        $out .= html::tag('fieldset', null,
            html::tag('legend', null,
                $this->enigma->gettext('subkeys')) . $table->show($attrib));
            html::tag('legend', null,
                $this->enigma->gettext('subkeys')) . $table->show());
        // Additional user IDs
        $table = new html_table(array('cols' => 2));
        // Columns: User ID, Validity
        $table = new html_table(array('cols' => 2, 'id' => 'enigmausertable', 'class' => 'records-table'));
        $table->add_header('id', $this->enigma->gettext('userid'));
        $table->add_header('valid', $this->enigma->gettext('uservalid'));
        foreach ($this->data->users as $user) {
            $username = $user->name;
            if ($user->comment) {
                $username .= ' (' . $user->comment . ')';
            }
            $username .= ' <' . $user->email . '>';
            $table->add('id', rcube::Q(trim($username)));
            $table->add('valid', $this->enigma->gettext($user->valid ? 'valid' : 'unknown'));
            $table->set_row_attribs($user->revoked || !$user->valid ? 'deleted' : '');
        }
        $out .= html::tag('fieldset', null,
            html::tag('legend', null,
                $this->enigma->gettext('userids')) . $table->show($attrib));
*/
            html::tag('legend', null,
                $this->enigma->gettext('userids')) . $table->show());
        return $out;
    }
    /**
     * Key(s) export handler
     */
    private function key_export()
    {
        $keys   = rcube_utils::get_input_value('_keys', rcube_utils::INPUT_GPC);
        $engine = $this->enigma->load_engine();
        $list   = $keys == '*' ? $engine->list_keys() : explode(',', $keys);
        if (is_array($list)) {
            $filename = 'export.pgp';
            if (count($list) == 1) {
                $filename = (is_object($list[0]) ? $list[0]->id : $list[0]) . '.pgp';
            }
            // send downlaod headers
            header('Content-Type: application/pgp-keys');
            header('Content-Disposition: attachment; filename="' . $filename . '"');
            if ($fp = fopen('php://output', 'w')) {
                foreach ($list as $key) {
                    $engine->export_key(is_object($key) ? $key->id : $key, $fp);
                }
            }
        }
        exit;
    }
    /**
@@ -484,6 +571,45 @@
    }
    /**
     * Server-side key pair generation handler
     */
    private function key_generate()
    {
        $user = rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST, true);
        $pass = rcube_utils::get_input_value('_password', rcube_utils::INPUT_POST, true);
        $size = (int) rcube_utils::get_input_value('_size', rcube_utils::INPUT_POST);
        if ($size > 4096) {
            $size = 4096;
        }
        $ident = rcube_mime::decode_address_list($user, 1, false);
        if (empty($ident)) {
            $this->rc->output->show_message('enigma.keygenerateerror', 'error');
            $this->rc->output->send();
        }
        $this->enigma->load_engine();
        $result = $this->enigma->engine->generate_key(array(
            'user'     => $ident[1]['name'],
            'email'    => $ident[1]['mailto'],
            'password' => $pass,
            'size'     => $size,
        ));
        if ($result instanceof enigma_key) {
            $this->rc->output->command('enigma_key_create_success');
            $this->rc->output->show_message('enigma.keygeneratesuccess', 'confirmation');
        }
        else {
            $this->rc->output->show_message('enigma.keygenerateerror', 'error');
        }
        $this->rc->output->send();
    }
    /**
     * Key generation page handler
     */
    private function key_create()
@@ -493,6 +619,8 @@
        $this->rc->output->add_handlers(array(
            'keyform' => array($this, 'tpl_key_create_form'),
        ));
        $this->rc->output->set_env('enigma_keygen_server', $this->rc->config->get('enigma_keygen_server'));
        $this->rc->output->set_pagetitle($this->enigma->gettext('keygenerate'));
        $this->rc->output->send('enigma.keycreate');
@@ -538,7 +666,8 @@
        $this->rc->output->add_gui_object('keyform', $attrib['id']);
        $this->rc->output->add_label('enigma.keygenerating', 'enigma.formerror',
            'enigma.passwordsdiffer', 'enigma.keygenerateerror', 'enigma.nonameident');
            'enigma.passwordsdiffer', 'enigma.keygenerateerror', 'enigma.nonameident',
            'enigma.keygennosupport');
        return $this->rc->output->form_tag(array(), $table->show($attrib));
    }
@@ -548,12 +677,11 @@
     */
    private function key_delete()
    {
        $keys = rcube_utils::get_input_value('_keys', rcube_utils::INPUT_POST);
        $this->enigma->load_engine();
        $keys   = rcube_utils::get_input_value('_keys', rcube_utils::INPUT_POST);
        $engine = $this->enigma->load_engine();
        foreach ((array)$keys as $key) {
            $res = $this->enigma->engine->delete_key($key);
            $res = $engine->delete_key($key);
            if ($res !== true) {
                $this->rc->output->show_message('enigma.keyremoveerror', 'error');
@@ -632,11 +760,13 @@
        $part_id = $p['part']->mime_id;
        // Decryption status
        if (isset($engine->decryptions[$part_id])) {
        if (($found = $this->find_part_id($part_id, $engine->decryptions)) !== null
            && ($status = $engine->decryptions[$found])
        ) {
            $attach_scripts = true;
            // get decryption status
            $status = $engine->decryptions[$part_id];
            // show the message only once
            unset($engine->decryptions[$found]);
            // display status info
            $attrib['id'] = 'enigma-message';
@@ -645,11 +775,11 @@
                $attrib['class'] = 'enigmaerror';
                $code            = $status->getCode();
                if ($code == enigma_error::E_KEYNOTFOUND) {
                if ($code == enigma_error::KEYNOTFOUND) {
                    $msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($status->getData('id')),
                        $this->enigma->gettext('decryptnokey')));
                }
                else if ($code == enigma_error::E_BADPASS) {
                else if ($code == enigma_error::BADPASS) {
                    $msg = rcube::Q($this->enigma->gettext('decryptbadpass'));
                    $this->password_prompt($status);
                }
@@ -666,10 +796,13 @@
        }
        // Signature verification status
        if (isset($engine->signed_parts[$part_id])
            && ($sig = $engine->signatures[$engine->signed_parts[$part_id]])
        if (($found = $this->find_part_id($part_id, $engine->signed_parts)) !== null
            && ($sig = $engine->signatures[$engine->signed_parts[$found]])
        ) {
            $attach_scripts = true;
            // show the message only once
            unset($engine->signatures[$engine->signed_parts[$part_id]]);
            // display status info
            $attrib['id'] = 'enigma-message';
@@ -677,7 +810,7 @@
            if ($sig instanceof enigma_signature) {
                $sender = ($sig->name ? $sig->name . ' ' : '') . '<' . $sig->email . '>';
                if ($sig->valid === enigma_error::E_UNVERIFIED) {
                if ($sig->valid === enigma_error::UNVERIFIED) {
                    $attrib['class'] = 'enigmawarning';
                    $msg = str_replace('$sender', $sender, $this->enigma->gettext('sigunverified'));
                    $msg = str_replace('$keyid', $sig->id, $msg);
@@ -692,7 +825,7 @@
                    $msg = rcube::Q(str_replace('$sender', $sender, $this->enigma->gettext('siginvalid')));
                }
            }
            else if ($sig && $sig->getCode() == enigma_error::E_KEYNOTFOUND) {
            else if ($sig && $sig->getCode() == enigma_error::KEYNOTFOUND) {
                $attrib['class'] = 'enigmawarning';
                $msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($sig->getData('id')),
                    $this->enigma->gettext('signokey')));
@@ -710,9 +843,6 @@
//            $msg .= '<br /><pre>'.$sig->body.'</pre>';
            $p['prefix'] .= html::div($attrib, $msg);
            // Display each signature message only once
            unset($engine->signatures[$engine->signed_parts[$part_id]]);
        }
        if ($attach_scripts) {
@@ -811,11 +941,11 @@
        if ($mode && ($status instanceof enigma_error)) {
            $code = $status->getCode();
            if ($code == enigma_error::E_KEYNOTFOUND) {
            if ($code == enigma_error::KEYNOTFOUND) {
                $vars = array('email' => $status->getData('missing'));
                $msg  = 'enigma.' . $mode . 'nokey';
            }
            else if ($code == enigma_error::E_BADPASS) {
            else if ($code == enigma_error::BADPASS) {
                $msg  = 'enigma.' . $mode . 'badpass';
                $type = 'warning';
@@ -853,11 +983,11 @@
            if ($status instanceof enigma_error) {
                $code = $status->getCode();
                if ($code == enigma_error::E_KEYNOTFOUND) {
                if ($code == enigma_error::KEYNOTFOUND) {
                    $msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($status->getData('id')),
                        $this->enigma->gettext('decryptnokey')));
                }
                else if ($code == enigma_error::E_BADPASS) {
                else if ($code == enigma_error::BADPASS) {
                    $this->password_prompt($status, array('compose-init' => true));
                    return $p;
                }
@@ -871,6 +1001,27 @@
            $this->rc->output->show_message($msg, 'error');
        }
        // Check sign/ecrypt options for signed/encrypted drafts
        $this->rc->output->set_env('enigma_force_encrypt', !empty($engine->decryptions));
        $this->rc->output->set_env('enigma_force_sign', !empty($engine->signatures));
        return $p;
    }
    /**
     * Check if the part or its parent exists in the array
     * of decryptions/signatures. Returns found ID.
     */
    private function find_part_id($part_id, $data)
    {
        $ids   = explode('.', $part_id);
        $i     = 0;
        $count = count($ids);
        while ($i < $count && strlen($part = implode('.', array_slice($ids, 0, ++$i)))) {
            if (array_key_exists($part, $data)) {
                return $part;
            }
        }
    }
}