summaryrefslogtreecommitdiff
path: root/plugins/enigma/lib
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/enigma/lib')
-rw-r--r--plugins/enigma/lib/enigma_driver.php18
-rw-r--r--plugins/enigma/lib/enigma_driver_gnupg.php62
-rw-r--r--plugins/enigma/lib/enigma_driver_phpssl.php19
-rw-r--r--plugins/enigma/lib/enigma_engine.php287
-rw-r--r--plugins/enigma/lib/enigma_error.php29
-rw-r--r--plugins/enigma/lib/enigma_key.php40
-rw-r--r--plugins/enigma/lib/enigma_mime_message.php299
-rw-r--r--plugins/enigma/lib/enigma_signature.php15
-rw-r--r--plugins/enigma/lib/enigma_subkey.php17
-rw-r--r--plugins/enigma/lib/enigma_ui.php127
-rw-r--r--plugins/enigma/lib/enigma_userid.php15
11 files changed, 750 insertions, 178 deletions
diff --git a/plugins/enigma/lib/enigma_driver.php b/plugins/enigma/lib/enigma_driver.php
index c0a91ac27..49208b39d 100644
--- a/plugins/enigma/lib/enigma_driver.php
+++ b/plugins/enigma/lib/enigma_driver.php
@@ -1,20 +1,14 @@
<?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. |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
| |
- | 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. |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-------------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
@@ -53,7 +47,7 @@ abstract class enigma_driver
/**
* Signing.
*/
- abstract function sign($text, $key, $passwd);
+ abstract function sign($text, $key, $passwd, $mode = null);
/**
* Signature verification.
diff --git a/plugins/enigma/lib/enigma_driver_gnupg.php b/plugins/enigma/lib/enigma_driver_gnupg.php
index 09e23d36c..52a0ad66c 100644
--- a/plugins/enigma/lib/enigma_driver_gnupg.php
+++ b/plugins/enigma/lib/enigma_driver_gnupg.php
@@ -3,18 +3,11 @@
+-------------------------------------------------------------------------+
| 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. |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
| |
- | 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. |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-------------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
@@ -30,6 +23,7 @@ class enigma_driver_gnupg extends enigma_driver
private $homedir;
private $user;
+
function __construct($user)
{
$this->rc = rcmail::get_instance();
@@ -86,30 +80,40 @@ class enigma_driver_gnupg extends enigma_driver
}
}
+ /**
+ * Encrypt a message
+ *
+ * @param string The message
+ * @param array List of keys
+ */
function encrypt($text, $keys)
{
-/*
- foreach ($keys as $key) {
- $this->gpg->addEncryptKey($key);
+ try {
+ foreach ($keys as $key) {
+ $this->gpg->addEncryptKey($key);
+ }
+
+ $dec = $this->gpg->encrypt($text, true);
+ return $dec;
+ }
+ catch (Exception $e) {
+ return $this->get_error_from_exception($e);
}
- $enc = $this->gpg->encrypt($text);
- return $enc;
-*/
}
/**
- * Register private keys and passwords
+ * Decrypt a message
*
* @param string Encrypted message
* @param array List of key-password mapping
*/
function decrypt($text, $keys = array())
{
- foreach ($keys as $key => $password) {
- $this->gpg->addDecryptKey($key, $password);
- }
-
try {
+ foreach ($keys as $key => $password) {
+ $this->gpg->addDecryptKey($key, $password);
+ }
+
$dec = $this->gpg->decrypt($text);
return $dec;
}
@@ -118,13 +122,15 @@ class enigma_driver_gnupg extends enigma_driver
}
}
- function sign($text, $key, $passwd)
+ function sign($text, $key, $passwd, $mode = null)
{
-/*
- $this->gpg->addSignKey($key, $passwd);
- $signed = $this->gpg->sign($text, Crypt_GPG::SIGN_MODE_DETACHED);
- return $signed;
-*/
+ try {
+ $this->gpg->addSignKey($key, $passwd);
+ return $this->gpg->sign($text, $mode, CRYPT_GPG::ARMOR_ASCII, true);
+ }
+ catch (Exception $e) {
+ return $this->get_error_from_exception($e);
+ }
}
function verify($text, $signature)
diff --git a/plugins/enigma/lib/enigma_driver_phpssl.php b/plugins/enigma/lib/enigma_driver_phpssl.php
index 6686d7dfa..0250893d2 100644
--- a/plugins/enigma/lib/enigma_driver_phpssl.php
+++ b/plugins/enigma/lib/enigma_driver_phpssl.php
@@ -1,20 +1,13 @@
<?php
/*
+-------------------------------------------------------------------------+
- | S/MIME driver for the Enigma Plugin |
+ | S/MIME 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. |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
| |
- | 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. |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-------------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
@@ -81,7 +74,7 @@ class enigma_driver_phpssl extends enigma_driver
{
}
- function sign($text, $key, $passwd)
+ function sign($text, $key, $passwd, $mode = null)
{
}
diff --git a/plugins/enigma/lib/enigma_engine.php b/plugins/enigma/lib/enigma_engine.php
index c3a2e503f..9b929947b 100644
--- a/plugins/enigma/lib/enigma_engine.php
+++ b/plugins/enigma/lib/enigma_engine.php
@@ -3,23 +3,15 @@
+-------------------------------------------------------------------------+
| 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. |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
| |
- | 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. |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-------------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-------------------------------------------------------------------------+
-
*/
/*
@@ -41,6 +33,13 @@ class enigma_engine
const PASSWORD_TIME = 120;
+ const SIGN_MODE_BODY = 1;
+ const SIGN_MODE_SEPARATE = 2;
+ const SIGN_MODE_MIME = 3;
+
+ const ENCRYPT_MODE_BODY = 1;
+ const ENCRYPT_MODE_MIME = 2;
+
/**
* Plugin initialization.
@@ -125,6 +124,175 @@ class enigma_engine
}
/**
+ * Handler for message signing
+ *
+ * @param Mail_mime Original message
+ * @param int Encryption mode
+ *
+ * @return enigma_error On error returns error object
+ */
+ function sign_message(&$message, $mode = null)
+ {
+ $mime = new enigma_mime_message($message, enigma_mime_message::PGP_SIGNED);
+ $from = $mime->getFromAddress();
+
+ // find private key
+ $key = $this->find_key($from, true);
+
+ if (empty($key)) {
+ return new enigma_error(enigma_error::E_KEYNOTFOUND);
+ }
+
+ // check if we have password for this key
+ $passwords = $this->get_passwords();
+ $pass = $passwords[$key->id];
+
+ if ($pass === null) {
+ // ask for password
+ $error = array('missing' => array($key->id => $key->name));
+ return new enigma_error(enigma_error::E_BADPASS, '', $error);
+ }
+
+ // select mode
+ switch ($mode) {
+ case self::SIGN_MODE_BODY:
+ $pgp_mode = Crypt_GPG::SIGN_MODE_CLEAR;
+ break;
+
+ case self::SIGN_MODE_MIME:
+ $pgp_mode = Crypt_GPG::SIGN_MODE_DETACHED;
+ break;
+/*
+ case self::SIGN_MODE_SEPARATE:
+ $pgp_mode = Crypt_GPG::SIGN_MODE_NORMAL;
+ break;
+*/
+ default:
+ if ($mime->isMultipart()) {
+ $pgp_mode = Crypt_GPG::SIGN_MODE_DETACHED;
+ }
+ else {
+ $pgp_mode = Crypt_GPG::SIGN_MODE_CLEAR;
+ }
+ }
+
+ // get message body
+ if ($pgp_mode == Crypt_GPG::SIGN_MODE_CLEAR) {
+ // in this mode we'll replace text part
+ // with the one containing signature
+ $body = $message->getTXTBody();
+ }
+ else {
+ // here we'll build PGP/MIME message
+ $body = $mime->getOrigBody();
+ }
+
+ // sign the body
+ $result = $this->pgp_sign($body, $key->id, $pass, $pgp_mode);
+
+ if ($result !== true) {
+ if ($result->getCode() == enigma_error::E_BADPASS) {
+ // ask for password
+ $error = array('missing' => array($key->id => $key->name));
+ return new enigma_error(enigma_error::E_BADPASS, '', $error);
+ }
+
+ return $result;
+ }
+
+ // replace message body
+ if ($pgp_mode == Crypt_GPG::SIGN_MODE_CLEAR) {
+ $message->setTXTBody($body);
+ }
+ else {
+ $mime->addPGPSignature($body);
+ $message = $mime;
+ }
+ }
+
+ /**
+ * Handler for message encryption
+ *
+ * @param Mail_mime Original message
+ * @param int Encryption mode
+ * @param bool Is draft-save action - use only sender's key for encryption
+ *
+ * @return enigma_error On error returns error object
+ */
+ function encrypt_message(&$message, $mode = null, $is_draft = false)
+ {
+ $mime = new enigma_mime_message($message, enigma_mime_message::PGP_ENCRYPTED);
+
+ // always use sender's key
+ $recipients = array($mime->getFromAddress());
+
+ // if it's not a draft we add all recipients' keys
+ if (!$is_draft) {
+ $recipients = array_merge($recipients, $mime->getRecipients());
+ }
+
+ if (empty($recipients)) {
+ return new enigma_error(enigma_error::E_KEYNOTFOUND);
+ }
+
+ $recipients = array_unique($recipients);
+
+ // find recipient public keys
+ foreach ((array) $recipients as $email) {
+ $key = $this->find_key($email);
+
+ if (empty($key)) {
+ return new enigma_error(enigma_error::E_KEYNOTFOUND, '', array(
+ 'missing' => $email
+ ));
+ }
+
+ $keys[] = $key->id;
+ }
+
+ // select mode
+ switch ($mode) {
+ case self::ENCRYPT_MODE_BODY:
+ $encrypt_mode = $mode;
+ break;
+
+ case self::ENCRYPT_MODE_MIME:
+ $encrypt_mode = $mode;
+ break;
+
+ default:
+ $encrypt_mode = $mime->isMultipart() ? self::ENCRYPT_MODE_MIME : self::ENCRYPT_MODE_BODY;
+ }
+
+ // get message body
+ if ($encrypt_mode == self::ENCRYPT_MODE_BODY) {
+ // in this mode we'll replace text part
+ // with the one containing encrypted message
+ $body = $message->getTXTBody();
+ }
+ else {
+ // here we'll build PGP/MIME message
+ $body = $mime->getOrigBody();
+ }
+
+ // sign the body
+ $result = $this->pgp_encrypt($body, $keys);
+
+ if ($result !== true) {
+ return $result;
+ }
+
+ // replace message body
+ if ($encrypt_mode == self::ENCRYPT_MODE_BODY) {
+ $message->setTXTBody($body);
+ }
+ else {
+ $mime->setPGPEncryptedBody($body);
+ $message = $mime;
+ }
+ }
+
+ /**
* Handler for message_part_structure hook.
* Called for every part of the message.
*
@@ -510,7 +678,6 @@ class enigma_engine
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)
@@ -533,7 +700,6 @@ class enigma_engine
private function pgp_decrypt(&$msg_body)
{
// @TODO: Handle big bodies using (temp) files
- // @TODO: caching of verification result
$keys = $this->get_passwords();
$result = $this->pgp_driver->decrypt($msg_body, $keys);
@@ -554,6 +720,66 @@ class enigma_engine
}
/**
+ * PGP message signing
+ *
+ * @param mixed Message body
+ * @param string Key ID
+ * @param string Key passphrase
+ * @param int Signing mode
+ *
+ * @return mixed True or enigma_error
+ */
+ private function pgp_sign(&$msg_body, $keyid, $password, $mode = null)
+ {
+ // @TODO: Handle big bodies using (temp) files
+ $result = $this->pgp_driver->sign($msg_body, $keyid, $password, $mode);
+
+ if ($result instanceof enigma_error) {
+ $err_code = $result->getCode();
+ if (!in_array($err_code, array(enigma_error::E_KEYNOTFOUND, enigma_error::E_BADPASS)))
+ rcube::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 message encrypting
+ *
+ * @param mixed Message body
+ * @param array Keys
+ *
+ * @return mixed True or enigma_error
+ */
+ private function pgp_encrypt(&$msg_body, $keys)
+ {
+ // @TODO: Handle big bodies using (temp) files
+ $result = $this->pgp_driver->encrypt($msg_body, $keys);
+
+ if ($result instanceof enigma_error) {
+ $err_code = $result->getCode();
+ if (!in_array($err_code, array(enigma_error::E_KEYNOTFOUND, enigma_error::E_BADPASS)))
+ rcube::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
@@ -577,6 +803,39 @@ class enigma_engine
}
/**
+ * Find PGP private/public key
+ *
+ * @param string E-mail address
+ * @param bool Need a key for signing?
+ *
+ * @return enigma_key The key
+ */
+ function find_key($email, $can_sign = false)
+ {
+ $this->load_pgp_driver();
+ $result = $this->pgp_driver->list_keys($email);
+
+ if ($result instanceof enigma_error) {
+ rcube::raise_error(array(
+ 'code' => 600, 'type' => 'php',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Enigma plugin: " . $result->getMessage()
+ ), true, false);
+
+ return;
+ }
+
+ $mode = $can_sign ? enigma_key::CAN_SIGN : enigma_key::CAN_ENCRYPT;
+
+ // check key validity and type
+ foreach ($result as $key) {
+ if ($keyid = $key->find_subkey($email, $mode)) {
+ return $key;
+ }
+ }
+ }
+
+ /**
* PGP key details.
*
* @param mixed Key ID
diff --git a/plugins/enigma/lib/enigma_error.php b/plugins/enigma/lib/enigma_error.php
index 7122e8e7b..1717a7c46 100644
--- a/plugins/enigma/lib/enigma_error.php
+++ b/plugins/enigma/lib/enigma_error.php
@@ -3,18 +3,11 @@
+-------------------------------------------------------------------------+
| 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. |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
| |
- | 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. |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-------------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
@@ -28,14 +21,14 @@ class enigma_error
private $data = array();
// error codes
- const E_OK = 0;
- const E_INTERNAL = 1;
- const E_NODATA = 2;
+ const E_OK = 0;
+ const E_INTERNAL = 1;
+ const E_NODATA = 2;
const E_KEYNOTFOUND = 3;
- const E_DELKEY = 4;
- const E_BADPASS = 5;
- const E_EXPIRED = 6;
- const E_UNVERIFIED = 7;
+ const E_DELKEY = 4;
+ const E_BADPASS = 5;
+ const E_EXPIRED = 6;
+ const E_UNVERIFIED = 7;
function __construct($code = null, $message = '', $data = array())
diff --git a/plugins/enigma/lib/enigma_key.php b/plugins/enigma/lib/enigma_key.php
index 66670c5d5..8c61cbd99 100644
--- a/plugins/enigma/lib/enigma_key.php
+++ b/plugins/enigma/lib/enigma_key.php
@@ -3,18 +3,11 @@
+-------------------------------------------------------------------------+
| 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. |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
| |
- | 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. |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-------------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
@@ -32,6 +25,9 @@ class enigma_key
const TYPE_KEYPAIR = 1;
const TYPE_PUBLIC = 2;
+ const CAN_SIGN = 1;
+ const CAN_ENCRYPT = 2;
+
/**
* Keys list sorting callback for usort()
*/
@@ -92,6 +88,28 @@ class enigma_key
}
/**
+ * Get key ID by user email
+ */
+ function find_subkey($email, $mode)
+ {
+ $now = time();
+
+ foreach ($this->users as $user) {
+ 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)
+ ) {
+ return $subkey;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Converts long ID or Fingerprint to short ID
* Crypt_GPG uses internal, but e.g. Thunderbird's Enigmail displays short ID
*
diff --git a/plugins/enigma/lib/enigma_mime_message.php b/plugins/enigma/lib/enigma_mime_message.php
new file mode 100644
index 000000000..feed78e03
--- /dev/null
+++ b/plugins/enigma/lib/enigma_mime_message.php
@@ -0,0 +1,299 @@
+<?php
+/*
+ +-------------------------------------------------------------------------+
+ | Mail_mime wrapper for the Enigma Plugin |
+ | |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ +-------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <alec@alec.pl> |
+ +-------------------------------------------------------------------------+
+*/
+
+class enigma_mime_message extends Mail_mime
+{
+ const PGP_SIGNED = 1;
+ const PGP_ENCRYPTED = 2;
+
+ protected $_type;
+ protected $_message;
+ protected $_body;
+ protected $_signature;
+ protected $_encrypted;
+
+
+ /**
+ * Object constructor
+ *
+ * @param Mail_mime Original message
+ * @param int Output message type
+ */
+ function __construct($message, $type)
+ {
+ $this->_message = $message;
+ $this->_type = $type;
+
+ // clone parameters
+ foreach (array_keys($this->_build_params) as $param) {
+ $this->_build_params[$param] = $message->getParam($param);
+ }
+
+ // clone headers
+ $this->_headers = $message->_headers;
+
+/*
+ if ($message->getParam('delay_file_io')) {
+ // use common temp dir
+ $temp_dir = $this->config->get('temp_dir');
+ $body_file = tempnam($temp_dir, 'rcmMsg');
+ $mime_result = $message->saveMessageBody($body_file);
+
+ if (is_a($mime_result, 'PEAR_Error')) {
+ self::raise_error(array('code' => 650, 'type' => 'php',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Could not create message: ".$mime_result->getMessage()),
+ true, false);
+ return false;
+ }
+
+ $msg_body = fopen($body_file, 'r');
+ }
+ else {
+*/
+ // \r\n is must-have here
+ $this->_body = $message->get() . "\r\n";
+/*
+ }
+*/
+ }
+
+ /**
+ * Check if the message is multipart (requires PGP/MIME)
+ *
+ * @return bool True if it is multipart, otherwise False
+ */
+ function isMultipart()
+ {
+ return $this->_message instanceof enigma_mime_message
+ || !empty($this->_message->_parts) || $this->_message->getHTMLBody();
+ }
+
+ /**
+ * Get e-mail address of message sender
+ *
+ * @return string Sender address
+ */
+ function getFromAddress()
+ {
+ // get sender address
+ $headers = $this->_message->headers();
+ $from = rcube_mime::decode_address_list($headers['From'], 1, false, null, true);
+ $from = $from[1];
+
+ return $from;
+ }
+
+ /**
+ * Get recipients' e-mail addresses
+ *
+ * @return array Recipients' addresses
+ */
+ function getRecipients()
+ {
+ // get sender address
+ $headers = $this->_message->headers();
+ $to = rcube_mime::decode_address_list($headers['To'], null, false, null, true);
+ $cc = rcube_mime::decode_address_list($headers['Cc'], null, false, null, true);
+ $bcc = rcube_mime::decode_address_list($headers['Bcc'], null, false, null, true);
+
+ $recipients = array_unique(array_merge($to, $cc, $bcc));
+ $recipients = array_diff($recipients, array('undisclosed-recipients:'));
+
+ return $recipients;
+ }
+
+ /**
+ * Get original message body, to be encrypted/signed
+ *
+ * @return string Message body
+ */
+ function getOrigBody()
+ {
+ $_headers = $this->_message->headers();
+ $headers = array();
+
+ if ($_headers['Content-Transfer-Encoding']) {
+ $headers[] = 'Content-Transfer-Encoding: ' . $_headers['Content-Transfer-Encoding'];
+ }
+ $headers[] = 'Content-Type: ' . $_headers['Content-Type'];
+
+ return implode("\r\n", $headers) . "\r\n\r\n" . $this->_body;
+ }
+
+ /**
+ * Register signature attachment
+ *
+ * @param string Signature body
+ */
+ function addPGPSignature($body)
+ {
+ $this->_signature = $body;
+ }
+
+ /**
+ * Register encrypted body
+ *
+ * @param string Encrypted body
+ */
+ function setPGPEncryptedBody($body)
+ {
+ $this->_encrypted = $body;
+ }
+
+ /**
+ * Builds the multipart message.
+ *
+ * @param array $params Build parameters that change the way the email
+ * is built. Should be associative. See $_build_params.
+ * @param resource $filename Output file where to save the message instead of
+ * returning it
+ * @param boolean $skip_head True if you want to return/save only the message
+ * without headers
+ *
+ * @return mixed The MIME message content string, null or PEAR error object
+ * @access public
+ */
+ function get($params = null, $filename = null, $skip_head = false)
+ {
+ if (isset($params)) {
+ while (list($key, $value) = each($params)) {
+ $this->_build_params[$key] = $value;
+ }
+ }
+
+ $this->_checkParams();
+
+ if ($this->_type == self::PGP_SIGNED) {
+ $body = "This is an OpenPGP/MIME signed message (RFC 4880 and 3156)";
+ $params = array(
+ 'content_type' => "multipart/signed; micalg=pgp-sha1; protocol=\"application/pgp-signature\"",
+ 'eol' => $this->_build_params['eol'],
+ );
+
+ $message = new Mail_mimePart($body, $params);
+
+ if (!empty($this->_body)) {
+ $headers = $this->_message->headers();
+ $params = array('content_type' => $headers['Content-Type']);
+
+ if ($headers['Content-Transfer-Encoding']) {
+ $params['encoding'] = $headers['Content-Transfer-Encoding'];
+ }
+
+ $message->addSubpart($this->_body, $params);
+ }
+
+ if (!empty($this->_signature)) {
+ $message->addSubpart($this->_signature, array(
+ 'filename' => 'signature.asc',
+ 'content_type' => 'application/pgp-signature',
+ 'disposition' => 'attachment',
+ 'description' => 'OpenPGP digital signature',
+ ));
+ }
+ }
+ else if ($this->_type == self::PGP_ENCRYPTED) {
+ $body = "This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156)";
+ $params = array(
+ 'content_type' => "multipart/encrypted; protocol=\"application/pgp-encrypted\"",
+ 'eol' => $this->_build_params['eol'],
+ );
+
+ $message = new Mail_mimePart($body, $params);
+
+ $message->addSubpart('Version: 1', array(
+ 'content_type' => 'application/pgp-encrypted',
+ 'description' => 'PGP/MIME version identification',
+ ));
+
+ $message->addSubpart($this->_encrypted, array(
+ 'content_type' => 'application/octet-stream',
+ 'description' => 'PGP/MIME encrypted message',
+ 'disposition' => 'inline',
+ 'filename' => 'encrypted.asc',
+ ));
+ }
+
+ // Use saved boundary
+ if (!empty($this->_build_params['boundary'])) {
+ $boundary = $this->_build_params['boundary'];
+ }
+ else {
+ $boundary = null;
+ }
+
+ // Write output to file
+ if ($filename) {
+ // Append mimePart message headers and body into file
+ $headers = $message->encodeToFile($filename, $boundary, $skip_head);
+ if ($this->_isError($headers)) {
+ return $headers;
+ }
+ $this->_headers = array_merge($this->_headers, $headers);
+ return null;
+ }
+ else {
+ $output = $message->encode($boundary, $skip_head);
+ if ($this->_isError($output)) {
+ return $output;
+ }
+ $this->_headers = array_merge($this->_headers, $output['headers']);
+ return $output['body'];
+ }
+ }
+
+ /**
+ * Get Content-Type and Content-Transfer-Encoding headers of the message
+ *
+ * @return array Headers array
+ * @access private
+ */
+ function _contentHeaders()
+ {
+ $this->_checkParams();
+
+ $eol = !empty($this->_build_params['eol']) ? $this->_build_params['eol'] : "\r\n";
+
+ // multipart message: and boundary
+ if (!empty($this->_build_params['boundary'])) {
+ $boundary = $this->_build_params['boundary'];
+ }
+ else if (!empty($this->_headers['Content-Type'])
+ && preg_match('/boundary="([^"]+)"/', $this->_headers['Content-Type'], $m)
+ ) {
+ $boundary = $m[1];
+ }
+ else {
+ $boundary = '=_' . md5(rand() . microtime());
+ }
+
+ $this->_build_params['boundary'] = $boundary;
+
+ if ($this->_type == self::PGP_SIGNED) {
+ $headers['Content-Type'] = "multipart/signed; micalg=pgp-sha1;$eol"
+ ." protocol=\"application/pgp-signature\";$eol"
+ ." boundary=\"$boundary\"";
+ }
+ else if ($this->_type == self::PGP_ENCRYPTED) {
+ $headers['Content-Type'] = "multipart/encrypted;$eol"
+ ." protocol=\"application/pgp-encrypted\";$eol"
+ ." boundary=\"$boundary\"";
+ }
+
+ return $headers;
+ }
+}
diff --git a/plugins/enigma/lib/enigma_signature.php b/plugins/enigma/lib/enigma_signature.php
index 65990903b..2e63a80f4 100644
--- a/plugins/enigma/lib/enigma_signature.php
+++ b/plugins/enigma/lib/enigma_signature.php
@@ -3,18 +3,11 @@
+-------------------------------------------------------------------------+
| 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. |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
| |
- | 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. |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-------------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
diff --git a/plugins/enigma/lib/enigma_subkey.php b/plugins/enigma/lib/enigma_subkey.php
index 1b9fb95ad..cd57611c0 100644
--- a/plugins/enigma/lib/enigma_subkey.php
+++ b/plugins/enigma/lib/enigma_subkey.php
@@ -3,18 +3,11 @@
+-------------------------------------------------------------------------+
| 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. |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
| |
- | 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. |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-------------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
@@ -31,7 +24,7 @@ class enigma_subkey
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
diff --git a/plugins/enigma/lib/enigma_ui.php b/plugins/enigma/lib/enigma_ui.php
index 26396f1dd..e866ba335 100644
--- a/plugins/enigma/lib/enigma_ui.php
+++ b/plugins/enigma/lib/enigma_ui.php
@@ -3,18 +3,11 @@
+-------------------------------------------------------------------------+
| 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. |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
| |
- | 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. |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-------------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
@@ -45,7 +38,7 @@ class enigma_ui
*
* @param string Preferences section
*/
- function init($section='')
+ function init()
{
$this->add_js();
@@ -150,7 +143,12 @@ class enigma_ui
$data = array('keyid' => key($data), 'user' => $data[key($data)]);
- $this->rc->output->set_env('enigma_password_request', $data);
+ if ($this->rc->action == 'send') {
+ $this->rc->output->command('enigma_password_request', $data);
+ }
+ else {
+ $this->rc->output->set_env('enigma_password_request', $data);
+ }
// add some labels to client
$this->rc->output->add_label('enigma.enterkeypasstitle', 'enigma.enterkeypass',
@@ -176,7 +174,7 @@ class enigma_ui
$attrib['name'] = $attrib['id'];
$this->rc->output->set_env('contentframe', $attrib['name']);
- $this->rc->output->set_env('blankpage', $attrib['src'] ?
+ $this->rc->output->set_env('blankpage', $attrib['src'] ?
$this->rc->output->abs_url($attrib['src']) : 'program/resources/blank.gif');
return $this->rc->output->frame($attrib);
@@ -223,9 +221,6 @@ class enigma_ui
$page = max(intval(rcube_utils::get_input_value('_p', rcube_utils::INPUT_GPC)), 1);
$search = rcube_utils::get_input_value('_q', rcube_utils::INPUT_GPC);
- // define list of cols to be displayed
-// $a_show_cols = array('name');
-
// Get the list
$list = $this->enigma->engine->list_keys($search);
@@ -233,24 +228,21 @@ class enigma_ui
$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);
+ else if (is_array($list)) {
+ // Save the size
+ $listsize = count($list);
- // Sort the list by key (user) name
- usort($list, array('enigma_key', 'cmp'));
+ // Sort the list by key (user) name
+ usort($list, array('enigma_key', 'cmp'));
- // Slice current page
- $list = array_slice($list, ($page - 1) * $pagesize, $pagesize);
+ // Slice current page
+ $list = array_slice($list, ($page - 1) * $pagesize, $pagesize);
+ $size = count($list);
- $size = count($list);
-
- // Add rows
- foreach ($list as $key) {
- $this->rc->output->command('enigma_add_list_row',
- array('name' => rcube::Q($key->name), 'id' => $key->id));
- }
+ // Add rows
+ foreach ($list as $key) {
+ $this->rc->output->command('enigma_add_list_row',
+ array('name' => rcube::Q($key->name), 'id' => $key->id));
}
}
@@ -285,11 +277,12 @@ class enigma_ui
*/
private function get_rowcount_text($all=0, $curr_count=0, $page=1)
{
- if (!$curr_count)
+ if (!$curr_count) {
$out = $this->enigma->gettext('nokeysfound');
+ }
else {
$pagesize = $this->rc->config->get('pagesize', 100);
- $first = ($page - 1) * $pagesize;
+ $first = ($page - 1) * $pagesize;
$out = $this->enigma->gettext(array(
'name' => 'keysfromto',
@@ -485,18 +478,16 @@ class enigma_ui
private function compose_ui()
{
-/*
$this->add_css();
// Options menu button
- // @TODO: make this work with non-default skins
$this->enigma->add_button(array(
'type' => 'link',
'command' => 'plugin.enigma',
'onclick' => "rcmail.command('menu-open', 'enigmamenu', event.target, event)",
'class' => 'button enigma',
- 'title' => 'securityoptions',
- 'label' => 'securityoptions',
+ 'title' => 'encryptionoptions',
+ 'label' => 'encryption',
'domain' => $this->enigma->ID,
'width' => 32,
'height' => 32
@@ -504,30 +495,27 @@ class enigma_ui
// Options menu contents
$this->enigma->add_hook('render_page', array($this, 'compose_menu'));
-*/
}
function compose_menu($p)
{
- $menu = new html_table(array('cols' => 2));
+ $menu = new html_table(array('cols' => 2));
$chbox = new html_checkbox(array('value' => 1));
- $menu->add(null, html::label(array('for' => 'enigmadefaultopt'),
- rcube::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'),
rcube::Q($this->enigma->gettext('signmsg'))));
- $menu->add(null, $chbox->show(1, array('name' => '_enigma_sign', 'id' => 'enigmasignopt')));
+ $menu->add(null, $chbox->show($this->rc->config->get('enigma_sign_all') ? 1 : 0,
+ array('name' => '_enigma_sign', 'id' => 'enigmasignopt')));
- $menu->add(null, html::label(array('for' => 'enigmacryptopt'),
+ $menu->add(null, html::label(array('for' => 'enigmaencryptopt'),
rcube::Q($this->enigma->gettext('encryptmsg'))));
- $menu->add(null, $chbox->show(1, array('name' => '_enigma_crypt', 'id' => 'enigmacryptopt')));
+ $menu->add(null, $chbox->show($this->rc->config->get('enigma_encrypt_all') ? 1 : 0,
+ array('name' => '_enigma_encrypt', 'id' => 'enigmaencryptopt')));
$menu = html::div(array('id' => 'enigmamenu', 'class' => 'popupmenu'),
$menu->show());
- $p['content'] = preg_replace('/(<form name="form"[^>]+>)/i', '\\1'."\n$menu", $p['content']);
+ $p['content'] .= $menu;
return $p;
}
@@ -715,4 +703,47 @@ class enigma_ui
return $p;
}
+ /**
+ * Handle message_ready hook (encryption/signing)
+ */
+ function message_ready($p)
+ {
+ $savedraft = !empty($_POST['_draft']) && empty($_GET['_saveonly']);
+
+ if (!$savedraft && rcube_utils::get_input_value('_enigma_sign', rcube_utils::INPUT_POST)) {
+ $this->enigma->load_engine();
+ $status = $this->enigma->engine->sign_message($p['message']);
+ $mode = 'sign';
+ }
+
+ if ((!$status instanceof enigma_error) && rcube_utils::get_input_value('_enigma_encrypt', rcube_utils::INPUT_POST)) {
+ $this->enigma->load_engine();
+ $status = $this->enigma->engine->encrypt_message($p['message'], null, $savedraft);
+ $mode = 'encrypt';
+ }
+
+ if ($mode && ($status instanceof enigma_error)) {
+ $code = $status->getCode();
+
+ if ($code == enigma_error::E_KEYNOTFOUND) {
+ $vars = array('email' => $status->getData('missing'));
+ $msg = 'enigma.' . $mode . 'nokey';
+ }
+ else if ($code == enigma_error::E_BADPASS) {
+ $msg = 'enigma.' . $mode . 'badpass';
+ $type = 'warning';
+
+ $this->password_prompt($status);
+ }
+ else {
+ $msg = 'enigma.' . $mode . 'error';
+ }
+
+ $this->rc->output->show_message($msg, $type ?: 'error', $vars);
+ $this->rc->output->send('iframe');
+ }
+
+ return $p;
+ }
+
}
diff --git a/plugins/enigma/lib/enigma_userid.php b/plugins/enigma/lib/enigma_userid.php
index 36185e718..da0358445 100644
--- a/plugins/enigma/lib/enigma_userid.php
+++ b/plugins/enigma/lib/enigma_userid.php
@@ -3,18 +3,11 @@
+-------------------------------------------------------------------------+
| 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. |
+ | Copyright (C) 2010-2015 The Roundcube Dev Team |
| |
- | 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. |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
| |
+-------------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |