From 0f4806ede6c5933c43221f714f68eeedff5ba389 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Thu, 03 Oct 2013 05:07:00 -0400
Subject: [PATCH] Added managesieve_domains option to limit redirect destinations

---
 plugins/managesieve/config.inc.php.dist                  |    4 ++
 plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php |   60 ++++++++++++++++++++++++-----
 plugins/managesieve/Changelog                            |    1 
 plugins/managesieve/managesieve.js                       |    2 
 4 files changed, 55 insertions(+), 12 deletions(-)

diff --git a/plugins/managesieve/Changelog b/plugins/managesieve/Changelog
index fbb6e0d..c792c81 100644
--- a/plugins/managesieve/Changelog
+++ b/plugins/managesieve/Changelog
@@ -1,3 +1,4 @@
+- Added managesieve_domains option to limit redirect destinations
 - Fix bug where at least one additional address of vacation message was required (#1489345)
 - Fix so i;ascii-numeric comparator is not forced as default for :count and :value operators
 - Fix date/currentdate related form issues and comparators handling (#1489346)
diff --git a/plugins/managesieve/config.inc.php.dist b/plugins/managesieve/config.inc.php.dist
index cb56a0e..52d3a9b 100644
--- a/plugins/managesieve/config.inc.php.dist
+++ b/plugins/managesieve/config.inc.php.dist
@@ -64,4 +64,8 @@
 // Scripts listed here will be not presented to the user.
 $config['managesieve_filename_exceptions'] = array();
 
+// List of domains limiting destination emails in redirect action
+// If not empty, user will need to select domain from a list
+$config['managesieve_domains'] = array();
+
 ?>
diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
index 97ca969..6c9f804 100644
--- a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
+++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
@@ -535,6 +535,7 @@
             $act_types      = rcube_utils::get_input_value('_action_type', rcube_utils::INPUT_POST, true);
             $mailboxes      = rcube_utils::get_input_value('_action_mailbox', rcube_utils::INPUT_POST, true);
             $act_targets    = rcube_utils::get_input_value('_action_target', rcube_utils::INPUT_POST, true);
+            $domain_targets = rcube_utils::get_input_value('_action_target_domain', rcube_utils::INPUT_POST);
             $area_targets   = rcube_utils::get_input_value('_action_target_area', rcube_utils::INPUT_POST, true);
             $reasons        = rcube_utils::get_input_value('_action_reason', rcube_utils::INPUT_POST, true);
             $addresses      = rcube_utils::get_input_value('_action_addresses', rcube_utils::INPUT_POST, true);
@@ -832,15 +833,14 @@
             $i = 0;
             // actions
             foreach ($act_types as $idx => $type) {
-                $type   = $this->strip_value($type);
-                $target = $this->strip_value($act_targets[$idx]);
+                $type = $this->strip_value($type);
 
                 switch ($type) {
-
                 case 'fileinto':
                 case 'fileinto_copy':
                     $mailbox = $this->strip_value($mailboxes[$idx], false, false);
                     $this->form['actions'][$i]['target'] = $this->mod_mailbox($mailbox, 'in');
+
                     if ($type == 'fileinto_copy') {
                         $type = 'fileinto';
                         $this->form['actions'][$i]['copy'] = true;
@@ -858,17 +858,31 @@
 
                 case 'redirect':
                 case 'redirect_copy':
+                    $target = $this->strip_value($act_targets[$idx]);
+                    $domain = $this->strip_value($domain_targets[$idx]);
+
+                    // force one of the configured domains
+                    $domains = (array) $this->rc->config->get('managesieve_domains');
+                    if (!empty($domains) && !empty($target)) {
+                        if (!$domain || !in_array($domain, $domains)) {
+                            $domain = $domains[0];
+                        }
+
+                        $target .= '@' . $domain;
+                    }
+
                     $this->form['actions'][$i]['target'] = $target;
 
-                    if ($this->form['actions'][$i]['target'] == '')
+                    if ($target == '')
                         $this->errors['actions'][$i]['target'] = $this->plugin->gettext('cannotbeempty');
-                    else if (!rcube_utils::check_email($this->form['actions'][$i]['target']))
-                        $this->errors['actions'][$i]['target'] = $this->plugin->gettext('noemailwarning');
+                    else if (!rcube_utils::check_email($target))
+                        $this->errors['actions'][$i]['target'] = $this->plugin->gettext(!empty($domains) ? 'forbiddenchars' : 'noemailwarning');
 
                     if ($type == 'redirect_copy') {
                         $type = 'redirect';
                         $this->form['actions'][$i]['copy'] = true;
                     }
+
                     break;
 
                 case 'addflag':
@@ -889,6 +903,7 @@
                 case 'vacation':
                     $reason        = $this->strip_value($reasons[$idx]);
                     $interval_type = $interval_types[$idx] == 'seconds' ? 'seconds' : 'days';
+
                     $this->form['actions'][$i]['reason']    = str_replace("\r\n", "\n", $reason);
                     $this->form['actions'][$i]['subject']   = $subject[$idx];
                     $this->form['actions'][$i]['addresses'] = array_shift($addresses);
@@ -1608,11 +1623,34 @@
 
         // actions target inputs
         $out .= '<td class="rowtargets">';
-        // shared targets
-        $out .= '<input type="text" name="_action_target['.$id.']" id="action_target' .$id. '" '
-            .'value="' .($action['type']=='redirect' ? rcube::Q($action['target'], 'strict', false) : ''). '" size="35" '
-            .'style="display:' .($action['type']=='redirect' ? 'inline' : 'none') .'" '
-            . $this->error_class($id, 'action', 'target', 'action_target') .' />';
+
+        // force domain selection in redirect email input
+        $domains = (array) $this->rc->config->get('managesieve_domains');
+        if (!empty($domains)) {
+            sort($domains);
+
+            $domain_select = new html_select(array('name' => "_action_target_domain[$id]", 'id' => 'action_target_domain'.$id));
+            $domain_select->add(array_combine($domains, $domains));
+
+            $parts = explode('@', $action['target']);
+
+            if (!empty($parts)) {
+                $action['domain'] = array_pop($parts);
+                $action['target'] = implode('@', $parts);
+            }
+        }
+
+        // redirect target
+        $out .= '<span id="redirect_target' . $id . '" style="white-space:nowrap;'
+            . ' display:' . ($action['type'] == 'redirect' ? 'inline' : 'none') . '">'
+            . '<input type="text" name="_action_target['.$id.']" id="action_target' .$id. '"'
+            . ' value="' .($action['type'] == 'redirect' ? rcube::Q($action['target'], 'strict', false) : '') . '"'
+            . (!empty($domains) ? ' size="20"' : ' size="35"')
+            . $this->error_class($id, 'action', 'target', 'action_target') .' />'
+            . (!empty($domains) ? ' @ ' . $domain_select->show($action['domain']) : '')
+            . '</span>';
+
+        // (e)reject target
         $out .= '<textarea name="_action_target_area['.$id.']" id="action_target_area' .$id. '" '
             .'rows="3" cols="35" '. $this->error_class($id, 'action', 'targetarea', 'action_target_area')
             .'style="display:' .(in_array($action['type'], array('reject', 'ereject')) ? 'inline' : 'none') .'">'
diff --git a/plugins/managesieve/managesieve.js b/plugins/managesieve/managesieve.js
index 156bce6..fa13b71 100644
--- a/plugins/managesieve/managesieve.js
+++ b/plugins/managesieve/managesieve.js
@@ -664,7 +664,7 @@
     v = obj.value, enabled = {},
     elems = {
       mailbox: document.getElementById('action_mailbox' + id),
-      target: document.getElementById('action_target' + id),
+      target: document.getElementById('redirect_target' + id),
       target_area: document.getElementById('action_target_area' + id),
       flags: document.getElementById('action_flags' + id),
       vacation: document.getElementById('action_vacation' + id),

--
Gitblit v1.9.1