mirror of
https://github.com/roundcube/roundcubemail.git
synced 2026-03-10 01:56:48 +01:00
- Support 'duplicate' extension [RFC 7352]
- Improve errors handling in filter form
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
CHANGELOG Roundcube Webmail
|
||||
===========================
|
||||
|
||||
- Managesieve: Support 'duplicate' extension [RFC 7352]
|
||||
- Managesieve: Unhide advanced rule controls if there are inputs with errors
|
||||
- Managesieve: Display warning message when filter form contains errors
|
||||
- Enigma: Added enigma_debug option
|
||||
- Fix message list multi-select/deselect issue (#5219)
|
||||
- Fix bug where getting HTML editor content could steal focus from other form controls (#5223)
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
* version 8.7 [2016-]
|
||||
-----------------------------------------------------------
|
||||
- Support 'duplicate' extension [RFC 7352]
|
||||
- Unhide advanced rule controls if there are inputs with errors
|
||||
- Display warning message when filter form contains errors
|
||||
|
||||
* version 8.6 [2016-04-06]
|
||||
-----------------------------------------------------------
|
||||
- Refactored script parser to be 100x faster
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"type": "roundcube-plugin",
|
||||
"description": "Adds a possibility to manage Sieve scripts (incoming mail filters). It's clickable interface which operates on text scripts and communicates with server using managesieve protocol. Adds Filters tab in Settings.",
|
||||
"license": "GPLv3+",
|
||||
"version": "8.6",
|
||||
"version": "8.7",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Aleksander Machniak",
|
||||
|
||||
@@ -63,7 +63,7 @@ class rcube_sieve_engine
|
||||
1 => 'notifyimportancehigh'
|
||||
);
|
||||
|
||||
const VERSION = '8.6';
|
||||
const VERSION = '8.7';
|
||||
const PROGNAME = 'Roundcube (Managesieve)';
|
||||
const PORT = 4190;
|
||||
|
||||
@@ -609,6 +609,12 @@ class rcube_sieve_engine
|
||||
$lastindexes = rcube_utils::get_input_value('_rule_index_last', rcube_utils::INPUT_POST);
|
||||
$dateheaders = rcube_utils::get_input_value('_rule_date_header', rcube_utils::INPUT_POST);
|
||||
$dateparts = rcube_utils::get_input_value('_rule_date_part', rcube_utils::INPUT_POST);
|
||||
$message = rcube_utils::get_input_value('_rule_message', rcube_utils::INPUT_POST);
|
||||
$dup_handles = rcube_utils::get_input_value('_rule_duplicate_handle', rcube_utils::INPUT_POST, true);
|
||||
$dup_headers = rcube_utils::get_input_value('_rule_duplicate_header', rcube_utils::INPUT_POST, true);
|
||||
$dup_uniqueids = rcube_utils::get_input_value('_rule_duplicate_uniqueid', rcube_utils::INPUT_POST, true);
|
||||
$dup_seconds = rcube_utils::get_input_value('_rule_duplicate_seconds', rcube_utils::INPUT_POST);
|
||||
$dup_lasts = rcube_utils::get_input_value('_rule_duplicate_last', rcube_utils::INPUT_POST);
|
||||
$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);
|
||||
@@ -818,6 +824,34 @@ class rcube_sieve_engine
|
||||
$this->form['tests'][$i]['content'] = $trans_type;
|
||||
}
|
||||
}
|
||||
else if ($header == 'message') {
|
||||
$test = $this->strip_value($message[$idx]);
|
||||
|
||||
if (preg_match('/^not/', $test)) {
|
||||
$this->form['tests'][$i]['not'] = true;
|
||||
$test = substr($test, 3);
|
||||
}
|
||||
|
||||
$this->form['tests'][$i]['test'] = $test;
|
||||
|
||||
if ($test == 'duplicate') {
|
||||
$this->form['tests'][$i]['last'] = !empty($dup_lasts[$idx]);
|
||||
$this->form['tests'][$i]['handle'] = trim($dup_handles[$idx]);
|
||||
$this->form['tests'][$i]['header'] = trim($dup_headers[$idx]);
|
||||
$this->form['tests'][$i]['uniqueid'] = trim($dup_uniqueids[$idx]);
|
||||
$this->form['tests'][$i]['seconds'] = trim($dup_seconds[$idx]);
|
||||
|
||||
if ($this->form['tests'][$i]['seconds']
|
||||
&& preg_match('/[^0-9]/', $this->form['tests'][$i]['seconds'])
|
||||
) {
|
||||
$this->errors['tests'][$i]['duplicate_seconds'] = $this->plugin->gettext('forbiddenchars');
|
||||
}
|
||||
|
||||
if ($this->form['tests'][$i]['header'] && $this->form['tests'][$i]['uniqueid']) {
|
||||
$this->errors['tests'][$i]['duplicate_uniqueid'] = $this->plugin->gettext('duplicate.conflict.err');
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$cust_header = $headers = $this->strip_value(array_shift($cust_headers));
|
||||
$mod = $this->strip_value($mods[$idx]);
|
||||
@@ -1095,6 +1129,9 @@ class rcube_sieve_engine
|
||||
// $this->rc->output->send();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->rc->output->show_message('managesieve.filterformerror', 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
$this->send();
|
||||
@@ -1406,13 +1443,17 @@ class rcube_sieve_engine
|
||||
$select_header->add($header, $index);
|
||||
}
|
||||
$select_header->add($this->plugin->gettext('...'), '...');
|
||||
if (in_array('body', $this->exts))
|
||||
if (in_array('body', $this->exts)) {
|
||||
$select_header->add($this->plugin->gettext('body'), 'body');
|
||||
}
|
||||
$select_header->add($this->plugin->gettext('size'), 'size');
|
||||
if (in_array('date', $this->exts)) {
|
||||
$select_header->add($this->plugin->gettext('datetest'), 'date');
|
||||
$select_header->add($this->plugin->gettext('currdate'), 'currentdate');
|
||||
}
|
||||
if (in_array('duplicate', $this->exts)) {
|
||||
$select_header->add($this->plugin->gettext('message'), 'message');
|
||||
}
|
||||
|
||||
if (isset($rule['test'])) {
|
||||
if (in_array($rule['test'], array('header', 'address', 'envelope'))) {
|
||||
@@ -1434,6 +1475,9 @@ class rcube_sieve_engine
|
||||
else if (in_array($rule['test'], array('size', 'body', 'date', 'currentdate'))) {
|
||||
$test = $rule['test'];
|
||||
}
|
||||
else if (in_array($rule['test'], array('duplicate'))) {
|
||||
$test = 'message';
|
||||
}
|
||||
else if ($rule['test'] != 'true') {
|
||||
$test = '...';
|
||||
}
|
||||
@@ -1460,7 +1504,7 @@ class rcube_sieve_engine
|
||||
|
||||
// matching type select (operator)
|
||||
$select_op = new html_select(array('name' => "_rule_op[]", 'id' => 'rule_op'.$id,
|
||||
'style' => 'display:' .($rule['test']!='size' ? 'inline' : 'none'),
|
||||
'style' => 'display:' .(!in_array($rule['test'], array('size', 'duplicate')) ? 'inline' : 'none'),
|
||||
'class' => 'operator_selector',
|
||||
'onchange' => 'rule_op_select(this, '.$id.')'));
|
||||
$select_op->add(rcube::Q($this->plugin->gettext('filtercontains')), 'contains');
|
||||
@@ -1527,9 +1571,22 @@ class rcube_sieve_engine
|
||||
$tout .= $select_dp->show($rule['test'] == 'currentdate' || $rule['test'] == 'date' ? $rule['part'] : '');
|
||||
}
|
||||
|
||||
// message test select (e.g. duplicate)
|
||||
if (in_array('duplicate', $this->exts)) {
|
||||
$select_msg = new html_select(array('name' => "_rule_message[]", 'id' => 'rule_message'.$id,
|
||||
'style' => in_array($rule['test'], array('duplicate')) ? '' : 'display:none',
|
||||
'class' => 'message_selector',
|
||||
));
|
||||
|
||||
$select_msg->add(rcube::Q($this->plugin->gettext('duplicate')), 'duplicate');
|
||||
$select_msg->add(rcube::Q($this->plugin->gettext('notduplicate')), 'notduplicate');
|
||||
|
||||
$tout .= $select_msg->show($test);
|
||||
}
|
||||
|
||||
$tout .= $select_op->show($test);
|
||||
$tout .= $this->list_input($id, 'rule_target', $target,
|
||||
$rule['test'] != 'size' && $rule['test'] != 'exists',
|
||||
$rule['test'] != 'size' && $rule['test'] != 'exists' && $rule['test'] != 'duplicate',
|
||||
$this->error_class($id, 'test', 'target', 'rule_target')) . "\n";
|
||||
|
||||
$select_size_op = new html_select(array('name' => "_rule_size_op[]", 'id' => 'rule_size_op'.$id));
|
||||
@@ -1555,8 +1612,9 @@ class rcube_sieve_engine
|
||||
'onchange' => 'rule_mod_select(' .$id .')'));
|
||||
$select_mod->add(rcube::Q($this->plugin->gettext('none')), '');
|
||||
$select_mod->add(rcube::Q($this->plugin->gettext('address')), 'address');
|
||||
if (in_array('envelope', $this->exts))
|
||||
if (in_array('envelope', $this->exts)) {
|
||||
$select_mod->add(rcube::Q($this->plugin->gettext('envelope')), 'envelope');
|
||||
}
|
||||
|
||||
$select_type = new html_select(array('name' => "_rule_mod_type[]", 'id' => 'rule_mod_type'.$id));
|
||||
$select_type->add(rcube::Q($this->plugin->gettext('allparts')), 'all');
|
||||
@@ -1567,7 +1625,7 @@ class rcube_sieve_engine
|
||||
$select_type->add(rcube::Q($this->plugin->gettext('detail')), 'detail');
|
||||
}
|
||||
|
||||
$need_mod = !in_array($rule['test'], array('size', 'body', 'date', 'currentdate'));
|
||||
$need_mod = !in_array($rule['test'], array('size', 'body', 'date', 'currentdate', 'duplicate'));
|
||||
$mout = '<div id="rule_mod' .$id. '" class="adv"' . (!$need_mod ? ' style="display:none"' : '') . '>';
|
||||
$mout .= ' <span class="label">' . rcube::Q($this->plugin->gettext('modifier')) . ' </span>';
|
||||
$mout .= $select_mod->show($rule['test']);
|
||||
@@ -1604,7 +1662,8 @@ class rcube_sieve_engine
|
||||
}
|
||||
|
||||
// Comparators
|
||||
$mout .= '<div id="rule_comp' .$id. '" class="adv"' . ($rule['test'] == 'size' ? ' style="display:none"' : '') . '>';
|
||||
$need_comp = $rule['test'] != 'size' && $rule['test'] != 'duplicate';
|
||||
$mout .= '<div id="rule_comp' .$id. '" class="adv"' . (!$need_comp ? ' style="display:none"' : '') . '>';
|
||||
$mout .= '<span class="label">' . rcube::Q($this->plugin->gettext('comparator')) . '</span>';
|
||||
$mout .= $select_comp->show($rule['comparator']);
|
||||
$mout .= '</div>';
|
||||
@@ -1633,6 +1692,32 @@ class rcube_sieve_engine
|
||||
$mout .= '</div>';
|
||||
}
|
||||
|
||||
// Duplicate
|
||||
if (in_array('duplicate', $this->exts)) {
|
||||
$need_duplicate = $rule['test'] == 'duplicate';
|
||||
$mout .= '<div id="rule_duplicate_div' .$id. '" class="adv"'. (!$need_duplicate ? ' style="display:none"' : '') .'>';
|
||||
$mout .= '<span class="label">' . rcube::Q($this->plugin->gettext('duplicate.handle')) . '</span>';
|
||||
$mout .= '<input type="text" name="_rule_duplicate_handle[]" id="rule_duplicate_handle'.$id
|
||||
. '" value="'. ($rule['handle'] ? rcube::JQ($rule['handle']) : '')
|
||||
. '" size="30"' . $this->error_class($id, 'test', 'duplicate_handle', 'rule_duplicate_handle') .' /><br>';
|
||||
$mout .= '<span class="label">' . rcube::Q($this->plugin->gettext('duplicate.header')) . '</span>';
|
||||
$mout .= '<input type="text" name="_rule_duplicate_header[]" id="rule_duplicate_header'.$id
|
||||
. '" value="'. ($rule['header'] ? rcube::JQ($rule['header']) : '')
|
||||
. '" size="30"' . $this->error_class($id, 'test', 'duplicate_header', 'rule_duplicate_header') .' /><br>';
|
||||
$mout .= '<span class="label">' . rcube::Q($this->plugin->gettext('duplicate.uniqueid')) . '</span>';
|
||||
$mout .= '<input type="text" name="_rule_duplicate_uniqueid[]" id="rule_duplicate_uniqueid'.$id
|
||||
. '" value="'. ($rule['uniqueid'] ? rcube::JQ($rule['uniqueid']) : '')
|
||||
. '" size="30"' . $this->error_class($id, 'test', 'duplicate_uniqueid', 'rule_duplicate_uniqueid') .' /><br>';
|
||||
$mout .= '<span class="label">' . rcube::Q($this->plugin->gettext('duplicate.seconds')) . '</span>';
|
||||
$mout .= '<input type="text" name="_rule_duplicate_seconds[]" id="rule_duplicate_seconds'.$id
|
||||
. '" value="'. rcube::JQ($rule['seconds'])
|
||||
. '" size="6"' . $this->error_class($id, 'test', 'duplicate_seconds', 'rule_duplicate_seconds') .' />';
|
||||
$mout .= ' <input type="checkbox" name="_rule_duplicate_last['.$id.']" id="rule_duplicate_last'.$id
|
||||
. '" value="1"' . (!empty($rule['last']) ? ' checked="checked"' : '') . ' />'
|
||||
. '<label for="rule_duplicate_last'.$id.'">'.rcube::Q($this->plugin->gettext('duplicate.last')).'</label>';
|
||||
$mout .= '</div>';
|
||||
}
|
||||
|
||||
// Build output table
|
||||
$out = $div ? '<div class="rulerow" id="rulerow' .$id .'">'."\n" : '';
|
||||
$out .= '<table><tr>';
|
||||
|
||||
@@ -24,21 +24,22 @@ class rcube_sieve_script
|
||||
{
|
||||
public $content = array(); // script rules array
|
||||
|
||||
private $vars = array(); // "global" variables
|
||||
private $prefix = ''; // script header (comments)
|
||||
private $supported = array( // Sieve extensions supported by class
|
||||
private $vars = array(); // "global" variables
|
||||
private $prefix = ''; // script header (comments)
|
||||
private $supported = array( // supported Sieve extensions:
|
||||
'body', // RFC5173
|
||||
'copy', // RFC3894
|
||||
'date', // RFC5260
|
||||
'duplicate', // RFC7352
|
||||
'enotify', // RFC5435
|
||||
'envelope', // RFC5228
|
||||
'ereject', // RFC5429
|
||||
'fileinto', // RFC5228
|
||||
'imapflags', // draft-melnikov-sieve-imapflags-06
|
||||
'imap4flags', // RFC5232
|
||||
'include', // draft-ietf-sieve-include-12
|
||||
'include', // RFC6609
|
||||
'index', // RFC5260
|
||||
'notify', // draft-martin-sieve-notify-01,
|
||||
'notify', // RFC5435
|
||||
'regex', // draft-ietf-sieve-regex-01
|
||||
'reject', // RFC5429
|
||||
'relational', // RFC3431
|
||||
@@ -316,8 +317,30 @@ class rcube_sieve_script
|
||||
$tests[$i] .= ' ' . self::escape_string($test['part']);
|
||||
$tests[$i] .= ' ' . self::escape_string($test['arg']);
|
||||
|
||||
break;
|
||||
|
||||
case 'duplicate':
|
||||
array_push($exts, 'duplicate');
|
||||
|
||||
$tests[$i] .= ($test['not'] ? 'not ' : '') . $test['test'];
|
||||
|
||||
$tokens = array('handle', 'uniqueid', 'header');
|
||||
foreach ($tokens as $token)
|
||||
if ($test[$token] !== null && $test[$token] !== '') {
|
||||
$tests[$i] .= " :$token " . self::escape_string($test[$token]);
|
||||
}
|
||||
|
||||
if (!empty($test['seconds'])) {
|
||||
$tests[$i] .= ' :seconds ' . intval($test['seconds']);
|
||||
}
|
||||
|
||||
if (!empty($test['last'])) {
|
||||
$tests[$i] .= ' :last';
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
@@ -749,6 +772,23 @@ class rcube_sieve_script
|
||||
$tests[] = $test;
|
||||
break;
|
||||
|
||||
case 'duplicate':
|
||||
$test = array('test' => $token, 'not' => $not);
|
||||
|
||||
for ($i=0, $len=count($tokens); $i<$len; $i++) {
|
||||
if (!is_array($tokens[$i])) {
|
||||
if (preg_match('/^:(handle|header|uniqueid|seconds)$/i', $tokens[$i], $m)) {
|
||||
$test[strtolower($m[1])] = $tokens[++$i];
|
||||
}
|
||||
else if (preg_match('/^:last$/i', $tokens[$i])) {
|
||||
$test['last'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tests[] = $test;
|
||||
break;
|
||||
|
||||
case 'exists':
|
||||
$tests[] = array('test' => 'exists', 'not' => $not,
|
||||
'arg' => array_pop($tokens));
|
||||
@@ -966,33 +1006,25 @@ class rcube_sieve_script
|
||||
$result = array();
|
||||
|
||||
for ($i=0, $len=count($tokens); $i<$len; $i++) {
|
||||
if (!is_array($tokens[$i]) && $tokens[$i][0] == ':') {
|
||||
if (preg_match('/^:comparator$/i', $tokens[$i])) {
|
||||
$test['comparator'] = $tokens[++$i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match('/^:(count|value)$/i', $tokens[$i])) {
|
||||
$test['type'] = strtolower(substr($tokens[$i], 1)) . '-' . $tokens[++$i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match('/^:(is|contains|matches|regex)$/i', $tokens[$i])) {
|
||||
$test['type'] = strtolower(substr($tokens[$i], 1));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match('/^:index$/i', $tokens[$i])) {
|
||||
$test['index'] = intval($tokens[++$i]);
|
||||
if ($tokens[$i+1] && preg_match('/^:last$/i', $tokens[$i+1])) {
|
||||
$test['last'] = true;
|
||||
$i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!is_array($tokens[$i]) && preg_match('/^:comparator$/i', $tokens[$i])) {
|
||||
$test['comparator'] = $tokens[++$i];
|
||||
}
|
||||
|
||||
$result[] = $tokens[$i];
|
||||
else if (!is_array($tokens[$i]) && preg_match('/^:(count|value)$/i', $tokens[$i])) {
|
||||
$test['type'] = strtolower(substr($tokens[$i], 1)) . '-' . $tokens[++$i];
|
||||
}
|
||||
else if (!is_array($tokens[$i]) && preg_match('/^:(is|contains|matches|regex)$/i', $tokens[$i])) {
|
||||
$test['type'] = strtolower(substr($tokens[$i], 1));
|
||||
}
|
||||
else if (!is_array($tokens[$i]) && preg_match('/^:index$/i', $tokens[$i])) {
|
||||
$test['index'] = intval($tokens[++$i]);
|
||||
if ($tokens[$i+1] && preg_match('/^:last$/i', $tokens[$i+1])) {
|
||||
$test['last'] = true;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$result[] = $tokens[$i];
|
||||
}
|
||||
}
|
||||
|
||||
$tokens = $result;
|
||||
@@ -1098,7 +1130,6 @@ class rcube_sieve_script
|
||||
{
|
||||
$result = array();
|
||||
$length = strlen($str);
|
||||
$mask = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:_';
|
||||
|
||||
// remove spaces from the beginning of the string
|
||||
while ($position < $length && (!$num || $num === true || count($result) < $num)) {
|
||||
@@ -1184,11 +1215,18 @@ class rcube_sieve_script
|
||||
if ($position == $length) {
|
||||
break 2;
|
||||
}
|
||||
if ($length - $position < 2) {
|
||||
$result[] = substr($str, $position);
|
||||
$position = $length;
|
||||
break;
|
||||
}
|
||||
|
||||
// tag/identifier/number
|
||||
if ($len = strspn($str, $mask, $position)) {
|
||||
$atom = substr($str, $position, $len);
|
||||
$position += $len;
|
||||
if (preg_match('/[a-zA-Z0-9:_]+/', $str, $m, PREG_OFFSET_CAPTURE, $position)
|
||||
&& $m[0][1] == $position
|
||||
) {
|
||||
$atom = $m[0][0];
|
||||
$position += strlen($atom);
|
||||
|
||||
if ($atom != 'text:') {
|
||||
$result[] = $atom;
|
||||
|
||||
@@ -56,7 +56,7 @@ $labels['add'] = 'Add';
|
||||
$labels['del'] = 'Delete';
|
||||
$labels['sender'] = 'Sender';
|
||||
$labels['recipient'] = 'Recipient';
|
||||
$labels['vacationaddr'] = 'My email addresses:';
|
||||
$labels['vacationaddr'] = 'My e-mail addresses:';
|
||||
$labels['vacationdays'] = 'How often send messages (in days):';
|
||||
$labels['vacationinterval'] = 'How often send messages:';
|
||||
$labels['vacationreason'] = 'Message body (vacation reason):';
|
||||
@@ -174,7 +174,7 @@ $labels['vacation.end'] = 'Vacation end';
|
||||
$labels['vacation.status'] = 'Status';
|
||||
$labels['vacation.on'] = 'On';
|
||||
$labels['vacation.off'] = 'Off';
|
||||
$labels['vacation.addresses'] = 'My email addresses';
|
||||
$labels['vacation.addresses'] = 'My e-mail addresses';
|
||||
$labels['vacation.interval'] = 'Reply interval';
|
||||
$labels['vacation.after'] = 'Put vacation rule after';
|
||||
$labels['vacation.saving'] = 'Saving data...';
|
||||
@@ -191,6 +191,14 @@ $labels['ariasummaryfilterslist'] = 'List of filters';
|
||||
$labels['ariasummaryfiltersetslist'] = 'List of filter sets';
|
||||
$labels['filterstitle'] = 'Edit incoming mail filters';
|
||||
$labels['vacationtitle'] = 'Edit out-of-office rule';
|
||||
$labels['message'] = 'Message';
|
||||
$labels['duplicate'] = 'is duplicate';
|
||||
$labels['notduplicate'] = 'is not duplicate';
|
||||
$labels['duplicate.handle'] = 'handle:';
|
||||
$labels['duplicate.header'] = 'header:';
|
||||
$labels['duplicate.uniqueid'] = 'identifier:';
|
||||
$labels['duplicate.seconds'] = 'timeout (seconds):';
|
||||
$labels['duplicate.last'] = 'relative to the last execution';
|
||||
|
||||
$messages = array();
|
||||
$messages['filterunknownerror'] = 'Unknown server error.';
|
||||
@@ -199,6 +207,7 @@ $messages['filterdeleteerror'] = 'Unable to delete filter. Server error occurred
|
||||
$messages['filterdeleted'] = 'Filter deleted successfully.';
|
||||
$messages['filtersaved'] = 'Filter saved successfully.';
|
||||
$messages['filtersaveerror'] = 'Unable to save filter. Server error occurred.';
|
||||
$messages['filterformerror'] = 'Filter form contains errors.';
|
||||
$messages['filterdeleteconfirm'] = 'Do you really want to delete selected filter?';
|
||||
$messages['ruledeleteconfirm'] = 'Are you sure, you want to delete selected rule?';
|
||||
$messages['actiondeleteconfirm'] = 'Are you sure, you want to delete selected action?';
|
||||
@@ -228,5 +237,6 @@ $messages['invaliddateformat'] = 'Invalid date or date part format';
|
||||
$messages['saveerror'] = 'Unable to save data. Server error occurred.';
|
||||
$messages['vacationsaved'] = 'Vacation data saved successfully.';
|
||||
$messages['emptyvacationbody'] = 'Body of vacation message is required!';
|
||||
$messages['duplicate.conflict.err'] = 'Both header and unique identifier are not alowed.';
|
||||
|
||||
?>
|
||||
|
||||
@@ -599,6 +599,7 @@ function rule_header_select(id)
|
||||
{
|
||||
var obj = document.getElementById('header' + id),
|
||||
size = document.getElementById('rule_size' + id),
|
||||
msg = document.getElementById('rule_message' + id),
|
||||
op = document.getElementById('rule_op' + id),
|
||||
header = document.getElementById('custom_header' + id + '_list'),
|
||||
mod = document.getElementById('rule_mod' + id),
|
||||
@@ -610,7 +611,11 @@ function rule_header_select(id)
|
||||
|
||||
if (h == 'size') {
|
||||
size.style.display = 'inline';
|
||||
$.each([op, header, mod, trans, comp], function() { this.style.display = 'none'; });
|
||||
$.each([op, header, mod, trans, comp, msg], function() { this.style.display = 'none'; });
|
||||
}
|
||||
else if (h == 'message') {
|
||||
msg.style.display = 'inline';
|
||||
$.each([op, header, mod, trans, comp, size], function() { this.style.display = 'none'; });
|
||||
}
|
||||
else {
|
||||
header.style.display = h != '...' ? 'none' : 'inline-block';
|
||||
@@ -619,6 +624,7 @@ function rule_header_select(id)
|
||||
comp.style.display = '';
|
||||
mod.style.display = h == 'body' || h == 'currentdate' || h == 'date' ? 'none' : 'block';
|
||||
trans.style.display = h == 'body' ? 'block' : 'none';
|
||||
msg.style.display = h == 'message' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
if (datepart)
|
||||
@@ -638,7 +644,7 @@ function rule_op_select(obj, id, header)
|
||||
if (!header)
|
||||
header = document.getElementById('header' + id).value;
|
||||
|
||||
target.style.display = obj.value == 'exists' || obj.value == 'notexists' || header == 'size' ? 'none' : 'inline-block';
|
||||
target.style.display = obj.value.match(/^(exists|notexists)$/) || header.match(/^(size|message)$/) ? 'none' : 'inline-block';
|
||||
};
|
||||
|
||||
function rule_trans_select(id)
|
||||
@@ -653,6 +659,7 @@ function rule_mod_select(id, header)
|
||||
{
|
||||
var obj = document.getElementById('rule_mod_op' + id),
|
||||
target = document.getElementById('rule_mod_type' + id),
|
||||
duplicate = document.getElementById('rule_duplicate_div' + id),
|
||||
index = document.getElementById('rule_index_div' + id);
|
||||
|
||||
if (!header)
|
||||
@@ -661,7 +668,10 @@ function rule_mod_select(id, header)
|
||||
target.style.display = obj.value != 'address' && obj.value != 'envelope' ? 'none' : 'inline';
|
||||
|
||||
if (index)
|
||||
index.style.display = header != 'body' && header != 'currentdate' && header != 'size' && obj.value != 'envelope' ? '' : 'none';
|
||||
index.style.display = !header.match(/^(body|currentdate|size|message)$/) && obj.value != 'envelope' ? '' : 'none';
|
||||
|
||||
if (duplicate)
|
||||
duplicate.style.display = header == 'message' ? '' : 'none';
|
||||
};
|
||||
|
||||
function rule_join_radio(value)
|
||||
@@ -954,6 +964,13 @@ function sieve_form_init()
|
||||
.click(function() { // show drop-down upon clicks
|
||||
$(this).autocomplete('search', $(this).val() || ' ');
|
||||
})
|
||||
|
||||
// display advanced controls when contain errors
|
||||
$('input.error').each(function() {
|
||||
if (String(this.id).match(/([0-9]+)$/)) {
|
||||
$('#ruleadv' + RegExp.$1 + '.show').click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -172,12 +172,12 @@ td.advbutton a
|
||||
|
||||
td.advbutton a.show
|
||||
{
|
||||
background: url(images/down_small.gif) center no-repeat;
|
||||
background: url(images/down_small.gif?v=8629.106) center no-repeat;
|
||||
}
|
||||
|
||||
td.advbutton a.hide
|
||||
{
|
||||
background: url(images/up_small.gif) center no-repeat;
|
||||
background: url(images/up_small.gif?v=c56c.106) center no-repeat;
|
||||
}
|
||||
|
||||
td.rowbuttons
|
||||
@@ -225,6 +225,11 @@ td.rowtargets div a
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
td.rowtargets div.adv input
|
||||
{
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
html.mozilla #filter-form select
|
||||
{
|
||||
padding-top: 3px;
|
||||
@@ -255,6 +260,7 @@ select.operator_selector
|
||||
}
|
||||
|
||||
td.rowtargets span,
|
||||
td.rowtargets label,
|
||||
span.label
|
||||
{
|
||||
color: #666666;
|
||||
@@ -305,7 +311,7 @@ span.sieve.error
|
||||
|
||||
a.button.add
|
||||
{
|
||||
background: url(images/add.png) no-repeat;
|
||||
background: url(images/add.png?v=a165.280) no-repeat;
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
margin-right: 4px;
|
||||
@@ -314,7 +320,7 @@ a.button.add
|
||||
|
||||
a.button.del
|
||||
{
|
||||
background: url(images/del.png) no-repeat;
|
||||
background: url(images/del.png?v=3c27.247) no-repeat;
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
@@ -400,7 +406,7 @@ td.rowtargets > span.listarea
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url(images/erase.png) -1px 0 no-repeat #eee;
|
||||
background: url(images/erase.png?v=3052.453) -1px 0 no-repeat #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#messagemenu li a.filterlink {
|
||||
background-image: url(images/filter.png);
|
||||
background-image: url(images/filter.png?v=b0fe.547);
|
||||
background-position: 7px 1px;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ body.iframe
|
||||
#filter-form legend, #filter-form label
|
||||
{
|
||||
color: #666666;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#rules, #actions
|
||||
@@ -146,12 +147,12 @@ td.advbutton a
|
||||
|
||||
td.advbutton a.show
|
||||
{
|
||||
background: url(images/down_small.gif) center no-repeat;
|
||||
background: url(images/down_small.gif?v=8629.106) center no-repeat;
|
||||
}
|
||||
|
||||
td.advbutton a.hide
|
||||
{
|
||||
background: url(images/up_small.gif) center no-repeat;
|
||||
background: url(images/up_small.gif?v=c56c.106) center no-repeat;
|
||||
}
|
||||
|
||||
td.rowbuttons
|
||||
@@ -199,6 +200,11 @@ td.rowtargets div a {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
td.rowtargets div.adv input
|
||||
{
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
input.disabled, input.disabled:hover
|
||||
{
|
||||
color: #999999;
|
||||
@@ -282,7 +288,7 @@ a.button
|
||||
|
||||
a.button.add
|
||||
{
|
||||
background: url(images/add.png) no-repeat;
|
||||
background: url(images/add.png?v=a165.280) no-repeat;
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
margin-right: 4px;
|
||||
@@ -291,7 +297,7 @@ a.button.add
|
||||
|
||||
a.button.del
|
||||
{
|
||||
background: url(images/del.png) no-repeat;
|
||||
background: url(images/del.png?v=3c27.247) no-repeat;
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
@@ -393,7 +399,7 @@ td.rowtargets > span.listarea
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url(images/erase.png) -1px -1px no-repeat #eee;
|
||||
background: url(images/erase.png?v=3052.453) -1px -1px no-repeat #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -414,7 +420,7 @@ body.iframe.mail #filter-form
|
||||
|
||||
/* vacation form */
|
||||
#settings-sections .vacation a {
|
||||
background-image: url(images/vacation_icons.png);
|
||||
background-image: url(images/vacation_icons.png?v=e738.767);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 7px 1px;
|
||||
}
|
||||
|
||||
16
plugins/managesieve/tests/src/parser_duplicate
Normal file
16
plugins/managesieve/tests/src/parser_duplicate
Normal file
@@ -0,0 +1,16 @@
|
||||
require ["duplicate","fileinto"];
|
||||
# rule:[test-duplicate]
|
||||
if duplicate
|
||||
{
|
||||
fileinto "urgent";
|
||||
}
|
||||
# rule:[test-duplicate-2]
|
||||
if allof (duplicate :handle "support" :header "X-Ticket-ID", header :contains "subject" "fileserver")
|
||||
{
|
||||
fileinto "test";
|
||||
}
|
||||
# rule:[test-duplicate-3]
|
||||
if not duplicate :uniqueid "test" :seconds 1800
|
||||
{
|
||||
discard;
|
||||
}
|
||||
Reference in New Issue
Block a user