From 889c76cbdc05992b060ded9984690285588e285b Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Fri, 20 Sep 2013 06:11:31 -0400
Subject: [PATCH] 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)

---
 plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php |   82 ++++++++++++++++++++++++++++------------
 plugins/managesieve/Changelog                            |    2 +
 plugins/managesieve/lib/Roundcube/rcube_sieve_script.php |    9 ++--
 3 files changed, 63 insertions(+), 30 deletions(-)

diff --git a/plugins/managesieve/Changelog b/plugins/managesieve/Changelog
index 491a484..fbb6e0d 100644
--- a/plugins/managesieve/Changelog
+++ b/plugins/managesieve/Changelog
@@ -1,4 +1,6 @@
 - 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)
 
 * version 7.0 [2013-09-09]
 -----------------------------------------------------------
diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
index 8920476..97ca969 100644
--- a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
+++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
@@ -622,7 +622,21 @@
                             if (!count($target)) {
                                 $this->errors['tests'][$i]['target'] = $this->plugin->gettext('cannotbeempty');
                             }
-                            else if ($type != 'regex' && $type != 'matches') {
+                            else if (strpos($type, 'count-') === 0) {
+                                foreach ($target as $arg) {
+                                    if (preg_match('/[^0-9]/', $arg)) {
+                                        $this->errors['tests'][$i]['target'] = $this->plugin->gettext('forbiddenchars');
+                                    }
+                                }
+                            }
+                            else if (strpos($type, 'value-') === 0) {
+                                // Some date/time formats do not support i;ascii-numeric comparator
+                                if ($comparator == 'i;ascii-numeric' && in_array($datepart, array('date', 'time', 'iso8601', 'std11'))) {
+                                    $comparator = '';
+                                }
+                            }
+
+                            if (!preg_match('/^(regex|matches|count-)/', $type) && count($target)) {
                                 foreach ($target as $arg) {
                                     if (!$this->validate_date_part($datepart, $arg)) {
                                         $this->errors['tests'][$i]['target'] = $this->plugin->gettext('invaliddateformat');
@@ -668,7 +682,21 @@
                             if (!count($target)) {
                                 $this->errors['tests'][$i]['target'] = $this->plugin->gettext('cannotbeempty');
                             }
-                            else if ($type != 'regex' && $type != 'matches') {
+                            else if (strpos($type, 'count-') === 0) {
+                                foreach ($target as $arg) {
+                                    if (preg_match('/[^0-9]/', $arg)) {
+                                        $this->errors['tests'][$i]['target'] = $this->plugin->gettext('forbiddenchars');
+                                    }
+                                }
+                            }
+                            else if (strpos($type, 'value-') === 0) {
+                                // Some date/time formats do not support i;ascii-numeric comparator
+                                if ($comparator == 'i;ascii-numeric' && in_array($datepart, array('date', 'time', 'iso8601', 'std11'))) {
+                                    $comparator = '';
+                                }
+                            }
+
+                            if (count($target) && !preg_match('/^(regex|matches|count-)/', $type)) {
                                 foreach ($target as $arg) {
                                     if (!$this->validate_date_part($datepart, $arg)) {
                                         $this->errors['tests'][$i]['target'] = $this->plugin->gettext('invaliddateformat');
@@ -699,7 +727,7 @@
                         }
                         else if (preg_match('/^(value|count)-/', $type)) {
                             foreach ($target as $target_value) {
-                                if (!preg_match('/[0-9]+/', $target_value)) {
+                                if (preg_match('/[^0-9]/', $target_value)) {
                                     $this->errors['tests'][$i]['target'] = $this->plugin->gettext('forbiddenchars');
                                 }
                             }
@@ -781,7 +809,7 @@
                             }
                             else if (preg_match('/^(value|count)-/', $type)) {
                                 foreach ($target as $target_value) {
-                                    if (!preg_match('/[0-9]+/', $target_value)) {
+                                    if (preg_match('/[^0-9]/', $target_value)) {
                                         $this->errors['tests'][$i]['target'] = $this->plugin->gettext('forbiddenchars');
                                     }
                                 }
@@ -794,9 +822,6 @@
                     }
 
                     if ($header != 'size' && $comparator) {
-                        if (preg_match('/^(value|count)/', $this->form['tests'][$i]['type']))
-                            $comparator = 'i;ascii-numeric';
-
                         $this->form['tests'][$i]['comparator'] = $comparator;
                     }
 
@@ -806,7 +831,7 @@
 
             $i = 0;
             // actions
-            foreach($act_types as $idx => $type) {
+            foreach ($act_types as $idx => $type) {
                 $type   = $this->strip_value($type);
                 $target = $this->strip_value($act_targets[$idx]);
 
@@ -1359,22 +1384,6 @@
             $select_op->add(rcube::Q($this->plugin->gettext('valuenotequals')), 'value-ne');
         }
 
-        // (current)date part select
-        if (in_array('date', $this->exts) || in_array('currentdate', $this->exts)) {
-            $date_parts = array('date', 'iso8601', 'std11', 'julian', 'time',
-                'year', 'month', 'day', 'hour', 'minute', 'second', 'weekday', 'zone');
-            $select_dp = new html_select(array('name' => "_rule_date_part[]", 'id' => 'rule_date_part'.$id,
-                'style' => $rule['test'] == 'currentdate' || $rule['test'] == 'date' ? '' : 'display:none',
-                'class' => 'datepart_selector',
-            ));
-
-            foreach ($date_parts as $part) {
-                $select_dp->add(rcube::Q($this->plugin->gettext($part)), $part);
-            }
-
-            $tout .= $select_dp->show($rule['test'] == 'currentdate' || $rule['test'] == 'date' ? $rule['part'] : '');
-        }
-
         // target(s) input
         if (in_array($rule['test'], array('header', 'address', 'envelope'))) {
             $test   = ($rule['not'] ? 'not' : '').($rule['type'] ? $rule['type'] : 'is');
@@ -1399,6 +1408,22 @@
         else {
             $test   = ($rule['not'] ? 'not' : '').$rule['test'];
             $target =  '';
+        }
+
+        // (current)date part select
+        if (in_array('date', $this->exts) || in_array('currentdate', $this->exts)) {
+            $date_parts = array('date', 'iso8601', 'std11', 'julian', 'time',
+                'year', 'month', 'day', 'hour', 'minute', 'second', 'weekday', 'zone');
+            $select_dp = new html_select(array('name' => "_rule_date_part[]", 'id' => 'rule_date_part'.$id,
+                'style' => in_array($rule['test'], array('currentdate', 'date')) && !preg_match('/^(notcount|count)-/', $test) ? '' : 'display:none',
+                'class' => 'datepart_selector',
+            ));
+
+            foreach ($date_parts as $part) {
+                $select_dp->add(rcube::Q($this->plugin->gettext($part)), $part);
+            }
+
+            $tout .= $select_dp->show($rule['test'] == 'currentdate' || $rule['test'] == 'date' ? $rule['part'] : '');
         }
 
         $tout .= $select_op->show($test);
@@ -2152,7 +2177,8 @@
             return;
         }
 
-        $headers = array();
+        $headers    = array();
+        $exceptions = array('date', 'currentdate', 'size', 'body');
 
         // find common headers used in script, will be added to the list
         // of available (predefined) headers (#1489271)
@@ -2161,6 +2187,12 @@
                 if ($test['test'] == 'header') {
                     foreach ((array) $test['arg1'] as $header) {
                         $lc_header = strtolower($header);
+
+                        // skip special names to not confuse UI
+                        if (in_array($lc_header, $exceptions)) {
+                            continue;
+                        }
+
                         if (!isset($this->headers[$lc_header]) && !isset($headers[$lc_header])) {
                             $headers[$lc_header] = $header;
                         }
diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php
index 371b45d..f6a2f7d 100644
--- a/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php
+++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php
@@ -939,22 +939,21 @@
             return;
         }
 
-        // relational operator + comparator
+        // relational operator
         if (preg_match('/^(value|count)-([gteqnl]{2})/', $test['type'], $m)) {
             array_push($exts, 'relational');
-            array_push($exts, 'comparator-i;ascii-numeric');
 
-            $out .= ' :' . $m[1] . ' "' . $m[2] . '" :comparator "i;ascii-numeric"';
+            $out .= ' :' . $m[1] . ' "' . $m[2];
         }
         else {
-            $this->add_comparator($test, $out, $exts);
-
             if ($test['type'] == 'regex') {
                 array_push($exts, 'regex');
             }
 
             $out .= ' :' . $test['type'];
         }
+
+        $this->add_comparator($test, $out, $exts);
     }
 
     /**

--
Gitblit v1.9.1