|
|
|
@ -39,6 +39,7 @@ class rcube_sieve_script
|
|
|
|
|
'imap4flags', // RFC5232
|
|
|
|
|
'include', // RFC6609
|
|
|
|
|
'index', // RFC5260
|
|
|
|
|
'mime', // RFC5703 (except: foreverypart, break, enclose, extracttext)
|
|
|
|
|
'notify', // RFC5435
|
|
|
|
|
'regex', // draft-ietf-sieve-regex-01
|
|
|
|
|
'reject', // RFC5429
|
|
|
|
@ -235,8 +236,11 @@ class rcube_sieve_script
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'exists':
|
|
|
|
|
$tests[$i] .= ($test['not'] ? 'not ' : '');
|
|
|
|
|
$tests[$i] .= 'exists ' . self::escape_string($test['arg']);
|
|
|
|
|
$tests[$i] .= ($test['not'] ? 'not ' : '') . 'exists';
|
|
|
|
|
|
|
|
|
|
$this->add_mime($test, $tests[$i], $exts);
|
|
|
|
|
|
|
|
|
|
$tests[$i] .= ' ' . self::escape_string($test['arg']);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'header':
|
|
|
|
@ -248,6 +252,10 @@ class rcube_sieve_script
|
|
|
|
|
$tests[$i] .= ($test['not'] ? 'not ' : '');
|
|
|
|
|
$tests[$i] .= $test['test'];
|
|
|
|
|
|
|
|
|
|
if ($test['test'] == 'header') {
|
|
|
|
|
$this->add_mime($test, $tests[$i], $exts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->add_index($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['test'];
|
|
|
|
|
|
|
|
|
|
if ($test['test'] != 'envelope') {
|
|
|
|
|
if ($test['test'] == 'address') {
|
|
|
|
|
$this->add_mime($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']);
|
|
|
|
|
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':
|
|
|
|
|
array_push($exts, $notify);
|
|
|
|
|
$action_script .= 'notify';
|
|
|
|
@ -799,8 +823,9 @@ class rcube_sieve_script
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'exists':
|
|
|
|
|
$tests[] = array('test' => 'exists', 'not' => $not,
|
|
|
|
|
'arg' => array_pop($tokens));
|
|
|
|
|
$test = array('test' => 'exists', 'not' => $not, 'arg' => array_pop($tokens));
|
|
|
|
|
$test += $this->test_tokens($tokens);
|
|
|
|
|
$tests[] = $test;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'true':
|
|
|
|
@ -907,6 +932,15 @@ class rcube_sieve_script
|
|
|
|
|
$result[] = $action;
|
|
|
|
|
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':
|
|
|
|
|
// skip, will be build according to used commands
|
|
|
|
|
// $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
|
|
|
|
|
*/
|
|
|
|
@ -1021,25 +1080,31 @@ class rcube_sieve_script
|
|
|
|
|
$result = array();
|
|
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|
else if (!is_array($tokens[$i]) && preg_match('/^:(count|value)$/i', $tokens[$i])) {
|
|
|
|
|
$test['type'] = strtolower(substr($tokens[$i], 1)) . '-' . $tokens[++$i];
|
|
|
|
|
else if ($token && preg_match('/^:(count|value)$/i', $token)) {
|
|
|
|
|
$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])) {
|
|
|
|
|
$test['type'] = strtolower(substr($tokens[$i], 1));
|
|
|
|
|
else if ($token && preg_match('/^:(mime|anychild|type|subtype|contenttype|param)$/i', $token)) {
|
|
|
|
|
$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]);
|
|
|
|
|
if ($tokens[$i+1] && preg_match('/^:last$/i', $tokens[$i+1])) {
|
|
|
|
|
$test['last'] = true;
|
|
|
|
|
$i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$result[] = $tokens[$i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$result[] = $tokens[$i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$tokens = $result;
|
|
|
|
@ -1090,8 +1155,9 @@ class rcube_sieve_script
|
|
|
|
|
static function escape_string($str)
|
|
|
|
|
{
|
|
|
|
|
if (is_array($str) && count($str) > 1) {
|
|
|
|
|
foreach ($str as $idx => $val)
|
|
|
|
|
foreach ($str as $idx => $val) {
|
|
|
|
|
$str[$idx] = self::escape_string($val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return '[' . implode(',', $str) . ']';
|
|
|
|
|
}
|
|
|
|
|