summaryrefslogtreecommitdiff
path: root/plugins/managesieve
diff options
context:
space:
mode:
authoralec <alec@208e9e7b-5314-0410-a742-e7e81cd9613c>2011-10-03 11:49:33 +0000
committeralec <alec@208e9e7b-5314-0410-a742-e7e81cd9613c>2011-10-03 11:49:33 +0000
commit7c3bcde7b32ed8ec5566ad5db0b07754b5e3f7fd (patch)
tree12cc992763c0cc22619e1b89df9d75e679ffb817 /plugins/managesieve
parente4def8a1bd65cb1ae33d6c0e7c44f3f516c8edc8 (diff)
- Fixed doubled Filter tab on page refresh
- Added filters set selector in filter form when invoked in mail task - Improved script parser, added support for include and variables extensions - Added Kolab's KEP:14 support (http://wiki.kolab.org/User:Greve/Drafts/KEP:14) git-svn-id: https://svn.roundcube.net/trunk@5300 208e9e7b-5314-0410-a742-e7e81cd9613c
Diffstat (limited to 'plugins/managesieve')
-rw-r--r--plugins/managesieve/Changelog4
-rw-r--r--plugins/managesieve/config.inc.php.dist7
-rw-r--r--plugins/managesieve/lib/rcube_sieve.php91
-rw-r--r--plugins/managesieve/lib/rcube_sieve_script.php536
-rw-r--r--plugins/managesieve/managesieve.js17
-rw-r--r--plugins/managesieve/managesieve.php362
-rw-r--r--plugins/managesieve/skins/default/managesieve.css2
7 files changed, 713 insertions, 306 deletions
diff --git a/plugins/managesieve/Changelog b/plugins/managesieve/Changelog
index b0bb2b2fa..dfe5f0d58 100644
--- a/plugins/managesieve/Changelog
+++ b/plugins/managesieve/Changelog
@@ -5,6 +5,10 @@
- Fixed PHP warning on connection error when submitting filter form
- Fixed bug where new action row with flags wasn't handled properly
- Added managesieve_connect hook for plugins
+- Fixed doubled Filter tab on page refresh
+- Added filters set selector in filter form when invoked in mail task
+- Improved script parser, added support for include and variables extensions
+- Added Kolab's KEP:14 support (http://wiki.kolab.org/User:Greve/Drafts/KEP:14)
* version 4.3 [2011-07-28]
-----------------------------------------------------------
diff --git a/plugins/managesieve/config.inc.php.dist b/plugins/managesieve/config.inc.php.dist
index d080347a1..b721dc7c6 100644
--- a/plugins/managesieve/config.inc.php.dist
+++ b/plugins/managesieve/config.inc.php.dist
@@ -53,4 +53,11 @@ $rcmail_config['managesieve_disabled_extensions'] = array();
// Enables debugging of conversation with sieve server. Logs it into <log_dir>/sieve
$rcmail_config['managesieve_debug'] = false;
+// Enables features described in http://wiki.kolab.org/KEP:14
+$rcmail_config['managesieve_kolab_master'] = false;
+
+// Script name extension used for scripts including. Dovecot uses '.sieve',
+// Cyrus uses '.siv'. Doesn't matter if you have managesieve_kolab_master disabled.
+$rcmail_config['managesieve_filename_extension'] = '.sieve';
+
?>
diff --git a/plugins/managesieve/lib/rcube_sieve.php b/plugins/managesieve/lib/rcube_sieve.php
index 7f989e098..7b7ea6eb6 100644
--- a/plugins/managesieve/lib/rcube_sieve.php
+++ b/plugins/managesieve/lib/rcube_sieve.php
@@ -1,13 +1,27 @@
<?php
/**
- Classes for managesieve operations (using PEAR::Net_Sieve)
-
- Author: Aleksander Machniak <alec@alec.pl>
-
- $Id$
-
-*/
+ * Classes for managesieve operations (using PEAR::Net_Sieve)
+ *
+ * Copyright (C) 2008-2011, The Roundcube Dev Team
+ * Copyright (C) 2011, Kolab Systems AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * $Id$
+ *
+ */
// Managesieve Protocol: RFC5804
@@ -195,7 +209,7 @@ class rcube_sieve
{
if ($this->exts)
return $this->exts;
-
+
if (!$this->sieve)
return $this->_set_error(SIEVE_ERROR_INTERNAL);
@@ -286,23 +300,28 @@ class rcube_sieve
*/
private function _parse($txt)
{
- // try to parse from Roundcube format
+ // parse
$script = new rcube_sieve_script($txt, $this->disabled, $this->exts);
- // ... else try to import from different formats
- if (empty($script->content)) {
- $script = $this->_import_rules($txt);
- $script = new rcube_sieve_script($script, $this->disabled, $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;
}
}
- $script->content[$idx]['actions'][] = array('type' => 'stop');
+ if (empty($script->content[$idx+1]) || $script->content[$idx+1]['type'] != 'if') {
+ $script->content[$idx]['actions'][] = array('type' => 'stop');
+ }
}
}
@@ -343,48 +362,6 @@ class rcube_sieve
return $this->save_script($name, $content);
}
- private function _import_rules($script)
- {
- $i = 0;
- $name = array();
-
- // Squirrelmail (Avelsieve)
- if (preg_match('/(#START_SIEVE_RULE.*END_SIEVE_RULE)\r?\n/', $script)) {
- $tokens = preg_split('/(#START_SIEVE_RULE.*END_SIEVE_RULE)\r?\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE);
- foreach ($tokens as $token) {
- if (preg_match('/^#START_SIEVE_RULE.*/', $token, $matches)) {
- $name[$i] = "unnamed rule ".($i+1);
- $content .= "# rule:[".$name[$i]."]\n";
- }
- elseif (isset($name[$i])) {
- // This preg_replace is added because I've found some Avelsieve scripts
- // with rules containing "if" here. I'm not sure it was working
- // before without this or not.
- $token = preg_replace('/^if\s+/', '', trim($token));
- $content .= "if $token\n";
- $i++;
- }
- }
- }
- // Horde (INGO)
- else if (preg_match('/(# .+)\r?\n/', $script)) {
- $tokens = preg_split('/(# .+)\r?\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE);
- foreach($tokens as $token) {
- if (preg_match('/^# (.+)/', $token, $matches)) {
- $name[$i] = $matches[1];
- $content .= "# rule:[" . $name[$i] . "]\n";
- }
- elseif (isset($name[$i])) {
- $token = str_replace(":comparator \"i;ascii-casemap\" ", "", $token);
- $content .= $token . "\n";
- $i++;
- }
- }
- }
-
- return $content;
- }
-
private function _set_error($error)
{
$this->error = $error;
diff --git a/plugins/managesieve/lib/rcube_sieve_script.php b/plugins/managesieve/lib/rcube_sieve_script.php
index 65f8d865c..e303f2779 100644
--- a/plugins/managesieve/lib/rcube_sieve_script.php
+++ b/plugins/managesieve/lib/rcube_sieve_script.php
@@ -1,19 +1,36 @@
<?php
/**
- Class for operations on Sieve scripts
-
- Author: Aleksander Machniak <alec@alec.pl>
-
- $Id$
-
-*/
+ * Class for operations on Sieve scripts
+ *
+ * Copyright (C) 2008-2011, The Roundcube Dev Team
+ * Copyright (C) 2011, Kolab Systems AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * $Id$
+ *
+ */
class rcube_sieve_script
{
public $content = array(); // script rules array
- private $supported = array( // extensions supported by class
+ private $vars = array(); // "global" variables
+ private $prefix = ''; // script header (comments)
+ private $capabilities = array(); // Sieve extensions supported by server
+ private $supported = array( // Sieve extensions supported by class
'fileinto', // RFC3028
'reject', // RFC5429
'ereject', // RFC5429
@@ -23,11 +40,11 @@ class rcube_sieve_script
'regex', // draft-ietf-sieve-regex-01
'imapflags', // draft-melnikov-sieve-imapflags-06
'imap4flags', // RFC5232
+ 'include', // draft-ietf-sieve-include-12
+ 'variables', // RFC5229
// TODO: body, notify
);
- private $capabilities;
-
/**
* Object constructor
*
@@ -35,7 +52,7 @@ class rcube_sieve_script
* @param array List of disabled extensions
* @param array List of capabilities supported by server
*/
- public function __construct($script, $disabled=null, $capabilities=null)
+ public function __construct($script, $disabled=array(), $capabilities=array())
{
if (!empty($disabled)) {
// we're working on lower-cased names
@@ -47,33 +64,10 @@ class rcube_sieve_script
}
}
- $this->capabilities = $capabilities;
- $this->content = $this->_parse_text($script);
- }
-
- /**
- * Adds script contents as text to the script array (at the end)
- *
- * @param string Text script contents
- */
- public function add_text($script)
- {
- $content = $this->_parse_text($script);
- $result = false;
-
- // check existsing script rules names
- foreach ($this->content as $idx => $elem) {
- $names[$elem['name']] = $idx;
- }
-
- foreach ($content as $elem) {
- if (!isset($names[$elem['name']])) {
- array_push($this->content, $elem);
- $result = true;
- }
- }
+ $this->capabilities = array_map('strtolower', (array) $capabilities);
- return $result;
+ // Parse text content of the script
+ $this->_parse_text($script);
}
/**
@@ -81,6 +75,8 @@ class rcube_sieve_script
*
* @param string Rule name
* @param array Rule content (as array)
+ *
+ * @return int The index of the new rule
*/
public function add_rule($content)
{
@@ -114,161 +110,272 @@ class rcube_sieve_script
}
/**
+ * Sets "global" variable
+ *
+ * @param string $name Variable name
+ * @param string $value Variable value
+ * @param array $mods Variable modifiers
+ */
+ public function set_var($name, $value, $mods = array())
+ {
+ // Check if variable exists
+ for ($i=0, $len=count($this->vars); $i<$len; $i++) {
+ if ($this->vars[$i]['name'] == $name) {
+ break;
+ }
+ }
+
+ $var = array_merge($mods, array('name' => $name, 'value' => $value));
+ $this->vars[$i] = $var;
+ }
+
+ /**
+ * Unsets "global" variable
+ *
+ * @param string $name Variable name
+ */
+ public function unset_var($name)
+ {
+ // Check if variable exists
+ foreach ($this->vars as $idx => $var) {
+ if ($var['name'] == $name) {
+ unset($this->vars[$idx]);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Gets the value of "global" variable
+ *
+ * @param string $name Variable name
+ *
+ * @return string Variable value
+ */
+ public function get_var($name)
+ {
+ // Check if variable exists
+ for ($i=0, $len=count($this->vars); $i<$len; $i++) {
+ if ($this->vars[$i]['name'] == $name) {
+ return $this->vars[$i]['name'];
+ }
+ }
+ }
+
+ /**
+ * Sets script header content
+ *
+ * @param string $text Header content
+ */
+ public function set_prefix($text)
+ {
+ $this->prefix = $text;
+ }
+
+ /**
* Returns script as text
*/
public function as_text()
{
- $script = '';
- $exts = array();
- $idx = 0;
+ $output = '';
+ $exts = array();
+ $idx = 0;
+
+ if (!empty($this->vars) && in_array('variables', (array)$this->capabilities)) {
+ array_push($exts, 'variables');
+ foreach ($this->vars as $var) {
+ $output .= 'set ';
+ foreach (array_diff(array_keys($var), array('name', 'value')) as $opt) {
+ $output .= ":$opt ";
+ }
+ $output .= self::escape_string($var['name']) . ' ' . self::escape_string($var['value']) . ";\n";
+ }
+ }
// rules
foreach ($this->content as $rule) {
$extension = '';
- $tests = array();
- $i = 0;
+ $script = '';
+ $tests = array();
+ $i = 0;
// header
- $script .= '# rule:[' . $rule['name'] . "]\n";
+ if (!empty($rule['name']) && strlen($rule['name'])) {
+ $script .= '# rule:[' . $rule['name'] . "]\n";
+ }
// constraints expressions
- foreach ($rule['tests'] as $test) {
- $tests[$i] = '';
- switch ($test['test']) {
- case 'size':
- $tests[$i] .= ($test['not'] ? 'not ' : '');
- $tests[$i] .= 'size :' . ($test['type']=='under' ? 'under ' : 'over ') . $test['arg'];
- break;
- case 'true':
- $tests[$i] .= ($test['not'] ? 'false' : 'true');
- break;
- case 'exists':
- $tests[$i] .= ($test['not'] ? 'not ' : '');
- $tests[$i] .= 'exists ' . self::escape_string($test['arg']);
- break;
- case 'header':
- $tests[$i] .= ($test['not'] ? 'not ' : '');
+ if (!empty($rule['tests'])) {
+ foreach ($rule['tests'] as $test) {
+ $tests[$i] = '';
+ switch ($test['test']) {
+ case 'size':
+ $tests[$i] .= ($test['not'] ? 'not ' : '');
+ $tests[$i] .= 'size :' . ($test['type']=='under' ? 'under ' : 'over ') . $test['arg'];
+ break;
+ case 'true':
+ $tests[$i] .= ($test['not'] ? 'false' : 'true');
+ break;
+ case 'exists':
+ $tests[$i] .= ($test['not'] ? 'not ' : '');
+ $tests[$i] .= 'exists ' . self::escape_string($test['arg']);
+ break;
+ case 'header':
+ $tests[$i] .= ($test['not'] ? 'not ' : '');
- // relational operator + comparator
- if (preg_match('/^(value|count)-([gteqnl]{2})/', $test['type'], $m)) {
- array_push($exts, 'relational');
- array_push($exts, 'comparator-i;ascii-numeric');
+ // relational operator + comparator
+ if (preg_match('/^(value|count)-([gteqnl]{2})/', $test['type'], $m)) {
+ array_push($exts, 'relational');
+ array_push($exts, 'comparator-i;ascii-numeric');
- $tests[$i] .= 'header :' . $m[1] . ' "' . $m[2] . '" :comparator "i;ascii-numeric"';
- }
- else {
- if ($test['type'] == 'regex') {
- array_push($exts, 'regex');
+ $tests[$i] .= 'header :' . $m[1] . ' "' . $m[2] . '" :comparator "i;ascii-numeric"';
}
+ else {
+ if ($test['type'] == 'regex') {
+ array_push($exts, 'regex');
+ }
- $tests[$i] .= 'header :' . $test['type'];
- }
+ $tests[$i] .= 'header :' . $test['type'];
+ }
- $tests[$i] .= ' ' . self::escape_string($test['arg1']);
- $tests[$i] .= ' ' . self::escape_string($test['arg2']);
- break;
+ $tests[$i] .= ' ' . self::escape_string($test['arg1']);
+ $tests[$i] .= ' ' . self::escape_string($test['arg2']);
+ break;
+ }
+ $i++;
}
- $i++;
}
// disabled rule: if false #....
- $script .= 'if ' . ($rule['disabled'] ? 'false # ' : '');
+ if (!empty($tests)) {
+ $script .= 'if ' . ($rule['disabled'] ? 'false # ' : '');
- if (empty($tests)) {
- $tests_str = 'true';
- }
- else if (count($tests) > 1) {
- $tests_str = implode(', ', $tests);
- }
- else {
- $tests_str = $tests[0];
- }
+ if (count($tests) > 1) {
+ $tests_str = implode(', ', $tests);
+ }
+ else {
+ $tests_str = $tests[0];
+ }
- if ($rule['join'] || count($tests) > 1) {
- $script .= sprintf('%s (%s)', $rule['join'] ? 'allof' : 'anyof', $tests_str);
- }
- else {
- $script .= $tests_str;
+ if ($rule['join'] || count($tests) > 1) {
+ $script .= sprintf('%s (%s)', $rule['join'] ? 'allof' : 'anyof', $tests_str);
+ }
+ else {
+ $script .= $tests_str;
+ }
+ $script .= "\n{\n";
}
- $script .= "\n{\n";
// action(s)
- foreach ($rule['actions'] as $action) {
- switch ($action['type']) {
+ if (!empty($rule['actions'])) {
+ foreach ($rule['actions'] as $action) {
+ $action_script = '';
- case 'fileinto':
- array_push($exts, 'fileinto');
- $script .= "\tfileinto ";
- if ($action['copy']) {
- $script .= ':copy ';
- array_push($exts, 'copy');
- }
- $script .= self::escape_string($action['target']) . ";\n";
- break;
+ switch ($action['type']) {
- case 'redirect':
- $script .= "\tredirect ";
- if ($action['copy']) {
- $script .= ':copy ';
- array_push($exts, 'copy');
- }
- $script .= self::escape_string($action['target']) . ";\n";
- break;
+ case 'fileinto':
+ array_push($exts, 'fileinto');
+ $action_script .= 'fileinto ';
+ if ($action['copy']) {
+ $action_script .= ':copy ';
+ array_push($exts, 'copy');
+ }
+ $action_script .= self::escape_string($action['target']);
+ break;
- case 'reject':
- case 'ereject':
- array_push($exts, $action['type']);
- $script .= "\t".$action['type']." "
- . self::escape_string($action['target']) . ";\n";
- break;
+ case 'redirect':
+ $action_script .= 'redirect ';
+ if ($action['copy']) {
+ $action_script .= ':copy ';
+ array_push($exts, 'copy');
+ }
+ $action_script .= self::escape_string($action['target']);
+ break;
- case 'addflag':
- case 'setflag':
- case 'removeflag':
- if (is_array($this->capabilities) && in_array('imap4flags', $this->capabilities))
- array_push($exts, 'imap4flags');
- else
- array_push($exts, 'imapflags');
+ case 'reject':
+ case 'ereject':
+ array_push($exts, $action['type']);
+ $action_script .= $action['type'].' '
+ . self::escape_string($action['target']);
+ break;
- $script .= "\t".$action['type']." "
- . self::escape_string($action['target']) . ";\n";
- break;
+ case 'addflag':
+ case 'setflag':
+ case 'removeflag':
+ if (is_array($this->capabilities) && in_array('imap4flags', $this->capabilities))
+ array_push($exts, 'imap4flags');
+ else
+ array_push($exts, 'imapflags');
- case 'keep':
- case 'discard':
- case 'stop':
- $script .= "\t" . $action['type'] .";\n";
- break;
+ $action_script .= $action['type'].' '
+ . self::escape_string($action['target']);
+ break;
- case 'vacation':
- array_push($exts, 'vacation');
- $script .= "\tvacation";
- if (!empty($action['days']))
- $script .= " :days " . $action['days'];
- if (!empty($action['addresses']))
- $script .= " :addresses " . self::escape_string($action['addresses']);
- if (!empty($action['subject']))
- $script .= " :subject " . self::escape_string($action['subject']);
- if (!empty($action['handle']))
- $script .= " :handle " . self::escape_string($action['handle']);
- if (!empty($action['from']))
- $script .= " :from " . self::escape_string($action['from']);
- if (!empty($action['mime']))
- $script .= " :mime";
- $script .= " " . self::escape_string($action['reason']) . ";\n";
- break;
+ case 'keep':
+ case 'discard':
+ case 'stop':
+ $action_script .= $action['type'];
+ break;
+
+ case 'include':
+ array_push($exts, 'include');
+ $action_script .= 'include ';
+ foreach (array_diff(array_keys($action), array('target', 'type')) as $opt) {
+ $action_script .= ":$opt ";
+ }
+ $action_script .= self::escape_string($action['target']);
+ break;
+
+ case 'set':
+ array_push($exts, 'variables');
+ $action_script .= 'set ';
+ foreach (array_diff(array_keys($action), array('name', 'value', 'type')) as $opt) {
+ $action_script .= ":$opt ";
+ }
+ $action_script .= self::escape_string($action['name']) . ' ' . self::escape_string($action['value']);
+ break;
+
+ case 'vacation':
+ array_push($exts, 'vacation');
+ $action_script .= 'vacation';
+ if (!empty($action['days']))
+ $action_script .= " :days " . $action['days'];
+ if (!empty($action['addresses']))
+ $action_script .= " :addresses " . self::escape_string($action['addresses']);
+ if (!empty($action['subject']))
+ $action_script .= " :subject " . self::escape_string($action['subject']);
+ if (!empty($action['handle']))
+ $action_script .= " :handle " . self::escape_string($action['handle']);
+ if (!empty($action['from']))
+ $action_script .= " :from " . self::escape_string($action['from']);
+ if (!empty($action['mime']))
+ $action_script .= " :mime";
+ $action_script .= " " . self::escape_string($action['reason']);
+ break;
+ }
+
+ if ($action_script) {
+ $script .= !empty($tests) ? "\t" : '';
+ $script .= $action_script . ";\n";
+ }
}
}
- $script .= "}\n";
- $idx++;
+ if ($script) {
+ $output .= $script . (!empty($tests) ? "}\n" : '');
+ $idx++;
+ }
}
// requires
if (!empty($exts))
- $script = 'require ["' . implode('","', array_unique($exts)) . "\"];\n" . $script;
+ $output = 'require ["' . implode('","', array_unique($exts)) . "\"];\n" . $output;
+
+ if (!empty($this->prefix)) {
+ $output = $this->prefix . "\n\n" . $output;
+ }
- return $script;
+ return $output;
}
/**
@@ -296,35 +403,85 @@ class rcube_sieve_script
*/
private function _parse_text($script)
{
- $i = 0;
- $content = array();
+ $prefix = '';
+ $options = array();
+
+ while ($script) {
+ $script = trim($script);
+ $rule = array();
+
+ // Comments
+ while ($script[0] == '#') {
+ $endl = strpos($script, "\n");
+ $line = $endl ? substr($script, 0, $endl) : $script;
- // tokenize rules
- if ($tokens = preg_split('/(# rule:\[.*\])\r?\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE)) {
- foreach($tokens as $token) {
- if (preg_match('/^# rule:\[(.*)\]/', $token, $matches)) {
- $content[$i]['name'] = $matches[1];
+ // Roundcube format
+ if (preg_match('/^# rule:\[(.*)\]/', $line, $matches)) {
+ $rulename = $matches[1];
}
- else if (isset($content[$i]['name']) && sizeof($content[$i]) == 1) {
- if ($rule = $this->_tokenize_rule($token)) {
- $content[$i] = array_merge($content[$i], $rule);
- $i++;
+ // Horde-Ingo format
+ else if (!empty($options['format']) && $options['format'] == 'INGO'
+ && preg_match('/^# (.*)/', $line, $matches)
+ ) {
+ $rulename = $matches[1];
+ }
+ else if (empty($options['prefix'])) {
+ $prefix .= $line . "\n";
+ }
+
+ $script = ltrim(substr($script, strlen($line) + 1));
+ }
+
+ // handle script header
+ if (empty($options['prefix'])) {
+ $options['prefix'] = true;
+ if ($prefix && strpos($prefix, 'Generated by Ingo')) {
+ $options['format'] = 'INGO';
+ }
+ }
+
+ // Control structures/blocks
+ if (preg_match('/^(if|else|elsif)/i', $script)) {
+ $rule = $this->_tokenize_rule($script);
+ if (strlen($rulename) && !empty($rule)) {
+ $rule['name'] = $rulename;
+ }
+ }
+ // Simple commands
+ else {
+ $rule = $this->_parse_actions($script, ';');
+ if (!empty($rule[0]) && is_array($rule)) {
+ // set "global" variables
+ if ($rule[0]['type'] == 'set') {
+ unset($rule[0]['type']);
+ $this->vars[] = $rule[0];
+ }
+ else {
+ $rule = array('actions' => $rule);
}
- else // unknown rule format
- unset($content[$i]);
}
}
+
+ $rulename = '';
+
+ if (!empty($rule)) {
+ $this->content[] = $rule;
+ }
}
- return $content;
+ if (!empty($prefix)) {
+ $this->prefix = trim($prefix);
+ }
}
/**
* Convert text script fragment to rule object
*
* @param string Text rule
+ *
+ * @return array Rule data
*/
- private function _tokenize_rule($content)
+ private function _tokenize_rule(&$content)
{
$cond = strtolower(self::tokenize($content, 1));
@@ -447,10 +604,12 @@ class rcube_sieve_script
/**
* Parse body of actions section
*
- * @param string Text body
+ * @param string $content Text body
+ * @param string $end End of text separator
+ *
* @return array Array of parsed action type/target pairs
*/
- private function _parse_actions($content)
+ private function _parse_actions(&$content, $end = '}')
{
$result = null;
@@ -531,7 +690,44 @@ class rcube_sieve_script
'target' => $tokens[count($tokens)-1]
);
break;
+
+ case 'include':
+ $include = array('type' => 'include', 'target' => array_pop($tokens));
+
+ // Parameters: :once, :optional, :global, :personal
+ for ($i=0, $len=count($tokens); $i<$len; $i++) {
+ $tok = strtolower($tokens[$i]);
+ if ($tok[0] == ':') {
+ $include[substr($tok, 1)] = true;
+ }
+ }
+
+ $result[] = $include;
+ break;
+
+ case 'set':
+ $set = array('type' => 'set', 'value' => array_pop($tokens), 'name' => array_pop($tokens));
+
+ // Parameters: :lower :upper :lowerfirst :upperfirst :quotewildcard :length
+ for ($i=0, $len=count($tokens); $i<$len; $i++) {
+ $tok = strtolower($tokens[$i]);
+ if ($tok[0] == ':') {
+ $set[substr($tok, 1)] = true;
+ }
+ }
+
+ $result[] = $set;
+ break;
+
+ case 'require':
+ // skip, will be build according to used commands
+ // $result[] = array('type' => 'require', 'target' => $tokens);
+ break;
+
}
+
+ if ($separator == $end)
+ break;
}
return $result;
@@ -595,7 +791,7 @@ class rcube_sieve_script
* @param mixed $num Number of tokens to return, 0 for all
* or True for all tokens until separator is found.
* Separator will be returned as last token.
- * @param int $in_list Enable to called recursively inside a list
+ * @param int $in_list Enable to call recursively inside a list
*
* @return mixed Tokens array or string if $num=1
*/
@@ -654,7 +850,7 @@ class rcube_sieve_script
$str = substr($str, 1);
if ($num === true) {
$result[] = $sep;
- break 2;
+ break 2;
}
break;
diff --git a/plugins/managesieve/managesieve.js b/plugins/managesieve/managesieve.js
index 9efbfe6b4..647f732f5 100644
--- a/plugins/managesieve/managesieve.js
+++ b/plugins/managesieve/managesieve.js
@@ -66,7 +66,7 @@ if (window.rcmail) {
rcmail.enable_command('plugin.managesieve-setdel', rcmail.gui_objects.filtersetslist.length > 1);
$('#'+rcmail.buttons['plugin.managesieve-setact'][0].id).attr('title', rcmail.gettext('managesieve.filterset'
- + (rcmail.gui_objects.filtersetslist.value == rcmail.env.active_set ? 'deact' : 'act')));
+ + ($.inArray(rcmail.gui_objects.filtersetslist.value, rcmail.env.active_sets) != -1 ? 'deact' : 'act')));
}
}
if (rcmail.gui_objects.sieveform && rcmail.env.rule_disabled)
@@ -265,7 +265,8 @@ rcube_webmail.prototype.load_managesieveframe = function(id)
if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) {
target = window.frames[this.env.contentframe];
var msgid = this.set_busy(true, 'loading');
- target.location.href = this.env.comm_path+'&_action=plugin.managesieve&_framed=1&_fid='+id+'&_unlock='+msgid;
+ target.location.href = this.env.comm_path+'&_action=plugin.managesieve&_framed=1'
+ +(id ? '&_fid='+id : '')+'&_unlock='+msgid;
}
};
@@ -429,7 +430,7 @@ rcube_webmail.prototype.managesieve_setact = function()
return false;
var script = this.gui_objects.filtersetslist.value,
- action = (script == rcmail.env.active_set ? 'deact' : 'setact');
+ action = ($.inArray(script, rcmail.env.active_sets) != -1 ? 'deact' : 'setact');
this.http_post('plugin.managesieve', '_act='+action+'&_set='+script);
};
@@ -446,15 +447,17 @@ rcube_webmail.prototype.managesieve_reset = function()
regx = new RegExp(RegExp.escape(label)+'$');
for (var x=0; x<opts.length; x++) {
- if (opts[x].value != rcmail.env.active_set && opts[x].innerHTML.match(regx))
- opts[x].innerHTML = opts[x].innerHTML.replace(regx, '');
- else if (opts[x].value == rcmail.env.active_set)
+ if ($.inArray(opts[x].value, rcmail.env.active_sets)<0) {
+ if (opts[x].innerHTML.match(regx))
+ opts[x].innerHTML = opts[x].innerHTML.replace(regx, '');
+ }
+ else if (!opts[x].innerHTML.match(regx))
opts[x].innerHTML = opts[x].innerHTML + label;
}
// change title of setact button
$('#'+rcmail.buttons['plugin.managesieve-setact'][0].id).attr('title', rcmail.gettext('managesieve.filterset'
- + (list.value == rcmail.env.active_set ? 'deact' : 'act')));
+ + ($.inArray(list.value, rcmail.env.active_sets) != -1 ? 'deact' : 'act')));
};
// Set delete
diff --git a/plugins/managesieve/managesieve.php b/plugins/managesieve/managesieve.php
index 3938f8857..9d2be50c6 100644
--- a/plugins/managesieve/managesieve.php
+++ b/plugins/managesieve/managesieve.php
@@ -7,7 +7,7 @@
* It's clickable interface which operates on text scripts and communicates
* with server using managesieve protocol. Adds Filters tab in Settings.
*
- * @version 4.3
+ * @version 5.0
* @author Aleksander Machniak <alec@alec.pl>
*
* Configuration (see config.inc.php.dist)
@@ -42,12 +42,17 @@ class managesieve extends rcube_plugin
private $tips = array();
private $script = array();
private $exts = array();
+ private $list;
+ private $active = array();
private $headers = array(
'subject' => 'Subject',
'sender' => 'From',
'recipient' => 'To',
);
+ const VERSION = '5.0';
+ const PROGNAME = 'Roundcube (Managesieve)';
+
function init()
{
@@ -61,7 +66,9 @@ class managesieve extends rcube_plugin
// load localization
$this->add_texts('localization/', array('filters','managefilters'));
- $this->include_script('managesieve.js');
+ if (!strpos($this->rc->action, 'managesieve')) {
+ $this->include_script('managesieve.js');
+ }
}
else if ($this->rc->task == 'mail') {
// register message hook
@@ -198,21 +205,19 @@ class managesieve extends rcube_plugin
);
if (!($error = $this->sieve->error())) {
+ // Get list of scripts
+ $list = $this->list_scripts();
- $list = $this->sieve->get_scripts();
- $active = $this->sieve->get_active();
- $_SESSION['managesieve_active'] = $active;
-
- if (!empty($_GET['_set'])) {
- $script_name = get_input_value('_set', RCUBE_INPUT_GET);
+ if (!empty($_GET['_set']) || !empty($_POST['_set'])) {
+ $script_name = get_input_value('_set', RCUBE_INPUT_GPC);
}
else if (!empty($_SESSION['managesieve_current'])) {
$script_name = $_SESSION['managesieve_current'];
}
else {
- // get active script
- if ($active) {
- $script_name = $active;
+ // get (first) active script
+ if (!empty($this->active[0])) {
+ $script_name = $this->active[0];
}
else if ($list) {
$script_name = $list[0];
@@ -230,14 +235,15 @@ class managesieve extends rcube_plugin
$content = file_get_contents($script_file);
// add script and set it active
- if ($this->sieve->save_script($script_name, $content))
- if ($this->sieve->activate($script_name))
- $_SESSION['managesieve_active'] = $script_name;
+ if ($this->sieve->save_script($script_name, $content)) {
+ $this->activate_script($script_name);
+ }
}
}
- if ($script_name)
+ if ($script_name) {
$this->sieve->load($script_name);
+ }
$error = $this->sieve->error();
}
@@ -263,9 +269,10 @@ class managesieve extends rcube_plugin
$this->script = array();
}
else {
- $this->script = $this->sieve->script->as_array();
$this->exts = $this->sieve->get_extensions();
- $this->rc->output->set_env('active_set', $_SESSION['managesieve_active']);
+ $this->script = $this->sieve->script->as_array();
+ if (empty($_GET['act']))
+ $this->rc->output->set_env('active_sets', $this->active);
$_SESSION['managesieve_current'] = $this->sieve->current;
}
@@ -282,7 +289,6 @@ class managesieve extends rcube_plugin
$this->include_script('managesieve.js');
}
- // Init plugin and handle managesieve connection
$error = $this->managesieve_start();
// Handle user requests
@@ -293,7 +299,7 @@ class managesieve extends rcube_plugin
if ($fid && isset($this->script[$fid]) && isset($this->script[$fid-1])) {
if ($this->sieve->script->update_rule($fid, $this->script[$fid-1]) !== false
&& $this->sieve->script->update_rule($fid-1, $this->script[$fid]) !== false) {
- $result = $this->sieve->save();
+ $result = $this->save_script();
}
if ($result) {
@@ -307,7 +313,7 @@ class managesieve extends rcube_plugin
if (isset($this->script[$fid]) && isset($this->script[$fid+1])) {
if ($this->sieve->script->update_rule($fid, $this->script[$fid+1]) !== false
&& $this->sieve->script->update_rule($fid+1, $this->script[$fid]) !== false) {
- $result = $this->sieve->save();
+ $result = $this->save_script();
}
if ($result === true) {
@@ -321,7 +327,7 @@ class managesieve extends rcube_plugin
else if ($action == 'delete' && !$error) {
if (isset($this->script[$fid])) {
if ($this->sieve->script->delete_rule($fid))
- $result = $this->sieve->save();
+ $result = $this->save_script();
if ($result === true) {
$this->rc->output->show_message('managesieve.filterdeleted', 'confirmation');
@@ -333,32 +339,31 @@ class managesieve extends rcube_plugin
}
else if ($action == 'setact' && !$error) {
$script_name = get_input_value('_set', RCUBE_INPUT_GPC);
- $result = $this->sieve->activate($script_name);
+ $result = $this->activate_script($script_name);
if ($result === true) {
- $this->rc->output->set_env('active_set', $script_name);
+ $this->rc->output->set_env('active_sets', $this->active);
$this->rc->output->show_message('managesieve.setactivated', 'confirmation');
$this->rc->output->command('managesieve_reset');
- $_SESSION['managesieve_active'] = $script_name;
} else {
$this->rc->output->show_message('managesieve.setactivateerror', 'error');
}
}
else if ($action == 'deact' && !$error) {
- $result = $this->sieve->deactivate();
+ $script_name = get_input_value('_set', RCUBE_INPUT_GPC);
+ $result = $this->deactivate_script($script_name);
if ($result === true) {
- $this->rc->output->set_env('active_set', '');
+ $this->rc->output->set_env('active_sets', $this->active);
$this->rc->output->show_message('managesieve.setdeactivated', 'confirmation');
$this->rc->output->command('managesieve_reset');
- $_SESSION['managesieve_active'] = '';
} else {
$this->rc->output->show_message('managesieve.setdeactivateerror', 'error');
}
}
else if ($action == 'setdel' && !$error) {
$script_name = get_input_value('_set', RCUBE_INPUT_GPC);
- $result = $this->sieve->remove($script_name);
+ $result = $this->remove_script($script_name);
if ($result === true) {
$this->rc->output->show_message('managesieve.setdeleted', 'confirmation');
@@ -457,6 +462,7 @@ class managesieve extends rcube_plugin
// filters set add action
if (!empty($_POST['_newset'])) {
+
$name = get_input_value('_name', RCUBE_INPUT_POST);
$copy = get_input_value('_copy', RCUBE_INPUT_POST);
$from = get_input_value('_from', RCUBE_INPUT_POST);
@@ -473,7 +479,7 @@ class managesieve extends rcube_plugin
// for security don't save script directly
// check syntax before, like this...
$this->sieve->load_script($file);
- if (!$this->sieve->save($name)) {
+ if (!$this->save_script($name)) {
$error = 'managesieve.setcreateerror';
}
}
@@ -740,7 +746,7 @@ class managesieve extends rcube_plugin
$fid = $this->sieve->script->update_rule($fid, $this->form);
if ($fid !== false)
- $save = $this->sieve->save();
+ $save = $this->save_script();
if ($save && $fid !== false) {
$this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
@@ -792,12 +798,19 @@ class managesieve extends rcube_plugin
// define list of cols to be displayed
$a_show_cols = array('managesieve.filtername');
- foreach($this->script as $idx => $filter)
+ $i = 1;
+ foreach ($this->script as $idx => $filter) {
+ if ($filter['type'] != 'if') {
+ continue;
+ }
+ $fname = $filter['name'] ? $filter['name'] : "#$i";
$result[] = array(
- 'managesieve.filtername' => $filter['name'],
+ 'managesieve.filtername' => $fname,
'id' => $idx,
'class' => $filter['disabled'] ? 'disabled' : '',
);
+ $i++;
+ }
// create XHTML table
$out = rcube_table_output($attrib, $result, $a_show_cols, 'id');
@@ -813,35 +826,36 @@ class managesieve extends rcube_plugin
}
// return the filters list as <SELECT>
- function filtersets_list($attrib)
+ function filtersets_list($attrib, $no_env = false)
{
// add id to message list table if not specified
if (!strlen($attrib['id']))
$attrib['id'] = 'rcmfiltersetslist';
- $list = $this->sieve->get_scripts();
- $active = $this->sieve->get_active();
+ $list = $this->list_scripts();
$select = new html_select(array('name' => '_set', 'id' => $attrib['id'],
- 'onchange' => 'rcmail.managesieve_set()'));
+ 'onchange' => $this->rc->task != 'mail' ? 'rcmail.managesieve_set()' : ''));
if ($list) {
asort($list, SORT_LOCALE_STRING);
foreach ($list as $set)
- $select->add($set . ($set == $active ? ' ('.$this->gettext('active').')' : ''), $set);
+ $select->add($set . (in_array($set, $this->active) ? ' ('.$this->gettext('active').')' : ''), $set);
}
$out = $select->show($this->sieve->current);
// set client env
- $this->rc->output->add_gui_object('filtersetslist', $attrib['id']);
- $this->rc->output->add_label(
- 'managesieve.setdeleteconfirm',
- 'managesieve.active',
- 'managesieve.filtersetact',
- 'managesieve.filtersetdeact'
- );
+ if (!$no_env) {
+ $this->rc->output->add_gui_object('filtersetslist', $attrib['id']);
+ $this->rc->output->add_label(
+ 'managesieve.setdeleteconfirm',
+ 'managesieve.active',
+ 'managesieve.filtersetact',
+ 'managesieve.filtersetdeact'
+ );
+ }
return $out;
}
@@ -891,16 +905,14 @@ class managesieve extends rcube_plugin
$out .= sprintf('<label for="%s">%s</label> ', 'from_none', Q($this->gettext('none')));
// filters set list
- $list = $this->sieve->get_scripts();
- $active = $this->sieve->get_active();
-
+ $list = $this->list_scripts();
$select = new html_select(array('name' => '_copy', 'id' => '_copy'));
if (is_array($list)) {
asort($list, SORT_LOCALE_STRING);
foreach ($list as $set)
- $select->add($set . ($set == $active ? ' ('.$this->gettext('active').')' : ''), $set);
+ $select->add($set . (in_array($set, $this->active) ? ' ('.$this->gettext('active').')' : ''), $set);
$out .= '<br /><input type="radio" id="from_set" name="_from" value="set"'
.($selected=='set' ? ' checked="checked"' : '').'></input>';
@@ -957,10 +969,17 @@ class managesieve extends rcube_plugin
else
$input_name = $input_name->show();
- $out .= sprintf("\n<label for=\"%s\"><b>%s:</b></label> %s<br /><br />\n",
+ $out .= sprintf("\n<label for=\"%s\"><b>%s:</b></label> %s\n",
$field_id, Q($this->gettext('filtername')), $input_name);
- $out .= '<fieldset><legend>' . Q($this->gettext('messagesrules')) . "</legend>\n";
+ // filter set selector
+ if ($this->rc->task == 'mail') {
+ $out .= sprintf("\n&nbsp;<label for=\"%s\"><b>%s:</b></label> %s\n",
+ $field_id, Q($this->gettext('filterset')),
+ $this->filtersets_list(array('id' => 'sievescriptname'), true));
+ }
+
+ $out .= '<br /><br /><fieldset><legend>' . Q($this->gettext('messagesrules')) . "</legend>\n";
// any, allof, anyof radio buttons
$field_id = '_allof';
@@ -1089,24 +1108,24 @@ class managesieve extends rcube_plugin
$select_op->add(Q($this->gettext('filternotexists')), 'notexists');
$select_op->add(Q($this->gettext('filtermatches')), 'matches');
$select_op->add(Q($this->gettext('filternotmatches')), 'notmatches');
- if (in_array('regex', $this->exts)) {
+ if (in_array('regex', $this->exts)) {
$select_op->add(Q($this->gettext('filterregex')), 'regex');
$select_op->add(Q($this->gettext('filternotregex')), 'notregex');
}
- if (in_array('relational', $this->exts)) {
- $select_op->add(Q($this->gettext('countisgreaterthan')), 'count-gt');
- $select_op->add(Q($this->gettext('countisgreaterthanequal')), 'count-ge');
- $select_op->add(Q($this->gettext('countislessthan')), 'count-lt');
- $select_op->add(Q($this->gettext('countislessthanequal')), 'count-le');
- $select_op->add(Q($this->gettext('countequals')), 'count-eq');
- $select_op->add(Q($this->gettext('countnotequals')), 'count-ne');
- $select_op->add(Q($this->gettext('valueisgreaterthan')), 'value-gt');
- $select_op->add(Q($this->gettext('valueisgreaterthanequal')), 'value-ge');
- $select_op->add(Q($this->gettext('valueislessthan')), 'value-lt');
- $select_op->add(Q($this->gettext('valueislessthanequal')), 'value-le');
- $select_op->add(Q($this->gettext('valueequals')), 'value-eq');
- $select_op->add(Q($this->gettext('valuenotequals')), 'value-ne');
- }
+ if (in_array('relational', $this->exts)) {
+ $select_op->add(Q($this->gettext('countisgreaterthan')), 'count-gt');
+ $select_op->add(Q($this->gettext('countisgreaterthanequal')), 'count-ge');
+ $select_op->add(Q($this->gettext('countislessthan')), 'count-lt');
+ $select_op->add(Q($this->gettext('countislessthanequal')), 'count-le');
+ $select_op->add(Q($this->gettext('countequals')), 'count-eq');
+ $select_op->add(Q($this->gettext('countnotequals')), 'count-ne');
+ $select_op->add(Q($this->gettext('valueisgreaterthan')), 'value-gt');
+ $select_op->add(Q($this->gettext('valueisgreaterthanequal')), 'value-ge');
+ $select_op->add(Q($this->gettext('valueislessthan')), 'value-lt');
+ $select_op->add(Q($this->gettext('valueislessthanequal')), 'value-le');
+ $select_op->add(Q($this->gettext('valueequals')), 'value-eq');
+ $select_op->add(Q($this->gettext('valuenotequals')), 'value-ne');
+ }
// target input (TODO: lists)
@@ -1265,12 +1284,12 @@ class managesieve extends rcube_plugin
$this->rc->imap_connect();
$select = rcmail_mailbox_select(array(
- 'realnames' => false,
- 'maxlength' => 100,
- 'id' => 'action_mailbox' . $id,
- 'name' => "_action_mailbox[$id]",
- 'style' => 'display:'.(!isset($action) || $action['type']=='fileinto' ? 'inline' : 'none')
- ));
+ 'realnames' => false,
+ 'maxlength' => 100,
+ 'id' => 'action_mailbox' . $id,
+ 'name' => "_action_mailbox[$id]",
+ 'style' => 'display:'.(!isset($action) || $action['type']=='fileinto' ? 'inline' : 'none')
+ ));
$out .= $select->show($mailbox);
$out .= '</td>';
@@ -1362,4 +1381,205 @@ class managesieve extends rcube_plugin
return $mailbox;
}
+
+ /**
+ * List sieve scripts
+ *
+ * @return array Scripts list
+ */
+ public function list_scripts()
+ {
+ if ($this->list !== null) {
+ return $this->list;
+ }
+
+ $this->list = $this->sieve->get_scripts();
+
+ // Handle active script(s) and list of scripts according to Kolab's KEP:14
+ if ($this->rc->config->get('managesieve_kolab_master')) {
+
+ // Skip protected names
+ foreach ((array)$this->list as $idx => $name) {
+ $_name = strtoupper($name);
+ if ($_name == 'MASTER')
+ $master_script = $name;
+ else if ($_name == 'MANAGEMENT')
+ $management_script = $name;
+ else if($_name == 'USER')
+ $user_script = $name;
+ else
+ continue;
+
+ unset($this->list[$idx]);
+ }
+
+ // get active script(s), read USER script
+ if ($user_script) {
+ $extension = $this->rc->config->get('managesieve_filename_extension', '.sieve');
+ $filename_regex = '/'.preg_quote($extension, '/').'$/';
+ $_SESSION['managesieve_user_script'] = $user_script;
+
+ $this->sieve->load($user_script);
+
+ foreach ($this->sieve->script->as_array() as $rules) {
+ foreach ($rules['actions'] as $action) {
+ if ($action['type'] == 'include' && empty($action['global'])) {
+ $name = preg_replace($filename_regex, '', $action['target']);
+ $this->active[] = $name;
+ }
+ }
+ }
+ }
+ // create USER script if it doesn't exist
+ else {
+ $content = "# USER Management Script\n"
+ ."#\n"
+ ."# This script includes the various active sieve scripts\n"
+ ."# it is AUTOMATICALLY GENERATED. DO NOT EDIT MANUALLY!\n"
+ ."#\n"
+ ."# For more information, see http://wiki.kolab.org/KEP:14#USER\n"
+ ."#\n";
+ if ($this->sieve->save_script('USER', $content)) {
+ $_SESSION['managesieve_user_script'] = 'USER';
+ if (empty($this->master_file))
+ $this->sieve->activate('USER');
+ }
+ }
+ }
+ else if (!empty($this->list)) {
+ // Get active script name
+ if ($active = $this->sieve->get_active()) {
+ $this->active = array($active);
+ }
+ }
+
+ return $this->list;
+ }
+
+ /**
+ * Removes sieve script
+ *
+ * @param string $name Script name
+ *
+ * @return bool True on success, False on failure
+ */
+ public function remove_script($name)
+ {
+ $result = $this->sieve->remove($name);
+
+ // Kolab's KEP:14
+ if ($result && $this->rc->config->get('managesieve_kolab_master')) {
+ $this->deactivate_script($name);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Activates sieve script
+ *
+ * @param string $name Script name
+ *
+ * @return bool True on success, False on failure
+ */
+ public function activate_script($name)
+ {
+ // Kolab's KEP:14
+ if ($this->rc->config->get('managesieve_kolab_master')) {
+ $extension = $this->rc->config->get('managesieve_filename_extension', '.sieve');
+ $user_script = $_SESSION['managesieve_user_script'];
+
+ // if the script is not active...
+ if ($user_script && ($key = array_search($name, $this->active)) === false) {
+ // ...rewrite USER file adding appropriate include command
+ if ($this->sieve->load($user_script)) {
+ // @TODO: include order
+ $this->sieve->script->add_rule(array(
+ 'actions' => array(
+ 0 => array(
+ 'target' => $name.$extension,
+ 'type' => 'include',
+ 'personal' => true,
+ ))));
+
+ $result = $this->sieve->save();
+ if ($result) {
+ $this->active[] = $name;
+ }
+ }
+ }
+ }
+ else {
+ $result = $this->sieve->activate($name);
+ if ($result)
+ $this->active = array($name);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Deactivates sieve script
+ *
+ * @param string $name Script name
+ *
+ * @return bool True on success, False on failure
+ */
+ public function deactivate_script($name)
+ {
+ // Kolab's KEP:14
+ if ($this->rc->config->get('managesieve_kolab_master')) {
+ $extension = $this->rc->config->get('managesieve_filename_extension', '.sieve');
+ $user_script = $_SESSION['managesieve_user_script'];
+
+ // if the script is active...
+ if ($user_script && ($key = array_search($name, $this->active)) !== false) {
+ // ...rewrite USER file removing appropriate include command
+ if ($this->sieve->load($user_script)) {
+ $script = $this->sieve->script->as_array();
+ $name = $name.$extension;
+
+ foreach ($script as $rid => $rules) {
+ foreach ($rules['actions'] as $aid => $action) {
+ if ($action['type'] == 'include' && empty($action['global'])
+ && $action['target'] == $name
+ ) {
+ break 2;
+ }
+ }
+ }
+
+ // Entry found
+ if ($rid < count($script)) {
+ $this->sieve->script->delete_rule($rid);
+ $result = $this->sieve->save();
+ if ($result) {
+ unset($this->active[$key]);
+ }
+ }
+ }
+ }
+ }
+ else {
+ $result = $this->sieve->deactivate();
+ if ($result)
+ $this->active = array();
+ }
+
+ return $result;
+ }
+
+ /**
+ * Saves current script (adding some variables)
+ */
+ public function save_script($name = null)
+ {
+ // Kolab's KEP:14
+ if ($this->rc->config->get('managesieve_kolab_master')) {
+ $this->sieve->script->set_var('editor', self::PROGNAME);
+ $this->sieve->script->set_var('editor_version', self::VERSION);
+ }
+
+ return $this->sieve->save($name);
+ }
}
diff --git a/plugins/managesieve/skins/default/managesieve.css b/plugins/managesieve/skins/default/managesieve.css
index e416fd17e..88f15bd59 100644
--- a/plugins/managesieve/skins/default/managesieve.css
+++ b/plugins/managesieve/skins/default/managesieve.css
@@ -257,7 +257,7 @@ span.label
padding-top: 5px;
width: 100%;
}
-
+
#footer .footerleft
{
padding-left: 2px;