Managesieve: Partial support for mime extension [RFC5703] - parser only (#5832)

pull/5867/head
Aleksander Machniak 7 years ago
parent 6b90d56e56
commit 0fa4b75f78

@ -39,6 +39,7 @@ class rcube_sieve_script
'imap4flags', // RFC5232 'imap4flags', // RFC5232
'include', // RFC6609 'include', // RFC6609
'index', // RFC5260 'index', // RFC5260
'mime', // RFC5703 (except: foreverypart, break, enclose, extracttext)
'notify', // RFC5435 'notify', // RFC5435
'regex', // draft-ietf-sieve-regex-01 'regex', // draft-ietf-sieve-regex-01
'reject', // RFC5429 'reject', // RFC5429
@ -235,8 +236,11 @@ class rcube_sieve_script
break; break;
case 'exists': case 'exists':
$tests[$i] .= ($test['not'] ? 'not ' : ''); $tests[$i] .= ($test['not'] ? 'not ' : '') . 'exists';
$tests[$i] .= 'exists ' . self::escape_string($test['arg']);
$this->add_mime($test, $tests[$i], $exts);
$tests[$i] .= ' ' . self::escape_string($test['arg']);
break; break;
case 'header': case 'header':
@ -248,6 +252,10 @@ class rcube_sieve_script
$tests[$i] .= ($test['not'] ? 'not ' : ''); $tests[$i] .= ($test['not'] ? 'not ' : '');
$tests[$i] .= $test['test']; $tests[$i] .= $test['test'];
if ($test['test'] == 'header') {
$this->add_mime($test, $tests[$i], $exts);
}
$this->add_index($test, $tests[$i], $exts); $this->add_index($test, $tests[$i], $exts);
$this->add_operator($test, $tests[$i], $exts); $this->add_operator($test, $tests[$i], $exts);
@ -264,7 +272,8 @@ class rcube_sieve_script
$tests[$i] .= ($test['not'] ? 'not ' : ''); $tests[$i] .= ($test['not'] ? 'not ' : '');
$tests[$i] .= $test['test']; $tests[$i] .= $test['test'];
if ($test['test'] != 'envelope') { if ($test['test'] == 'address') {
$this->add_mime($test, $tests[$i], $exts);
$this->add_index($test, $tests[$i], $exts); $this->add_index($test, $tests[$i], $exts);
} }
@ -437,6 +446,21 @@ class rcube_sieve_script
$action_script .= self::escape_string($action['name']) . ' ' . self::escape_string($action['value']); $action_script .= self::escape_string($action['name']) . ' ' . self::escape_string($action['value']);
break; break;
case 'replace':
array_push($exts, 'mime');
$action_script .= 'replace';
if (!empty($action['mime'])) {
$action_script .= " :mime";
}
if (!empty($action['subject'])) {
$action_script .= " :subject " . self::escape_string($action['subject']);
}
if (!empty($action['from'])) {
$action_script .= " :from " . self::escape_string($action['from']);
}
$action_script .= ' ' . self::escape_string($action['replace']);
break;
case 'notify': case 'notify':
array_push($exts, $notify); array_push($exts, $notify);
$action_script .= 'notify'; $action_script .= 'notify';
@ -799,8 +823,9 @@ class rcube_sieve_script
break; break;
case 'exists': case 'exists':
$tests[] = array('test' => 'exists', 'not' => $not, $test = array('test' => 'exists', 'not' => $not, 'arg' => array_pop($tokens));
'arg' => array_pop($tokens)); $test += $this->test_tokens($tokens);
$tests[] = $test;
break; break;
case 'true': case 'true':
@ -907,6 +932,15 @@ class rcube_sieve_script
$result[] = $action; $result[] = $action;
break; break;
case 'replace':
$action = array('type' => 'replace', 'replace' => array_pop($tokens));
$args = array('mime');
$vargs = array('subject', 'from');
$action += $this->action_arguments($tokens, $args, $vargs);
$result[] = $action;
break;
case 'require': case 'require':
// skip, will be build according to used commands // skip, will be build according to used commands
// $result[] = array('type' => 'require', 'target' => array_pop($tokens)); // $result[] = array('type' => 'require', 'target' => array_pop($tokens));
@ -986,6 +1020,31 @@ class rcube_sieve_script
} }
} }
/**
* Add mime argument(s) to the test
*/
private function add_mime($test, &$out, &$exts)
{
foreach (array('mime', 'mime-anychild', 'mime-type', 'mime-subtype', 'mime-contenttype', 'mime-param') as $opt) {
if (!empty($test[$opt])) {
$opt_name = str_replace('mime-', '', $opt);
if (!$got_mime) {
$out .= ' :mime';
$got_mime = true;
array_push($exts, 'mime');
}
if ($opt_name != 'mime') {
$out .= " :$opt_name";
}
if ($opt_name == 'param') {
$out .= ' ' . self::escape_string($test[$opt]);
}
}
}
}
/** /**
* Add operators to the test * Add operators to the test
*/ */
@ -1021,25 +1080,31 @@ class rcube_sieve_script
$result = array(); $result = array();
for ($i=0, $len=count($tokens); $i<$len; $i++) { for ($i=0, $len=count($tokens); $i<$len; $i++) {
if (!is_array($tokens[$i]) && preg_match('/^:comparator$/i', $tokens[$i])) { $token = is_array($tokens[$i]) ? null : $tokens[$i];
if ($token && preg_match('/^:comparator$/i', $token)) {
$test['comparator'] = $tokens[++$i]; $test['comparator'] = $tokens[++$i];
} }
else if (!is_array($tokens[$i]) && preg_match('/^:(count|value)$/i', $tokens[$i])) { else if ($token && preg_match('/^:(count|value)$/i', $token)) {
$test['type'] = strtolower(substr($tokens[$i], 1)) . '-' . $tokens[++$i]; $test['type'] = strtolower(substr($token, 1)) . '-' . $tokens[++$i];
}
else if ($token && preg_match('/^:(is|contains|matches|regex)$/i', $token)) {
$test['type'] = strtolower(substr($token, 1));
} }
else if (!is_array($tokens[$i]) && preg_match('/^:(is|contains|matches|regex)$/i', $tokens[$i])) { else if ($token && preg_match('/^:(mime|anychild|type|subtype|contenttype|param)$/i', $token)) {
$test['type'] = strtolower(substr($tokens[$i], 1)); $token = strtolower(substr($token, 1));
$key = $token == 'mime' ? $token : "mime-$token";
$test[$key] = $token == 'param' ? $tokens[++$i] : true;
} }
else if (!is_array($tokens[$i]) && preg_match('/^:index$/i', $tokens[$i])) { else if ($token && preg_match('/^:index$/i', $token)) {
$test['index'] = intval($tokens[++$i]); $test['index'] = intval($tokens[++$i]);
if ($tokens[$i+1] && preg_match('/^:last$/i', $tokens[$i+1])) { if ($tokens[$i+1] && preg_match('/^:last$/i', $tokens[$i+1])) {
$test['last'] = true; $test['last'] = true;
$i++; $i++;
} }
} }
else { else {
$result[] = $tokens[$i]; $result[] = $tokens[$i];
} }
} }
$tokens = $result; $tokens = $result;
@ -1090,8 +1155,9 @@ class rcube_sieve_script
static function escape_string($str) static function escape_string($str)
{ {
if (is_array($str) && count($str) > 1) { if (is_array($str) && count($str) > 1) {
foreach ($str as $idx => $val) foreach ($str as $idx => $val) {
$str[$idx] = self::escape_string($val); $str[$idx] = self::escape_string($val);
}
return '[' . implode(',', $str) . ']'; return '[' . implode(',', $str) . ']';
} }

Loading…
Cancel
Save