From 13eb9bdc245273918bc2b96b475d7d74f01aae2b Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Sat, 03 Oct 2015 12:56:33 -0400
Subject: [PATCH] Enigma: Display complete key information (subkeys, user IDs)

---
 plugins/enigma/lib/enigma_driver_gnupg.php  |   15 ++++-
 plugins/enigma/lib/enigma_key.php           |    8 +-
 plugins/enigma/lib/enigma_ui.php            |   71 ++++++++++++++++++++---
 plugins/enigma/localization/en_US.inc       |   16 +++++
 plugins/enigma/skins/classic/enigma.css     |    9 +++
 plugins/enigma/lib/enigma_subkey.php        |   32 ++++++++++
 plugins/enigma/lib/enigma_driver_phpssl.php |    2 
 7 files changed, 130 insertions(+), 23 deletions(-)

diff --git a/plugins/enigma/lib/enigma_driver_gnupg.php b/plugins/enigma/lib/enigma_driver_gnupg.php
index 4046bdd..c41c6c1 100644
--- a/plugins/enigma/lib/enigma_driver_gnupg.php
+++ b/plugins/enigma/lib/enigma_driver_gnupg.php
@@ -299,7 +299,7 @@
             else if ($code == enigma_error::DELKEY) {
                 $key = $this->get_key($keyid);
                 for ($i = count($key->subkeys) - 1; $i >= 0; $i--) {
-                    $type = $key->subkeys[$i]->can_encrypt ? 'priv' : 'pub';
+                    $type = ($key->subkeys[$i]->usage & enigma_key::CAN_ENCRYPT) ? 'priv' : 'pub';
                     $result = $this->{'delete_' . $type . 'key'}($key->subkeys[$i]->id);
                     if ($result !== true) {
                         return $result;
@@ -423,6 +423,14 @@
         $ekey->name = trim($ekey->users[0]->name . ' <' . $ekey->users[0]->email . '>');
 
         foreach ($key->getSubKeys() as $idx => $subkey) {
+            $usage = 0;
+            if ($subkey->canSign()) {
+                $usage += enigma_key::CAN_SIGN;
+            }
+            if ($subkey->canEncrypt()) {
+                $usage += enigma_key::CAN_ENCRYPT;
+            }
+
             $skey = new enigma_subkey();
             $skey->id          = $subkey->getId();
             $skey->revoked     = $subkey->isRevoked();
@@ -430,8 +438,9 @@
             $skey->expires     = $subkey->getExpirationDate();
             $skey->fingerprint = $subkey->getFingerprint();
             $skey->has_private = $subkey->hasPrivate();
-            $skey->can_sign    = $subkey->canSign();
-            $skey->can_encrypt = $subkey->canEncrypt();
+            $skey->algorithm   = $subkey->getAlgorithm();
+            $skey->length      = $subkey->getLength();
+            $skey->usage       = $usage;
 
             $ekey->subkeys[$idx] = $skey;
         };
diff --git a/plugins/enigma/lib/enigma_driver_phpssl.php b/plugins/enigma/lib/enigma_driver_phpssl.php
index d2e2044..a5aa6de 100644
--- a/plugins/enigma/lib/enigma_driver_phpssl.php
+++ b/plugins/enigma/lib/enigma_driver_phpssl.php
@@ -183,8 +183,6 @@
                 $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;
         };
diff --git a/plugins/enigma/lib/enigma_key.php b/plugins/enigma/lib/enigma_key.php
index 734cbb8..b687e62 100644
--- a/plugins/enigma/lib/enigma_key.php
+++ b/plugins/enigma/lib/enigma_key.php
@@ -28,6 +28,9 @@
 
     const CAN_SIGN    = 1;
     const CAN_ENCRYPT = 2;
+    const CAN_CERTIFY = 4;
+    const CAN_AUTH    = 8;
+
 
     /**
      * Keys list sorting callback for usort()
@@ -99,9 +102,7 @@
             if ($user->email === $email && $user->valid && !$user->revoked) {
                 foreach ($this->subkeys as $subkey) {
                     if (!$subkey->revoked && (!$subkey->expires || $subkey->expires > $now)) {
-                        if (($mode == self::CAN_ENCRYPT && $subkey->can_encrypt)
-                            || ($mode == self::CAN_SIGN && $subkey->has_private)
-                        ) {
+                        if ($subkey->usage & $mode) {
                             return $subkey;
                         }
                     }
@@ -147,5 +148,4 @@
 
         return $result;
     }
-
 }
diff --git a/plugins/enigma/lib/enigma_subkey.php b/plugins/enigma/lib/enigma_subkey.php
index 90557d5..dfcfebf 100644
--- a/plugins/enigma/lib/enigma_subkey.php
+++ b/plugins/enigma/lib/enigma_subkey.php
@@ -23,8 +23,9 @@
     public $created;
     public $revoked;
     public $has_private;
-    public $can_sign;
-    public $can_encrypt;
+    public $algorithm;
+    public $length;
+    public $usage;
 
     /**
      * Converts internal ID to short ID
@@ -47,4 +48,31 @@
     {
         return enigma_key::format_fingerprint($this->fingerprint);
     }
+
+    /**
+     * Returns human-readable name of the key's algorithm
+     *
+     * @return string Algorithm name
+     */
+    function get_algorithm()
+    {
+        // http://tools.ietf.org/html/rfc4880#section-9.1
+        switch ($this->algorithm) {
+        case 1:
+        case 2:
+        case 3:
+            return 'RSA';
+        case 16:
+        case 20:
+            return 'Elgamal';
+        case 17:
+            return 'DSA';
+        case 18:
+            return 'Elliptic Curve';
+        case 19:
+            return 'ECDSA';
+        case 21:
+            return 'Diffie-Hellman';
+        }
+    }
 }
diff --git a/plugins/enigma/lib/enigma_ui.php b/plugins/enigma/lib/enigma_ui.php
index f0ab713..e596fde 100644
--- a/plugins/enigma/lib/enigma_ui.php
+++ b/plugins/enigma/lib/enigma_ui.php
@@ -357,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'));
@@ -385,23 +385,72 @@
         $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_AUTH    => $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;
     }
 
