rcube_sieve_script::as_text PHP Method

as_text() public method

public as_text ( )
    public function as_text()
    {
        $script = '';
        $variables = '';
        $exts = array();
        // rules
        $activeRules = 0;
        foreach ($this->content as $rule) {
            $tests = array();
            $i = 0;
            if ($rule['disabled'] == 1) {
                $script .= '# rule:[' . $rule['name'] . "]" . RCUBE_SIEVE_NEWLINE;
                $script .= '# disabledRule:[' . $this->_safe_serial(serialize($rule)) . "]" . RCUBE_SIEVE_NEWLINE;
            } else {
                // header
                $script .= '# rule:[' . $rule['name'] . "]" . RCUBE_SIEVE_NEWLINE;
                // constraints expressions
                foreach ($rule['tests'] as $test) {
                    $tests[$i] = '';
                    switch ($test['type']) {
                        case 'size':
                            $tests[$i] .= $test['not'] ? 'not ' : '';
                            $tests[$i] .= 'size :' . ($test['operator'] == 'under' ? 'under ' : 'over ') . $test['target'];
                            break;
                        case 'virustest':
                        case 'spamtest':
                            array_push($exts, $test['type']);
                            array_push($exts, 'relational');
                            array_push($exts, 'comparator-i;ascii-numeric');
                            $tests[$i] .= $test['not'] ? 'not ' : '';
                            $tests[$i] .= $test['type'] . ' :value ' . ($test['operator'] == 'eq' ? '"eq" ' : ($test['operator'] == 'le' ? '"le" ' : '"ge" ')) . ':comparator "i;ascii-numeric" "' . $test['target'] . '"';
                            break;
                        case 'true':
                            $tests[$i] .= $test['not'] ? 'not true' : 'true';
                            break;
                        case 'exists':
                            $tests[$i] .= $test['not'] ? 'not ' : '';
                            if (is_array($test['header'])) {
                                $tests[$i] .= 'exists ["' . implode('", "', $this->_escape_string($test['header'])) . '"]';
                            } else {
                                $tests[$i] .= 'exists "' . $this->_escape_string($test['header']) . '"';
                            }
                            break;
                        case 'envelope':
                            array_push($exts, 'envelope');
                        case 'header':
                        case 'address':
                            if ($test['operator'] == 'regex') {
                                array_push($exts, 'regex');
                            } elseif (substr($test['operator'], 0, 5) == 'count' || substr($test['operator'], 0, 5) == 'value') {
                                array_push($exts, 'relational');
                            } elseif ($test['operator'] == 'user' || $test['operator'] == 'detail' || $test['operator'] == 'domain') {
                                array_push($exts, 'subaddress');
                            }
                            $tests[$i] .= $test['not'] ? 'not ' : '';
                            $tests[$i] .= $test['type'] . ' :' . $test['operator'];
                            if ($test['comparator'] != '') {
                                if ($test['comparator'] != 'i;ascii-casemap' && $test['comparator'] != 'i;octet') {
                                    array_push($exts, 'comparator-' . $test['comparator']);
                                }
                                $tests[$i] .= ' :comparator "' . $test['comparator'] . '"';
                            }
                            if (is_array($test['header'])) {
                                $tests[$i] .= ' ["' . implode('", "', $this->_escape_string($test['header'])) . '"]';
                            } else {
                                $tests[$i] .= ' "' . $this->_escape_string($test['header']) . '"';
                            }
                            if (is_array($test['target'])) {
                                $tests[$i] .= ' ["' . implode('", "', $this->_escape_string($test['target'])) . '"]';
                            } else {
                                $tests[$i] .= ' "' . $this->_escape_string($test['target']) . '"';
                            }
                            break;
                        case 'body':
                            array_push($exts, 'body');
                            if ($test['operator'] == 'regex') {
                                array_push($exts, 'regex');
                            } elseif (substr($test['operator'], 0, 5) == 'count' || substr($test['operator'], 0, 5) == 'value') {
                                array_push($exts, 'relational');
                            }
                            $tests[$i] .= $test['not'] ? 'not ' : '';
                            $tests[$i] .= $test['type'];
                            if ($test['bodypart'] != '') {
                                $tests[$i] .= ' :' . $test['bodypart'];
                            }
                            if ($test['contentpart'] != '') {
                                $tests[$i] .= ' "' . $test['contentpart'] . '"';
                            }
                            $tests[$i] .= ' :' . $test['operator'];
                            if ($test['comparator'] != '') {
                                if ($test['comparator'] != 'i;ascii-casemap' && $test['comparator'] != 'i;octet') {
                                    array_push($exts, 'comparator-' . $test['comparator']);
                                }
                                $tests[$i] .= ' :comparator "' . $test['comparator'] . '"';
                            }
                            if (is_array($test['target'])) {
                                $tests[$i] .= ' ["' . implode('", "', $this->_escape_string($test['target'])) . '"]';
                            } else {
                                $tests[$i] .= ' "' . $this->_escape_string($test['target']) . '"';
                            }
                            break;
                        case 'date':
                            array_push($exts, 'date');
                            if ($test['operator'] == 'regex') {
                                array_push($exts, 'regex');
                            } elseif (substr($test['operator'], 0, 5) == 'count' || substr($test['operator'], 0, 5) == 'value') {
                                array_push($exts, 'relational');
                            }
                            $tests[$i] .= $test['not'] ? 'not ' : '';
                            $tests[$i] .= $test['header'];
                            $timezone = rcube::get_instance()->config->get('timezone', 'auto');
                            if ($timezone != 'auto') {
                                $tz = new DateTimeZone($timezone);
                                $date = new DateTime('now', $tz);
                                $tests[$i] .= ' :zone ' . '"' . $date->format('O') . '"';
                            }
                            $tests[$i] .= ' :' . $test['operator'];
                            if ($test['comparator'] != '') {
                                if ($test['comparator'] != 'i;ascii-casemap' && $test['comparator'] != 'i;octet') {
                                    array_push($exts, 'comparator-' . $test['comparator']);
                                }
                                $tests[$i] .= ' :comparator "' . $test['comparator'] . '"';
                            }
                            $tests[$i] .= ' "' . $this->_escape_string($test['datepart']) . '"';
                            $tests[$i] .= ' "' . $this->_escape_string($test['target']) . '"';
                            break;
                    }
                    $i++;
                }
                $script .= ($activeRules > 0 && $this->elsif ? 'els' : '') . ($rule['join'] ? 'if allof (' : 'if anyof (');
                $activeRules++;
                if (sizeof($tests) > 1) {
                    $script .= implode("," . RCUBE_SIEVE_NEWLINE . RCUBE_SIEVE_INDENT, $tests);
                } elseif (sizeof($tests)) {
                    $script .= $tests[0];
                } else {
                    $script .= 'true';
                }
                $script .= ")" . RCUBE_SIEVE_NEWLINE . "{" . RCUBE_SIEVE_NEWLINE;
                // action(s)
                $actions = '';
                foreach ($rule['actions'] as $action) {
                    switch ($action['type']) {
                        case 'fileinto':
                        case 'fileinto_copy':
                            array_push($exts, 'fileinto');
                            $args = '';
                            if ($action['type'] == 'fileinto_copy') {
                                array_push($exts, 'copy');
                                $args .= ' :copy';
                            }
                            if ($action['create']) {
                                array_push($exts, 'mailbox');
                                $args .= ' :create';
                            }
                            // variables support in fileinto by David Warden
                            if (preg_match('/\\$\\{\\d+\\}/', $action['target'])) {
                                array_push($exts, 'variables');
                            }
                            $actions .= RCUBE_SIEVE_INDENT . "fileinto" . $args . " \"" . $this->_escape_string($action['target']) . "\";" . RCUBE_SIEVE_NEWLINE;
                            break;
                        case 'redirect':
                        case 'redirect_copy':
                            $args = '';
                            if ($action['type'] == 'redirect_copy') {
                                array_push($exts, 'copy');
                                $args .= ' :copy';
                            }
                            $tokens = preg_split('/[,;\\s]/', $action['target']);
                            foreach ($tokens as $email) {
                                $actions .= RCUBE_SIEVE_INDENT . "redirect" . $args . " \"" . $this->_escape_string($email) . "\";" . RCUBE_SIEVE_NEWLINE;
                            }
                            break;
                        case 'reject':
                        case 'ereject':
                            array_push($exts, $action['type']);
                            if (strpos($action['target'], "\n") !== false) {
                                $actions .= RCUBE_SIEVE_INDENT . $action['type'] . " text:" . RCUBE_SIEVE_NEWLINE . $action['target'] . RCUBE_SIEVE_NEWLINE . "." . RCUBE_SIEVE_NEWLINE . ";" . RCUBE_SIEVE_NEWLINE;
                            } else {
                                $actions .= RCUBE_SIEVE_INDENT . $action['type'] . " \"" . $this->_escape_string($action['target']) . "\";" . RCUBE_SIEVE_NEWLINE;
                            }
                            break;
                        case 'vacation':
                            array_push($exts, 'vacation');
                            $action['subject'] = $this->_escape_string($action['subject']);
                            //							// encoding subject header with mb_encode provides better results with asian characters
                            //							if (function_exists("mb_encode_mimeheader"))
                            //							{
                            //								mb_internal_encoding($action['charset']);
                            //								$action['subject'] = mb_encode_mimeheader($action['subject'], $action['charset'], 'Q');
                            //								mb_internal_encoding(RCUBE_CHARSET);
                            //							}
                            // detect original recipient
                            if ($action['from'] == 'auto') {
                                if (strpos($variables, 'set "from"') === false) {
                                    array_push($exts, 'variables');
                                    $variables .= 'set "from" "";' . RCUBE_SIEVE_NEWLINE;
                                    $variables .= 'if header :matches "to" "*" {' . RCUBE_SIEVE_NEWLINE;
                                    $variables .= RCUBE_SIEVE_INDENT . 'set "from" "${1}";' . RCUBE_SIEVE_NEWLINE;
                                    $variables .= '}' . RCUBE_SIEVE_NEWLINE;
                                }
                                $action['from'] = "\${from}";
                            } elseif ($action['from'] == 'auto') {
                                $action['from'] = "\${from}";
                            }
                            // append original subject
                            if ($action['origsubject'] == '1') {
                                if (strpos($variables, 'set "subject"') === false) {
                                    array_push($exts, 'variables');
                                    $variables .= 'set "subject" "";' . RCUBE_SIEVE_NEWLINE;
                                    $variables .= 'if header :matches "subject" "*" {' . RCUBE_SIEVE_NEWLINE;
                                    $variables .= RCUBE_SIEVE_INDENT . 'set "subject" "${1}";' . RCUBE_SIEVE_NEWLINE;
                                    $variables .= '}' . RCUBE_SIEVE_NEWLINE;
                                }
                                $action['subject'] = trim($action['subject']);
                                if (substr($action['subject'], -1, 1) != ":") {
                                    $action['subject'] .= ":";
                                }
                                $action['subject'] .= " \${subject}";
                            }
                            $actions .= RCUBE_SIEVE_INDENT . "vacation" . RCUBE_SIEVE_NEWLINE;
                            if (!empty($action['seconds'])) {
                                array_push($exts, 'vacation-seconds');
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":seconds " . $action['seconds'] . RCUBE_SIEVE_NEWLINE;
                            } elseif (!empty($action['days'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":days " . $action['days'] . RCUBE_SIEVE_NEWLINE;
                            }
                            if (!empty($action['addresses'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":addresses [\"" . str_replace(",", "\",\"", $this->_escape_string($action['addresses'])) . "\"]" . RCUBE_SIEVE_NEWLINE;
                            }
                            if (!empty($action['subject'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":subject \"" . $action['subject'] . "\"" . RCUBE_SIEVE_NEWLINE;
                            }
                            if (!empty($action['handle'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":handle \"" . $this->_escape_string($action['handle']) . "\"" . RCUBE_SIEVE_NEWLINE;
                            }
                            if (!empty($action['from'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":from \"" . $this->_escape_string($action['from']) . "\"" . RCUBE_SIEVE_NEWLINE;
                            }
                            if ($action['htmlmsg']) {
                                $MAIL_MIME = new Mail_mime("\r\n");
                                $action['msg'] = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">' . "\r\n<html><body>\r\n" . $action['msg'] . "\r\n</body></html>\r\n";
                                $MAIL_MIME->setHTMLBody($action['msg']);
                                // add a plain text version of the e-mail as an alternative part.
                                $h2t = new rcube_html2text($action['msg'], false, true, 0);
                                $plainTextPart = $h2t->get_text();
                                if (!$plainTextPart) {
                                    // empty message body breaks attachment handling in drafts
                                    $plainTextPart = "\r\n";
                                } else {
                                    // make sure all line endings are CRLF (#1486712)
                                    $plainTextPart = preg_replace('/\\r?\\n/', "\r\n", $plainTextPart);
                                }
                                $MAIL_MIME->setTXTBody($plainTextPart);
                                $MAIL_MIME->setParam('html_charset', $action['charset']);
                                $MAIL_MIME->setParam('text_charset', $action['charset']);
                                $action['msg'] = $MAIL_MIME->getMessage();
                            }
                            // escape lines which start is a .
                            $action['msg'] = preg_replace('/(^|\\r?\\n)\\./', "\$1..", $action['msg']);
                            if ($action['htmlmsg']) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":mime text:" . RCUBE_SIEVE_NEWLINE . $action['msg'] . RCUBE_SIEVE_NEWLINE . "." . RCUBE_SIEVE_NEWLINE . ";" . RCUBE_SIEVE_NEWLINE;
                            } elseif ($action['charset'] != "UTF-8") {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":mime text:" . RCUBE_SIEVE_NEWLINE . "Content-Type: text/plain; charset=" . $action['charset'] . RCUBE_SIEVE_NEWLINE . RCUBE_SIEVE_NEWLINE . $action['msg'] . RCUBE_SIEVE_NEWLINE . "." . RCUBE_SIEVE_NEWLINE . ";" . RCUBE_SIEVE_NEWLINE;
                            } elseif (strpos($action['msg'], "\n") !== false) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . "text:" . RCUBE_SIEVE_NEWLINE . $action['msg'] . RCUBE_SIEVE_NEWLINE . "." . RCUBE_SIEVE_NEWLINE . ";" . RCUBE_SIEVE_NEWLINE;
                            } else {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . "\"" . $this->_escape_string($action['msg']) . "\";" . RCUBE_SIEVE_NEWLINE;
                            }
                            break;
                        case 'imapflags':
                        case 'imap4flags':
                            array_push($exts, $action['type']);
                            if (strpos($actions, "setflag") !== false) {
                                $actions .= RCUBE_SIEVE_INDENT . "addflag \"" . $this->_escape_string($action['target']) . "\";" . RCUBE_SIEVE_NEWLINE;
                            } else {
                                $actions .= RCUBE_SIEVE_INDENT . "setflag \"" . $this->_escape_string($action['target']) . "\";" . RCUBE_SIEVE_NEWLINE;
                            }
                            break;
                        case 'notify':
                            array_push($exts, 'notify');
                            $actions .= RCUBE_SIEVE_INDENT . "notify" . RCUBE_SIEVE_NEWLINE;
                            $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":method \"" . $this->_escape_string($action['method']) . "\"" . RCUBE_SIEVE_NEWLINE;
                            if (!empty($action['options'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":options [\"" . str_replace(",", "\",\"", $this->_escape_string($action['options'])) . "\"]" . RCUBE_SIEVE_NEWLINE;
                            }
                            if (!empty($action['from'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":from \"" . $this->_escape_string($action['from']) . "\"" . RCUBE_SIEVE_NEWLINE;
                            }
                            if (!empty($action['importance'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":importance \"" . $this->_escape_string($action['importance']) . "\"" . RCUBE_SIEVE_NEWLINE;
                            }
                            $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":message \"" . $this->_escape_string($action['msg']) . "\";" . RCUBE_SIEVE_NEWLINE;
                            break;
                        case 'enotify':
                            array_push($exts, 'enotify');
                            $actions .= RCUBE_SIEVE_INDENT . "notify" . RCUBE_SIEVE_NEWLINE;
                            if (!empty($action['options'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":options [\"" . str_replace(",", "\",\"", $this->_escape_string($action['options'])) . "\"]" . RCUBE_SIEVE_NEWLINE;
                            }
                            if (!empty($action['from'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":from \"" . $this->_escape_string($action['from']) . "\"" . RCUBE_SIEVE_NEWLINE;
                            }
                            if (!empty($action['importance'])) {
                                $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":importance \"" . $this->_escape_string($action['importance']) . "\"" . RCUBE_SIEVE_NEWLINE;
                            }
                            $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . ":message \"" . $this->_escape_string($action['msg']) . "\"" . RCUBE_SIEVE_NEWLINE;
                            $actions .= RCUBE_SIEVE_INDENT . RCUBE_SIEVE_INDENT . "\"" . $this->_escape_string($action['method']) . "\";" . RCUBE_SIEVE_NEWLINE;
                            break;
                        case 'editheaderadd':
                            array_push($exts, 'editheader');
                            $actions .= RCUBE_SIEVE_INDENT . "addheader";
                            if ($action['index'] == 'last') {
                                $actions .= " :last";
                            }
                            $actions .= " \"" . $this->_escape_string($action['name']) . "\" \"" . $this->_escape_string($action['value']) . "\";" . RCUBE_SIEVE_NEWLINE;
                            break;
                        case 'editheaderrem':
                            array_push($exts, 'editheader');
                            $actions .= RCUBE_SIEVE_INDENT . "deleteheader";
                            if (is_numeric($action['index'])) {
                                $actions .= " :index " . $action['index'];
                            } elseif ($action['index'] == 'last') {
                                $actions .= " :last";
                            }
                            if (strlen($action['operator']) > 0) {
                                $actions .= " :" . $action['operator'];
                            }
                            $actions .= " \"" . $this->_escape_string($action['name']) . "\"";
                            if (strlen($action['value']) > 0) {
                                $actions .= " \"" . $this->_escape_string($action['value']) . "\"";
                            }
                            $actions .= ";" . RCUBE_SIEVE_NEWLINE;
                            break;
                        case 'variables':
                            array_push($exts, 'variables');
                            $actions .= RCUBE_SIEVE_INDENT . "set \"" . $this->_escape_string($action['name']) . "\" \"" . $this->_escape_string($action['value']) . "\";" . RCUBE_SIEVE_NEWLINE;
                            break;
                        case 'keep':
                        case 'discard':
                        case 'stop':
                            $actions .= RCUBE_SIEVE_INDENT . $action['type'] . ";" . RCUBE_SIEVE_NEWLINE;
                            break;
                    }
                }
                $script .= $actions . "}" . RCUBE_SIEVE_NEWLINE;
            }
        }
        if ($variables) {
            $variables .= RCUBE_SIEVE_NEWLINE;
        }
        // requires
        $exts = array_unique($exts);
        if (sizeof($exts)) {
            $script = 'require ["' . implode('","', $exts) . "\"];" . RCUBE_SIEVE_NEWLINE . RCUBE_SIEVE_NEWLINE . $variables . $script;
        }
        // author
        if ($script && RCUBE_SIEVE_HEADER) {
            $script = RCUBE_SIEVE_HEADER . RCUBE_SIEVE_NEWLINE . $script;
        }
        return $script;
    }

Usage Example

Example #1
0
 /**
  * Sieve script parsing
  *
  * @dataProvider data_parser
  */
 function test_parser($input, $output, $message)
 {
     // get capabilities list from the script
     $caps = array();
     if (preg_match('/require \\[([a-z0-9", ]+)\\]/', $input, $m)) {
         foreach (explode(',', $m[1]) as $cap) {
             $caps[] = trim($cap, '" ');
         }
     }
     $script = new rcube_sieve_script($input, $caps);
     $result = $script->as_text();
     $this->assertEquals(trim($result), trim($output), $message);
 }