diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php index 228213bee..e026f3e5f 100644 --- a/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php +++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php @@ -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) . ']'; }