sieve = new Net_Sieve(); if ($debug) { $this->sieve->setDebug(true, array($this, 'debug_handler')); } $result = $this->sieve->connect($host, $port, $options, $usetls); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_CONNECTION); } if (!empty($auth_cid)) { $authz = $username; $username = $auth_cid; } if (!empty($auth_pw)) { $password = $auth_pw; } $result = $this->sieve->login($username, $password, $auth_type ? strtoupper($auth_type) : null, $authz); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_LOGIN); } $this->exts = $this->get_extensions(); // disable features by config if (!empty($disabled)) { // we're working on lower-cased names $disabled = array_map('strtolower', (array) $disabled); foreach ($disabled as $ext) { if (($idx = array_search($ext, $this->exts)) !== false) { unset($this->exts[$idx]); } } } } public function __destruct() { $this->sieve->disconnect(); } /** * Getter for error code */ public function error() { return $this->error ?: false; } /** * Saves current script into server */ public function save($name = null) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } if (!$this->script) { return $this->_set_error(self::ERROR_INTERNAL); } if (!$name) { $name = $this->current; } $script = $this->script->as_text(); if (!$script) { $script = '/* empty script */'; } $result = $this->sieve->installScript($name, $script); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_INSTALL); } return true; } /** * Saves text script into server */ public function save_script($name, $content = null) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } if (!$content) { $content = '/* empty script */'; } $result = $this->sieve->installScript($name, $content); if (is_a($result, 'PEAR_Error')) { $rawErrorMessage = $result->getMessage(); $errMessages = preg_split("/$name:/", $rawErrorMessage); if (count($errMessages) > 0) { foreach ($errMessages as $singleError) { $matches = array(); $res = preg_match('/line (\d+):(.*)/i', $singleError, $matches); if ($res === 1 ) { if (count($matches) > 2) { $this->errorLines[] = array("line" => $matches[1], "msg" => $matches[2]); } else { $this->errorLines[] = array("line" => $matches[1], "msg" => null); } } } } return $this->_set_error(self::ERROR_INSTALL); } return true; } /** * Returns the current error line within the saved sieve script */ public function get_error_lines() { return $this->errorLines; } /** * Activates specified script */ public function activate($name = null) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } if (!$name) { $name = $this->current; } $result = $this->sieve->setActive($name); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_ACTIVATE); } return true; } /** * De-activates specified script */ public function deactivate() { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } $result = $this->sieve->setActive(''); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_DEACTIVATE); } return true; } /** * Removes specified script */ public function remove($name = null) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } if (!$name) { $name = $this->current; } // script must be deactivated first if ($name == $this->sieve->getActive()) { $result = $this->sieve->setActive(''); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_DELETE); } } $result = $this->sieve->removeScript($name); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_DELETE); } if ($name == $this->current) { $this->current = null; } return true; } /** * Gets list of supported by server Sieve extensions */ public function get_extensions() { if ($this->exts) return $this->exts; if (!$this->sieve) return $this->_set_error(self::ERROR_INTERNAL); $ext = $this->sieve->getExtensions(); if (is_a($ext, 'PEAR_Error')) { return array(); } // we're working on lower-cased names $ext = array_map('strtolower', (array) $ext); if ($this->script) { $supported = $this->script->get_extensions(); foreach ($ext as $idx => $ext_name) if (!in_array($ext_name, $supported)) unset($ext[$idx]); } return array_values($ext); } /** * Gets list of scripts from server */ public function get_scripts() { if (!$this->list) { if (!$this->sieve) return $this->_set_error(self::ERROR_INTERNAL); $list = $this->sieve->listScripts(); if (is_a($list, 'PEAR_Error')) { return $this->_set_error(self::ERROR_OTHER); } $this->list = $list; } return $this->list; } /** * Returns active script name */ public function get_active() { if (!$this->sieve) return $this->_set_error(self::ERROR_INTERNAL); return $this->sieve->getActive(); } /** * Loads script by name */ public function load($name) { if (!$this->sieve) return $this->_set_error(self::ERROR_INTERNAL); if ($this->current == $name) return true; $script = $this->sieve->getScript($name); if (is_a($script, 'PEAR_Error')) { return $this->_set_error(self::ERROR_OTHER); } // try to parse from Roundcube format $this->script = $this->_parse($script); $this->current = $name; return true; } /** * Loads script from text content */ public function load_script($script) { if (!$this->sieve) return $this->_set_error(self::ERROR_INTERNAL); // try to parse from Roundcube format $this->script = $this->_parse($script); } /** * Creates rcube_sieve_script object from text script */ private function _parse($txt) { // parse $script = new rcube_sieve_script($txt, $this->exts); // fix/convert to Roundcube format if (!empty($script->content)) { // replace all elsif with if+stop, we support only ifs foreach ($script->content as $idx => $rule) { if (empty($rule['type']) || !preg_match('/^(if|elsif|else)$/', $rule['type'])) { continue; } $script->content[$idx]['type'] = 'if'; // 'stop' not found? foreach ($rule['actions'] as $action) { if (preg_match('/^(stop|vacation)$/', $action['type'])) { continue 2; } } if (!empty($script->content[$idx+1]) && $script->content[$idx+1]['type'] != 'if') { $script->content[$idx]['actions'][] = array('type' => 'stop'); } } } return $script; } /** * Gets specified script as text */ public function get_script($name) { if (!$this->sieve) return $this->_set_error(self::ERROR_INTERNAL); $content = $this->sieve->getScript($name); if (is_a($content, 'PEAR_Error')) { return $this->_set_error(self::ERROR_OTHER); } return $content; } /** * Creates empty script or copy of other script */ public function copy($name, $copy) { if (!$this->sieve) return $this->_set_error(self::ERROR_INTERNAL); if ($copy) { $content = $this->sieve->getScript($copy); if (is_a($content, 'PEAR_Error')) { return $this->_set_error(self::ERROR_OTHER); } } return $this->save_script($name, $content); } private function _set_error($error) { $this->error = $error; return false; } /** * This is our own debug handler for connection */ public function debug_handler(&$sieve, $message) { rcube::write_log('sieve', preg_replace('/\r\n$/', '', $message)); } }