diff --git a/plugins/enigma/localization/en_US.inc b/plugins/enigma/localization/en_US.inc
index 7cf3761..dd1d090 100644
--- a/plugins/enigma/localization/en_US.inc
+++ b/plugins/enigma/localization/en_US.inc
@@ -28,11 +28,25 @@
 $labels['fingerprint'] = 'Fingerprint';
 $labels['subkeys'] = 'Subkeys';
 $labels['basicinfo'] = 'Basic Information';
-$labels['userids'] = 'Additional User IDs';
+$labels['userids'] = 'Additional Users';
 $labels['typepublickey'] = 'public key';
 $labels['typekeypair'] = 'key pair';
 $labels['keyattfound'] = 'This message contains attached PGP key(s).';
 $labels['keyattimport'] = 'Import key(s)';
+$labels['typesign'] = 'Sign';
+$labels['typeencrypt'] = 'Encrypt';
+$labels['typecert'] = 'Certify';
+$labels['typeauth'] = 'Authentication';
+$labels['subkeyid'] = 'ID';
+$labels['subkeyalgo'] = 'Algorithm';
+$labels['subkeycreated'] = 'Created';
+$labels['subkeyexpires'] = 'Expires';
+$labels['subkeyusage'] = 'Usage';
+$labels['expiresnever'] = 'never';
+$labels['unknown'] = 'unknown';
+$labels['uservalid'] = 'Valid';
+$labels['userid'] = 'ID';
+$labels['valid'] = 'valid';
 
 $labels['supportencryption'] = 'Enable message encryption and signing';
 $labels['supportsignatures'] = 'Enable message signatures verification';
diff --git a/plugins/enigma/skins/classic/enigma.css b/plugins/enigma/skins/classic/enigma.css
index 2f5d331..6850506 100644
--- a/plugins/enigma/skins/classic/enigma.css
+++ b/plugins/enigma/skins/classic/enigma.css
@@ -142,6 +142,15 @@
   text-align: right;
 }
 
+#key-details table {
+  width: 100%;
+}
+
+#key-details table td,
+#key-details table th {
+  border: 0;
+}
+
 #keystoolbar
 {
   position: absolute;

--
Gitblit v1.9.1