diff --git a/plugins/managesieve/Changelog b/plugins/managesieve/Changelog index 491a48472..fbb6e0d1f 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 8920476b3..97ca96996 100644 --- a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php +++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php @@ -622,7 +622,21 @@ class rcube_sieve_engine 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 @@ class rcube_sieve_engine 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 @@ class rcube_sieve_engine } 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 @@ class rcube_sieve_engine } 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 @@ class rcube_sieve_engine } 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 @@ class rcube_sieve_engine $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 @@ class rcube_sieve_engine $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'); @@ -1401,6 +1410,22 @@ class rcube_sieve_engine $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); $tout .= $this->list_input($id, 'rule_target', $target, $rule['test'] != 'size' && $rule['test'] != 'exists', @@ -2152,7 +2177,8 @@ class rcube_sieve_engine 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 @@ class rcube_sieve_engine 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 371b45d84..f6a2f7dd5 100644 --- a/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php +++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php @@ -939,22 +939,21 @@ class rcube_sieve_script 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); } /**