From b825f86108a91957f6467176e418cfc257874658 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Sun, 04 Aug 2013 04:41:02 -0400
Subject: [PATCH] Move identity selection based on non-standard headers into (new) identity_select plugin (#1488553)

---
 CHANGELOG                                        |    1 
 plugins/identity_select/package.xml              |   53 +++++++++++++++++
 program/steps/mail/func.inc                      |   24 +------
 program/lib/Roundcube/rcube_storage.php          |    2 
 plugins/identity_select/tests/IdentitySelect.php |   22 +++++++
 plugins/identity_select/identity_select.php      |   68 ++++++++++++++++++++++
 6 files changed, 149 insertions(+), 21 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index ead4a73..6a30ad7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
+- Move identity selection based on non-standard headers into (new) identity_select plugin (#1488553)
 - Fix colorspace issue on image conversion using ImageMagick (#1489270)
 - Fix XSS vulnerability when editing a message "as new" or draft (#1489251)
 - Fix downloading binary files with (wrong) text/* content-type (#1489267)
diff --git a/plugins/identity_select/identity_select.php b/plugins/identity_select/identity_select.php
new file mode 100644
index 0000000..2037767
--- /dev/null
+++ b/plugins/identity_select/identity_select.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * Identity selection based on additional message headers.
+ *
+ * On reply to a message user identity selection is based on
+ * content of standard headers i.e. From, To, Cc and Return-Path.
+ * Here you can add header(s) set by your SMTP server (e.g.
+ * Delivered-To, Envelope-To, X-Envelope-To, X-RCPT-TO) to make
+ * identity selection more accurate.
+ *
+ * Enable the plugin in config.inc.php and add your desired headers:
+ *   $rcmail_config['identity_select_headers'] = array('Delivered-To');
+ *
+ * @version @package_version@
+ * @author Aleksander Machniak <alec@alec.pl>
+ * @license GNU GPLv3+
+ */
+class identity_select extends rcube_plugin
+{
+    public $task = 'mail';
+
+
+    function init()
+    {
+        $this->add_hook('identity_select', array($this, 'select'));
+        $this->add_hook('storage_init', array($this, 'storage_init'));
+    }
+
+    /**
+     * Adds additional headers to supported headers list
+     */
+    function storage_init($p)
+    {
+        $rcmail = rcmail::get_instance();
+
+        if ($add_headers = (array)$rcmail->config->get('identity_select_headers', array())) {
+            $p['fetch_headers'] = trim($p['fetch_headers'] . ' ' . strtoupper(join(' ', $add_headers)));
+        }
+
+        return $p;
+    }
+
+    /**
+     * Identity selection
+     */
+    function select($p)
+    {
+        if ($p['selected'] !== null) {
+            return $p;
+        }
+
+        $rcmail = rcmail::get_instance();
+
+        foreach ((array)$rcmail->config->get('identity_select_headers', array()) as $header) {
+            if ($header = $p['message']->headers->get($header, false)) {
+                foreach ($p['identities'] as $idx => $ident) {
+                    if (in_array($ident['email_ascii'], (array)$header)) {
+                        $p['selected'] = $idx;
+                        break 2;
+                    }
+                }
+            }
+        }
+
+        return $p;
+    }
+}
diff --git a/plugins/identity_select/package.xml b/plugins/identity_select/package.xml
new file mode 100644
index 0000000..425c288
--- /dev/null
+++ b/plugins/identity_select/package.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" packagerversion="1.9.0" version="2.0" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+    http://pear.php.net/dtd/tasks-1.0.xsd
+    http://pear.php.net/dtd/package-2.0
+    http://pear.php.net/dtd/package-2.0.xsd">
+	<name>identity_select</name>
+	<channel>pear.roundcube.net</channel>
+	<summary>Extended identity selection</summary>
+	<description>
+		On reply to a message user identity selection is based on
+		content of standard headers like From, To, Cc and Return-Path.
+		Here you can add header(s) set by your SMTP server (e.g.
+		Delivered-To, Envelope-To, X-Envelope-To, X-RCPT-TO) to make
+		identity selection more accurate.
+	</description>
+	<lead>
+		<name>Aleksander Machniak</name>
+		<user>alec</user>
+		<email>alec@alec.pl</email>
+		<active>yes</active>
+	</lead>
+	<date>2013-08-04</date>
+	<version>
+		<release>1.0</release>
+		<api>1.0</api>
+	</version>
+	<stability>
+		<release>stable</release>
+		<api>stable</api>
+	</stability>
+	<license uri="http://www.gnu.org/licenses/gpl.html">GNU GPLv3+</license>
+	<notes>-</notes>
+	<contents>
+		<dir baseinstalldir="/" name="/">
+			<file name="identity_select.php" role="php">
+				<tasks:replace from="@name@" to="name" type="package-info"/>
+				<tasks:replace from="@package_version@" to="version" type="package-info"/>
+			</file>
+		</dir>
+		<!-- / -->
+	</contents>
+	<dependencies>
+		<required>
+			<php>
+				<min>5.2.1</min>
+			</php>
+			<pearinstaller>
+				<min>1.7.0</min>
+			</pearinstaller>
+		</required>
+	</dependencies>
+	<phprelease/>
+</package>
diff --git a/plugins/identity_select/tests/IdentitySelect.php b/plugins/identity_select/tests/IdentitySelect.php
new file mode 100644
index 0000000..3d72697
--- /dev/null
+++ b/plugins/identity_select/tests/IdentitySelect.php
@@ -0,0 +1,22 @@
+<?php
+
+class IdentitySelect_Plugin extends PHPUnit_Framework_TestCase
+{
+
+    function setUp()
+    {
+        include_once dirname(__FILE__) . '/../identity_select.php';
+    }
+
+    /**
+     * Plugin object construction test
+     */
+    function test_constructor()
+    {
+        $rcube  = rcube::get_instance();
+        $plugin = new identity_select($rcube->api);
+
+        $this->assertInstanceOf('identity_select', $plugin);
+        $this->assertInstanceOf('rcube_plugin', $plugin);
+    }
+}
diff --git a/program/lib/Roundcube/rcube_storage.php b/program/lib/Roundcube/rcube_storage.php
index 4b336f2..de83345 100644
--- a/program/lib/Roundcube/rcube_storage.php
+++ b/program/lib/Roundcube/rcube_storage.php
@@ -61,8 +61,6 @@
         'MAIL-FOLLOWUP-TO',
         'MAIL-REPLY-TO',
         'RETURN-PATH',
-        'DELIVERED-TO',
-        'ENVELOPE-TO',
     );
 
     const UNKNOWN       = 0;
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index cf3a791..e14d25e 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -1798,27 +1798,13 @@
         }
     }
 
-    // Fallback using Delivered-To
-    if ($from_idx === null && ($delivered_to = $MESSAGE->headers->others['delivered-to'])) {
-        foreach ($identities as $idx => $ident) {
-            if (in_array($ident['email_ascii'], (array)$delivered_to)) {
-                $from_idx = $idx;
-                break;
-            }
-        }
-    }
+    // See identity_select plugin for example usage of this hook
+    $plugin = rcmail::get_instance()->plugins->exec_hook('identity_select',
+        array('message' => $MESSAGE, 'identities' => $identities, 'selected' => $from_idx));
 
-    // Fallback using Envelope-To
-    if ($from_idx === null && ($envelope_to = $MESSAGE->headers->others['envelope-to'])) {
-        foreach ($identities as $idx => $ident) {
-            if (in_array($ident['email_ascii'], (array)$envelope_to)) {
-                $from_idx = $idx;
-                break;
-            }
-        }
-    }
+    $selected = $plugin['selected'];
 
-    return $identities[$from_idx !== null ? $from_idx : $default_identity];
+    return $identities[$selected !== null ? $selected : $default_identity];
 }
 
 // Fixes some content-type names

--
Gitblit v1.9.1