From 98c489e9f49de6a4442821614d5e69b36173eeab Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Thu, 18 Mar 2010 04:53:32 -0400
Subject: [PATCH] - Managesieve: Added import from Horde-INGO - Managesieve: Support for more than one match using if+stop instead of if+elsif structures (#1486078) - Managesieve: Support for selectively disabling rules within a single sieve script (#1485882) - Managesieve: Added vertical splitter

---
 CHANGELOG                                                    |    3 
 plugins/managesieve/skins/default/templates/managesieve.html |   14 
 plugins/managesieve/lib/rcube_sieve.php                      |  827 ++++++++++++++++++++++++-----------------------
 plugins/managesieve/localization/pl_PL.inc                   |    1 
 plugins/managesieve/skins/default/templates/filteredit.html  |   10 
 plugins/managesieve/Changelog                                |    7 
 plugins/managesieve/localization/en_US.inc                   |    1 
 plugins/managesieve/managesieve.js                           |   39 +
 plugins/managesieve/managesieve.php                          |   32 +
 plugins/managesieve/skins/default/managesieve.css            |   38 +
 10 files changed, 533 insertions(+), 439 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 101d1f4..ecfefd6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,9 @@
 CHANGELOG RoundCube Webmail
 ===========================
 
+- Managesieve: import from Horde-INGO
+- Managesieve: support for more than one match (#1486078)
+- Managesieve: support for selectively disabling rules within a single sieve script (#1485882)
 - Threaded message listing now available
 - Added sorting by ARRIVAL and CC
 - Message list columns configurable by the user
diff --git a/plugins/managesieve/Changelog b/plugins/managesieve/Changelog
index 2a6ef09..c84a495 100644
--- a/plugins/managesieve/Changelog
+++ b/plugins/managesieve/Changelog
@@ -1,3 +1,10 @@
+* version 2.3 [2010-03-18]
+-----------------------------------------------------------
+- Added import from Horde-INGO
+- Support for more than one match using if+stop instead of if+elsif structures (#1486078)
+- Support for selectively disabling rules within a single sieve script (#1485882)
+- Added vertical splitter
+
 * version 2.2 [2010-02-06]
 -----------------------------------------------------------
 - Fix handling of "<>" characters in filter names (#1486477)
diff --git a/plugins/managesieve/lib/rcube_sieve.php b/plugins/managesieve/lib/rcube_sieve.php
index fb76452..649967f 100644
--- a/plugins/managesieve/lib/rcube_sieve.php
+++ b/plugins/managesieve/lib/rcube_sieve.php
@@ -58,6 +58,10 @@
         $this->disabled = $disabled;
     }
 
+    public function __destruct() {
+        $this->sieve->disconnect();
+    }
+
     /**
     * Getter for error code
     */
@@ -221,14 +225,24 @@
 	// try to parse from Roundcube format
         $this->script = new rcube_sieve_script($script, $this->disabled);
 
-        // ... else try Squirrelmail format
-        if (empty($this->script->content) && $name == 'phpscript') {
-
-    	    $script = $this->sieve->getScript('phpscript');
-    	    $script = $this->_convert_from_squirrel_rules($script);
-
+        // ... else try to import from different formats
+        if (empty($this->script->content)) {
+    	    $script = $this->_import_rules($script);
     	    $this->script = new rcube_sieve_script($script, $this->disabled);
     	}
+
+        // replace all elsif with if+stop, we support only ifs
+        foreach ($this->script->content as $idx => $rule) {
+            if (!isset($this->script->content[$idx+1])
+                || preg_match('/^else|elsif$/', $this->script->content[$idx+1]['type'])) {
+                // 'stop' not found?
+                if (!preg_match('/^(stop|vacation)$/', $rule['actions'][count($rule['actions'])-1]['type'])) {
+                    $this->script->content[$idx]['actions'][] = array(
+                        'type' => 'stop'
+                    );
+                }
+            }
+        }
 
     	$this->current = $name;
 
@@ -254,23 +268,38 @@
     }
 
 
-    private function _convert_from_squirrel_rules($script)
+    private function _import_rules($script)
     {
         $i = 0;
         $name = array();
 
-        // tokenize rules
-        if ($tokens = preg_split('/(#START_SIEVE_RULE.*END_SIEVE_RULE)\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE))
+        // Squirrelmail (Avelsieve)
+        if ($tokens = preg_split('/(#START_SIEVE_RULE.*END_SIEVE_RULE)\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";
+                    $content .= "# rule:[".$name[$i]."]\n";
                 }
         	elseif (isset($name[$i])) {
 	    	    $content .= "if $token\n";
 		    $i++;
                 }
             }
+        }
+        // Horde (INGO)
+        else if ($tokens = preg_split('/(# .+)\r?\n/i', $script, -1, PREG_SPLIT_DELIM_CAPTURE)) {
+            foreach($tokens as $token) {
+                if (preg_match('/^# (.+)/i', $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;
     }
@@ -293,563 +322,553 @@
 
 class rcube_sieve_script
 {
-  public $content = array();	// script rules array   
+    public $content = array();	// script rules array   
 
-  private $supported = array(	// extensions supported by class
-    'fileinto',
-    'reject',
-    'ereject',
-    'vacation', 	// RFC5230
+    private $supported = array(	// extensions supported by class
+        'fileinto',
+        'reject',
+        'ereject',
+        'vacation', 	// RFC5230
     // TODO: (most wanted first) body, imapflags, notify, regex
     );
   
-  /**
+    /**
     * Object constructor
     *
     * @param  string  Script's text content
     * @param  array   Disabled extensions
     */
-  public function __construct($script, $disabled=NULL)
+    public function __construct($script, $disabled=NULL)
     {
-      if (!empty($disabled))
-        foreach ($disabled as $ext)
-          if (($idx = array_search($ext, $this->supported)) !== false)
-	    unset($this->supported[$idx]);
+        if (!empty($disabled))
+            foreach ($disabled as $ext)
+                if (($idx = array_search($ext, $this->supported)) !== false)
+	            unset($this->supported[$idx]);
 
-      $this->content = $this->_parse_text($script);
+        $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)
+    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;
-	  }
+        $content = $this->_parse_text($script);
+        $result = false;
 
-      return $result;
+        // 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;
+	    }
+        }
+
+        return $result;
     }
 
-  /**
+    /**
     * Adds rule to the script (at the end)
     *
     * @param	string	Rule name
     * @param	array	Rule content (as array)
     */
-  public function add_rule($content)
+    public function add_rule($content)
     {
-      // TODO: check this->supported
-      array_push($this->content, $content);
-      return sizeof($this->content)-1;
+        // TODO: check this->supported
+        array_push($this->content, $content);
+        return sizeof($this->content)-1;
     }
 
-  public function delete_rule($index)
+    public function delete_rule($index)
     {
-      if(isset($this->content[$index]))
-        {
-          unset($this->content[$index]);
-	  return true;
+        if(isset($this->content[$index])) {
+            unset($this->content[$index]);
+	    return true;
 	}
-      return false;
+        return false;
     }
 
-  public function size()
+    public function size()
     {
-      return sizeof($this->content);
+        return sizeof($this->content);
     }
 
-  public function update_rule($index, $content)
+    public function update_rule($index, $content)
     {
-      // TODO: check this->supported
-      if ($this->content[$index])
-        {
-	  $this->content[$index] = $content;
-	  return $index;
+        // TODO: check this->supported
+        if ($this->content[$index]) {
+	    $this->content[$index] = $content;
+	    return $index;
 	}
-      return false;
+        return false;
     }
 
-  /**
+    /**
     * Returns script as text
     */
-  public function as_text()
+    public function as_text()
     {
-      $script = '';
-      $exts = array();
-      $idx = 0;
-      
-      // rules
-      foreach ($this->content as $rule)
-        {
-	  $extension = '';
-	  $tests = array();
-	  $i = 0;
-	  
-	  // header
-	  $script .= '# rule:[' . $rule['name'] . "]\n";
+        $script = '';
+        $exts = array();
+        $idx = 0;
+
+        // rules
+        foreach ($this->content as $rule) {
+	    $extension = '';
+	    $tests = array();
+	    $i = 0;
+
+	    // header
+	    $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'] ? 'not true' : 'true');
-		  break;
-		  case 'exists':
-		    $tests[$i] .= ($test['not'] ? 'not ' : '');
-		    if (is_array($test['arg']))
-			$tests[$i] .= 'exists ["' . implode('", "', $this->_escape_string($test['arg'])) . '"]';
-		    else
-			$tests[$i] .= 'exists "' . $this->_escape_string($test['arg']) . '"';
-		  break;    
-		  case 'header':
-		    $tests[$i] .= ($test['not'] ? 'not ' : '');
-		    $tests[$i] .= 'header :' . $test['type'];
-		    if (is_array($test['arg1']))
-			$tests[$i] .= ' ["' . implode('", "', $this->_escape_string($test['arg1'])) . '"]';
-		    else
-			$tests[$i] .= ' "' . $this->_escape_string($test['arg1']) . '"';
-		    if (is_array($test['arg2']))
-			$tests[$i] .= ' ["' . implode('", "', $this->_escape_string($test['arg2'])) . '"]';
-		    else
-			$tests[$i] .= ' "' . $this->_escape_string($test['arg2']) . '"';
-		  break;
+	    // 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'] ? 'not true' : 'true');
+		    break;
+		    case 'exists':
+		        $tests[$i] .= ($test['not'] ? 'not ' : '');
+		        if (is_array($test['arg']))
+			    $tests[$i] .= 'exists ["' . implode('", "', $this->_escape_string($test['arg'])) . '"]';
+		        else
+			    $tests[$i] .= 'exists "' . $this->_escape_string($test['arg']) . '"';
+		    break;    
+		    case 'header':
+		        $tests[$i] .= ($test['not'] ? 'not ' : '');
+		        $tests[$i] .= 'header :' . $test['type'];
+		        if (is_array($test['arg1']))
+			    $tests[$i] .= ' ["' . implode('", "', $this->_escape_string($test['arg1'])) . '"]';
+		        else
+			    $tests[$i] .= ' "' . $this->_escape_string($test['arg1']) . '"';
+		        if (is_array($test['arg2']))
+			    $tests[$i] .= ' ["' . implode('", "', $this->_escape_string($test['arg2'])) . '"]';
+		        else
+			    $tests[$i] .= ' "' . $this->_escape_string($test['arg2']) . '"';
+		    break;
 		}
-	      $i++;
-	    }
-  
-	  $script .= ($idx>0 ? 'els' : '').($rule['join'] ? 'if allof (' : 'if anyof (');
-	  if (sizeof($tests) > 1)
-	    $script .= implode(",\n\t", $tests);
-	  elseif (sizeof($tests))
-	    $script .= $tests[0];
-	  else
-	    $script .= 'true';
-	  $script .= ")\n{\n";
-  
-	  // action(s)
-	  foreach ($rule['actions'] as $action)
-          {
-	    switch ($action['type'])
-	    {
-	      case 'fileinto':
-	        $extension = 'fileinto';
-		$script .= "\tfileinto \"" . $this->_escape_string($action['target']) . "\";\n";
-	      break;
-	      case 'redirect':
-		$script .= "\tredirect \"" . $this->_escape_string($action['target']) . "\";\n";
-	      break;
-	      case 'reject':
-	      case 'ereject':
-	        $extension = $action['type'];
-		if (strpos($action['target'], "\n")!==false)
-		  $script .= "\t".$action['type']." text:\n" . $action['target'] . "\n.\n;\n";
-		else
-		  $script .= "\t".$action['type']." \"" . $this->_escape_string($action['target']) . "\";\n";
-	      break;
-	      case 'keep':
-	      case 'discard':
-	      case 'stop':
-	        $script .= "\t" . $action['type'] .";\n";
-	      break;
-	      case 'vacation':
-                $extension = 'vacation';
-                $script .= "\tvacation";
-		if ($action['days'])
-		  $script .= " :days " . $action['days'];
-		if ($action['addresses'])
-		  $script .= " :addresses " . $this->_print_list($action['addresses']);
-		if ($action['subject'])
-		  $script .= " :subject \"" . $this->_escape_string($action['subject']) . "\"";
-		if ($action['handle'])
-		  $script .= " :handle \"" . $this->_escape_string($action['handle']) . "\"";
-		if ($action['from'])
-		  $script .= " :from \"" . $this->_escape_string($action['from']) . "\"";
-		if ($action['mime'])
-		  $script .= " :mime";
-		if (strpos($action['reason'], "\n")!==false)
-		  $script .= " text:\n" . $action['reason'] . "\n.\n;\n";
-		else
-		  $script .= " \"" . $this->_escape_string($action['reason']) . "\";\n";
-	      break;
+	        $i++;
 	    }
 
-	    if ($extension && !isset($exts[$extension]))
-	      $exts[$extension] = $extension;
-	  }
+//            $script .= ($idx>0 ? 'els' : '').($rule['join'] ? 'if allof (' : 'if anyof (');
+            // disabled rule: if false #....
+            $script .= 'if' . ($rule['disabled'] ? ' false #' : '');
+	    $script .= $rule['join'] ? ' allof (' : ' anyof (';
+	    if (sizeof($tests) > 1)
+	        $script .= implode(",\n\t", $tests);
+	    else if (sizeof($tests))
+	        $script .= $tests[0];
+	    else
+	        $script .= 'true';
+	    $script .= ")\n{\n";
+  
+	    // action(s)
+	    foreach ($rule['actions'] as $action) {
+	        switch ($action['type']) {
+	            case 'fileinto':
+	                $extension = 'fileinto';
+		        $script .= "\tfileinto \"" . $this->_escape_string($action['target']) . "\";\n";
+	            break;
+	            case 'redirect':
+		        $script .= "\tredirect \"" . $this->_escape_string($action['target']) . "\";\n";
+	            break;
+	            case 'reject':
+	            case 'ereject':
+	                $extension = $action['type'];
+		        if (strpos($action['target'], "\n")!==false)
+		            $script .= "\t".$action['type']." text:\n" . $action['target'] . "\n.\n;\n";
+		        else
+		            $script .= "\t".$action['type']." \"" . $this->_escape_string($action['target']) . "\";\n";
+	            break;
+	            case 'keep':
+	            case 'discard':
+	            case 'stop':
+	                $script .= "\t" . $action['type'] .";\n";
+	            break;
+	            case 'vacation':
+                        $extension = 'vacation';
+                        $script .= "\tvacation";
+		        if ($action['days'])
+		            $script .= " :days " . $action['days'];
+		        if ($action['addresses'])
+		            $script .= " :addresses " . $this->_print_list($action['addresses']);
+		        if ($action['subject'])
+		            $script .= " :subject \"" . $this->_escape_string($action['subject']) . "\"";
+		        if ($action['handle'])
+		            $script .= " :handle \"" . $this->_escape_string($action['handle']) . "\"";
+		        if ($action['from'])
+		            $script .= " :from \"" . $this->_escape_string($action['from']) . "\"";
+		        if ($action['mime'])
+		            $script .= " :mime";
+		        if (strpos($action['reason'], "\n")!==false)
+		            $script .= " text:\n" . $action['reason'] . "\n.\n;\n";
+		        else
+		            $script .= " \"" . $this->_escape_string($action['reason']) . "\";\n";
+	            break;
+	        }
 
-	  $script .= "}\n";
-	  $idx++;
+	        if ($extension && !isset($exts[$extension]))
+	            $exts[$extension] = $extension;
+	    }
+
+	    $script .= "}\n";
+	    $idx++;
 	}
       
-      // requires
-      if (sizeof($exts))
-        $script = 'require ["' . implode('","', $exts) . "\"];\n" . $script;
+        // requires
+        if (sizeof($exts))
+            $script = 'require ["' . implode('","', $exts) . "\"];\n" . $script;
 
-      return $script;
+        return $script;
     }
 
-  /**
+    /**
     * Returns script object
     *
     */
-  public function as_array()
+    public function as_array()
     {
-      return $this->content;
+        return $this->content;
     }
 
-  /**
+    /**
     * Returns array of supported extensions
     *
     */
-  public function get_extensions()
+    public function get_extensions()
     {
-      return array_values($this->supported);
+        return array_values($this->supported);
     }
 
-  /**
+    /**
     * Converts text script to rules array
     *
     * @param	string	Text script
     */
-  private function _parse_text($script)
+    private function _parse_text($script)
     {
-      $i = 0;
-      $content = array();
+        $i = 0;
+        $content = array();
 
-      // remove C comments
-      $script = preg_replace('|/\*.*?\*/|sm', '', $script);
+        // remove C comments
+        $script = preg_replace('|/\*.*?\*/|sm', '', $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];
-	      }
-	    elseif (isset($content[$i]['name']) && sizeof($content[$i]) == 1)
-	      {
-	        if ($rule = $this->_tokenize_rule($token))
-		  {
-	    	    $content[$i] = array_merge($content[$i], $rule);
-	    	    $i++;
-		  }
-		else // unknown rule format
-		    unset($content[$i]);
-	      }
-	  }
+        // 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];
+	        }
+	        elseif (isset($content[$i]['name']) && sizeof($content[$i]) == 1) {
+	            if ($rule = $this->_tokenize_rule($token)) {
+	    	        $content[$i] = array_merge($content[$i], $rule);
+	    	        $i++;
+		    }
+		    else // unknown rule format
+		        unset($content[$i]);
+	        }
+	    }
+        }
 
-      return $content;
+        return $content;
     }
 
-  /**
+    /**
     * Convert text script fragment to rule object
     *
     * @param	string	Text rule
     */
-  private function _tokenize_rule($content)
+    private function _tokenize_rule($content)
     {
-      $result = NULL;
+        $result = NULL;
     
-      if (preg_match('/^(if|elsif|else)\s+((true|not\s+true|allof|anyof|exists|header|not|size)(.*))\s+\{(.*)\}$/sm', trim($content), $matches))
-        {
-	  list($tests, $join) = $this->_parse_tests(trim($matches[2]));
-	  $actions = $this->_parse_actions(trim($matches[5]));
+        if (preg_match('/^(if|elsif|else)\s+((true|false|not\s+true|allof|anyof|exists|header|not|size)(.*))\s+\{(.*)\}$/sm',
+            trim($content), $matches)) {
 
-	  if ($tests && $actions)
-	    $result = array(
+            $tests = trim($matches[2]);
+
+            // disabled rule (false + comment): if false #.....
+            if ($matches[3] == 'false') {
+                $tests = preg_replace('/^false\s+#\s+/', '', $tests);
+                $disabled = true;
+            }
+            else
+                $disabled = false;
+
+	    list($tests, $join) = $this->_parse_tests($tests);
+	    $actions = $this->_parse_actions(trim($matches[5]));
+
+	    if ($tests && $actions)
+	        $result = array(
+                    'type' => $matches[1],
 		    'tests' => $tests,
 		    'actions' => $actions,
 		    'join' => $join,
-	    );
+                    'disabled' => $disabled,
+	        );
 	}
 
-      return $result;
+        return $result;
     }    
 
-  /**
+    /**
     * Parse body of actions section
     *
     * @param	string	Text body
     * @return	array	Array of parsed action type/target pairs
     */
-  private function _parse_actions($content)
+    private function _parse_actions($content)
     {
-      $result = NULL;
+        $result = NULL;
 
-      // supported actions
-      $patterns[] = '^\s*discard;';
-      $patterns[] = '^\s*keep;';
-      $patterns[] = '^\s*stop;';
-      $patterns[] = '^\s*redirect\s+(.*?[^\\\]);';
-      if (in_array('fileinto', $this->supported))
-        $patterns[] = '^\s*fileinto\s+(.*?[^\\\]);';
-      if (in_array('reject', $this->supported)) {
-        $patterns[] = '^\s*reject\s+text:(.*)\n\.\n;';
-        $patterns[] = '^\s*reject\s+(.*?[^\\\]);';
-        $patterns[] = '^\s*ereject\s+text:(.*)\n\.\n;';
-        $patterns[] = '^\s*ereject\s+(.*?[^\\\]);';
-      }
-      if (in_array('vacation', $this->supported))
-        $patterns[] = '^\s*vacation\s+(.*?[^\\\]);';
+        // supported actions
+        $patterns[] = '^\s*discard;';
+        $patterns[] = '^\s*keep;';
+        $patterns[] = '^\s*stop;';
+        $patterns[] = '^\s*redirect\s+(.*?[^\\\]);';
+        if (in_array('fileinto', $this->supported))
+            $patterns[] = '^\s*fileinto\s+(.*?[^\\\]);';
+        if (in_array('reject', $this->supported)) {
+            $patterns[] = '^\s*reject\s+text:(.*)\n\.\n;';
+            $patterns[] = '^\s*reject\s+(.*?[^\\\]);';
+            $patterns[] = '^\s*ereject\s+text:(.*)\n\.\n;';
+            $patterns[] = '^\s*ereject\s+(.*?[^\\\]);';
+        }
+        if (in_array('vacation', $this->supported))
+            $patterns[] = '^\s*vacation\s+(.*?[^\\\]);';
 
-      $pattern = '/(' . implode('$)|(', $patterns) . '$)/ms';
+        $pattern = '/(' . implode('$)|(', $patterns) . '$)/ms';
 
-      // parse actions body
-      if (preg_match_all($pattern, $content, $mm, PREG_SET_ORDER))
-      {
-    	foreach ($mm as $m)
-	{
-	  $content = trim($m[0]);
+        // parse actions body
+        if (preg_match_all($pattern, $content, $mm, PREG_SET_ORDER)) {
+    	    foreach ($mm as $m) {
+	        $content = trim($m[0]);
 	  
-    	  if(preg_match('/^(discard|keep|stop)/', $content, $matches))
-    	    {
-	      $result[] = array('type' => $matches[1]);
-	    }
-          elseif(preg_match('/^fileinto/', $content))
-    	    {
-	      $result[] = array('type' => 'fileinto', 'target' => $this->_parse_string($m[sizeof($m)-1])); 
-	    }
-          elseif(preg_match('/^redirect/', $content))
-    	    {
-	      $result[] = array('type' => 'redirect', 'target' => $this->_parse_string($m[sizeof($m)-1])); 
-	    }
-    	  elseif(preg_match('/^(reject|ereject)\s+(.*);$/sm', $content, $matches))
-    	    {
-	      $result[] = array('type' => $matches[1], 'target' => $this->_parse_string($matches[2])); 
-	    }
-          elseif(preg_match('/^vacation\s+(.*);$/sm', $content, $matches))
-            {
-	      $vacation = array('type' => 'vacation');
+    	        if(preg_match('/^(discard|keep|stop)/', $content, $matches)) {
+	            $result[] = array('type' => $matches[1]);
+	        }
+                elseif(preg_match('/^fileinto/', $content)) {
+	            $result[] = array('type' => 'fileinto', 'target' => $this->_parse_string($m[sizeof($m)-1])); 
+	        }
+                elseif(preg_match('/^redirect/', $content)) {
+	            $result[] = array('type' => 'redirect', 'target' => $this->_parse_string($m[sizeof($m)-1])); 
+	        }
+    	        elseif(preg_match('/^(reject|ereject)\s+(.*);$/sm', $content, $matches)) {
+	            $result[] = array('type' => $matches[1], 'target' => $this->_parse_string($matches[2])); 
+	        }
+                elseif(preg_match('/^vacation\s+(.*);$/sm', $content, $matches)) {
+	            $vacation = array('type' => 'vacation');
 
-    	      if (preg_match('/:(days)\s+([0-9]+)/', $content, $vm)) {
-	        $vacation['days'] = $vm[2];
-		$content = preg_replace('/:(days)\s+([0-9]+)/', '', $content); 
-	      }
-    	      if (preg_match('/:(subject)\s+(".*?[^\\\]")/', $content, $vm)) {
-	        $vacation['subject'] = $vm[2];
-		$content = preg_replace('/:(subject)\s+(".*?[^\\\]")/', '', $content); 
-	      }
-    	      if (preg_match('/:(addresses)\s+\[(.*?[^\\\])\]/', $content, $vm)) {
-	        $vacation['addresses'] = $this->_parse_list($vm[2]);
-		$content = preg_replace('/:(addresses)\s+\[(.*?[^\\\])\]/', '', $content); 
-	      }
-    	      if (preg_match('/:(handle)\s+(".*?[^\\\]")/', $content, $vm)) {
-	        $vacation['handle'] = $vm[2];
-		$content = preg_replace('/:(handle)\s+(".*?[^\\\]")/', '', $content); 
-	      }
-    	      if (preg_match('/:(from)\s+(".*?[^\\\]")/', $content, $vm)) {
-	        $vacation['from'] = $vm[2];
-		$content = preg_replace('/:(from)\s+(".*?[^\\\]")/', '', $content); 
-	      }
-	      $content = preg_replace('/^vacation/', '', $content);	     
-	      $content = preg_replace('/;$/', '', $content);
-	      $content = trim($content);
-    	      if (preg_match('/^:(mime)/', $content, $vm)) {
-	        $vacation['mime'] = true;
-		$content = preg_replace('/^:mime/', '', $content); 
-	      }
+    	            if (preg_match('/:(days)\s+([0-9]+)/', $content, $vm)) {
+	                $vacation['days'] = $vm[2];
+		        $content = preg_replace('/:(days)\s+([0-9]+)/', '', $content); 
+	            }
+    	            if (preg_match('/:(subject)\s+(".*?[^\\\]")/', $content, $vm)) {
+	                $vacation['subject'] = $vm[2];
+    		        $content = preg_replace('/:(subject)\s+(".*?[^\\\]")/', '', $content); 
+    	            }
+    	            if (preg_match('/:(addresses)\s+\[(.*?[^\\\])\]/', $content, $vm)) {
+	                $vacation['addresses'] = $this->_parse_list($vm[2]);
+		        $content = preg_replace('/:(addresses)\s+\[(.*?[^\\\])\]/', '', $content); 
+	            }
+    	            if (preg_match('/:(handle)\s+(".*?[^\\\]")/', $content, $vm)) {
+	                $vacation['handle'] = $vm[2];
+		        $content = preg_replace('/:(handle)\s+(".*?[^\\\]")/', '', $content); 
+	            }
+    	            if (preg_match('/:(from)\s+(".*?[^\\\]")/', $content, $vm)) {
+	                $vacation['from'] = $vm[2];
+		        $content = preg_replace('/:(from)\s+(".*?[^\\\]")/', '', $content); 
+	            }
 
-	      $vacation['reason'] = $this->_parse_string($content);
+	            $content = preg_replace('/^vacation/', '', $content);	     
+	            $content = preg_replace('/;$/', '', $content);
+	            $content = trim($content);
 
-              $result[] = $vacation;
+    	            if (preg_match('/^:(mime)/', $content, $vm)) {
+	                $vacation['mime'] = true;
+		        $content = preg_replace('/^:mime/', '', $content); 
+	            }
+
+	            $vacation['reason'] = $this->_parse_string($content);
+
+                    $result[] = $vacation;
+                }
             }
         }
-      }
 
-      return $result;
+        return $result;
     }    
     
-   /**
+    /**
     * Parse test/conditions section
     *
     * @param	string	Text 
     */
-
-  private function _parse_tests($content)
+    private function _parse_tests($content)
     {
-      $result = NULL;
+        $result = NULL;
 
-      // lists
-      if (preg_match('/^(allof|anyof)\s+\((.*)\)$/sm', $content, $matches))
-	{
-	  $content = $matches[2];
-	  $join = $matches[1]=='allof' ? true : false;
+        // lists
+        if (preg_match('/^(allof|anyof)\s+\((.*)\)$/sm', $content, $matches)) {
+	    $content = $matches[2];
+	    $join = $matches[1]=='allof' ? true : false;
 	}
-      else
-	  $join = false;
+        else
+	    $join = false;
       
-      // supported tests regular expressions
-      // TODO: comparators, envelope
-      $patterns[] = '(not\s+)?(exists)\s+\[(.*?[^\\\])\]';
-      $patterns[] = '(not\s+)?(exists)\s+(".*?[^\\\]")';
-      $patterns[] = '(not\s+)?(true)';
-      $patterns[] = '(not\s+)?(size)\s+:(under|over)\s+([0-9]+[KGM]{0,1})';
-      $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)\s+\[(.*?[^\\\]")\]\s+\[(.*?[^\\\]")\]';
-      $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)\s+(".*?[^\\\]")\s+(".*?[^\\\]")';
-      $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)\s+\[(.*?[^\\\]")\]\s+(".*?[^\\\]")';
-      $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)\s+(".*?[^\\\]")\s+\[(.*?[^\\\]")\]';
+        // supported tests regular expressions
+        // TODO: comparators, envelope
+        $patterns[] = '(not\s+)?(exists)\s+\[(.*?[^\\\])\]';
+        $patterns[] = '(not\s+)?(exists)\s+(".*?[^\\\]")';
+        $patterns[] = '(not\s+)?(true)';
+        $patterns[] = '(not\s+)?(size)\s+:(under|over)\s+([0-9]+[KGM]{0,1})';
+        $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)\s+\[(.*?[^\\\]")\]\s+\[(.*?[^\\\]")\]';
+        $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)\s+(".*?[^\\\]")\s+(".*?[^\\\]")';
+        $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)\s+\[(.*?[^\\\]")\]\s+(".*?[^\\\]")';
+        $patterns[] = '(not\s+)?(header)\s+:(contains|is|matches)\s+(".*?[^\\\]")\s+\[(.*?[^\\\]")\]';
       
-      // join patterns...
-      $pattern = '/(' . implode(')|(', $patterns) . ')/';
+        // join patterns...
+        $pattern = '/(' . implode(')|(', $patterns) . ')/';
 
-      // ...and parse tests list
-      if (preg_match_all($pattern, $content, $matches, PREG_SET_ORDER))
-        {
-	  foreach ($matches as $match)
-	    {
-	      $size = sizeof($match);
+        // ...and parse tests list
+        if (preg_match_all($pattern, $content, $matches, PREG_SET_ORDER)) {
+	    foreach ($matches as $match) {
+	        $size = sizeof($match);
 	      
-	      if (preg_match('/^(not\s+)?size/', $match[0]))
-	        {
-		  $result[] = array(
-		    'test' 	=> 'size',
-		    'not' 	=> $match[$size-4] ? true : false,
-		    'type' 	=> $match[$size-2], // under/over
-		    'arg'	=> $match[$size-1], // value
-		  );
+	        if (preg_match('/^(not\s+)?size/', $match[0])) {
+		    $result[] = array(
+		        'test' 	=> 'size',
+		        'not' 	=> $match[$size-4] ? true : false,
+		        'type' 	=> $match[$size-2], // under/over
+		        'arg'	=> $match[$size-1], // value
+		    );
 		}
-	      elseif (preg_match('/^(not\s+)?header/', $match[0]))
-	    	{
-		  $result[] = array(
-		    'test'	=> 'header',
-		    'not' 	=> $match[$size-5] ? true : false,
-		    'type'	=> $match[$size-3], // is/contains/matches
-		    'arg1' 	=> $this->_parse_list($match[$size-2]), // header(s)
-		    'arg2'	=> $this->_parse_list($match[$size-1]), // string(s)
-		  );  
+	        elseif (preg_match('/^(not\s+)?header/', $match[0])) {
+		    $result[] = array(
+		        'test'	=> 'header',
+		        'not' 	=> $match[$size-5] ? true : false,
+		        'type'	=> $match[$size-3], // is/contains/matches
+		        'arg1' 	=> $this->_parse_list($match[$size-2]), // header(s)
+		        'arg2'	=> $this->_parse_list($match[$size-1]), // string(s)
+		    );  
 		}
-	      elseif (preg_match('/^(not\s+)?exists/', $match[0]))
-		{
-		  $result[] = array(
-		    'test' 	=> 'exists',
-		    'not' 	=> $match[$size-3] ? true : false,
-		    'arg' 	=> $this->_parse_list($match[$size-1]), // header(s)
-		  );
+	        elseif (preg_match('/^(not\s+)?exists/', $match[0])) {
+		    $result[] = array(
+		        'test' 	=> 'exists',
+		        'not' 	=> $match[$size-3] ? true : false,
+		        'arg' 	=> $this->_parse_list($match[$size-1]), // header(s)
+		    );
 	        }
-	      elseif (preg_match('/^(not\s+)?true/', $match[0]))
-		{
-		  $result[] = array(
-		    'test' 	=> 'true',
-		    'not' 	=> $match[$size-2] ? true : false,
-		  );
+	        elseif (preg_match('/^(not\s+)?true/', $match[0])) {
+		    $result[] = array(
+		        'test' 	=> 'true',
+		        'not' 	=> $match[$size-2] ? true : false,
+		    );
 	        }
 	    }
 	}
 
-      return array($result, $join);
+        return array($result, $join);
     }    
 
-   /**
+    /**
     * Parse string value
     *
     * @param	string	Text 
     */
-  private function _parse_string($content)
+    private function _parse_string($content)
     {
-      $text = '';
-      $content = trim($content);
+        $text = '';
+        $content = trim($content);
 
-      if (preg_match('/^text:(.*)\.$/sm', $content, $matches))
-        $text = trim($matches[1]);
-      elseif (preg_match('/^"(.*)"$/', $content, $matches))
-        $text = str_replace('\"', '"', $matches[1]);
+        if (preg_match('/^text:(.*)\.$/sm', $content, $matches))
+            $text = trim($matches[1]);
+        elseif (preg_match('/^"(.*)"$/', $content, $matches))
+            $text = str_replace('\"', '"', $matches[1]);
 
-      return $text;
+        return $text;
     }    
 
-   /**
+    /**
     * Escape special chars in string value
     *
     * @param	string	Text 
     */
-  private function _escape_string($content)
+    private function _escape_string($content)
     {
-      $replace['/"/'] = '\\"';
+        $replace['/"/'] = '\\"';
       
-      if (is_array($content))
-        {
-	  for ($x=0, $y=sizeof($content); $x<$y; $x++)
-	    $content[$x] = preg_replace(array_keys($replace), array_values($replace), $content[$x]);
+        if (is_array($content)) {
+	    for ($x=0, $y=sizeof($content); $x<$y; $x++)
+	        $content[$x] = preg_replace(array_keys($replace), array_values($replace), $content[$x]);
         
-	  return $content;
+	    return $content;
 	}
-      else
-        return preg_replace(array_keys($replace), array_values($replace), $content);
+        else
+            return preg_replace(array_keys($replace), array_values($replace), $content);
     }
 
-   /**
+    /**
     * Parse string or list of strings to string or array of strings
     *
     * @param	string	Text 
     */
-  private function _parse_list($content)
+    private function _parse_list($content)
     {
-      $result = array();
+        $result = array();
       
-      for ($x=0, $len=strlen($content); $x<$len; $x++)
-        {
-	  switch ($content[$x])
-	    {
-	      case '\\':
-	        $str .= $content[++$x];
-              break;
-	      case '"':
-	        if (isset($str))
-	    	  {
-		    $result[] = $str;
-		    unset($str);
-		  }
-	        else
-	          $str = '';
-	      break;
-	      default:
-	        if(isset($str))
-	          $str .= $content[$x];
-	      break;
+        for ($x=0, $len=strlen($content); $x<$len; $x++) {
+	    switch ($content[$x]) {
+	        case '\\':
+	            $str .= $content[++$x];
+                break;
+	        case '"':
+	            if (isset($str)) {
+		        $result[] = $str;
+		        unset($str);
+		    }
+	            else
+	                $str = '';
+	        break;
+	        default:
+	            if(isset($str))
+	                $str .= $content[$x];
+	        break;
 	    }
 	}
       
-      if (sizeof($result)>1)
-        return $result;
-      elseif (sizeof($result) == 1)
-	return $result[0];
-      else
-        return NULL;
+        if (sizeof($result)>1)
+            return $result;
+        elseif (sizeof($result) == 1)
+	    return $result[0];
+        else
+            return NULL;
     }    
 
-   /**
+    /**
     * Convert array of elements to list of strings
     *
     * @param	string	Text 
     */
-  private function _print_list($list)
+    private function _print_list($list)
     {
-      $list = (array) $list;
-      foreach($list as $idx => $val)
-        $list[$idx] = $this->_escape_string($val);
+        $list = (array) $list;
+        foreach($list as $idx => $val)
+            $list[$idx] = $this->_escape_string($val);
     
-      return '["' . implode('","', $list) . '"]';
+        return '["' . implode('","', $list) . '"]';
     }
 }
 
diff --git a/plugins/managesieve/localization/en_US.inc b/plugins/managesieve/localization/en_US.inc
index a5bb878..ac410d3 100644
--- a/plugins/managesieve/localization/en_US.inc
+++ b/plugins/managesieve/localization/en_US.inc
@@ -46,6 +46,7 @@
 $labels['active'] = 'active';
 $labels['copyfromset'] = 'Copy filters from set';
 $labels['none'] = '- none -';
+$labels['filterdisabled'] = 'Filter disabled';
 
 $messages = array();
 $messages['filterunknownerror'] = 'Unknown server error';
diff --git a/plugins/managesieve/localization/pl_PL.inc b/plugins/managesieve/localization/pl_PL.inc
index 663b37f..6d3ca31 100644
--- a/plugins/managesieve/localization/pl_PL.inc
+++ b/plugins/managesieve/localization/pl_PL.inc
@@ -47,6 +47,7 @@
 $labels['active'] = 'aktywny';
 $labels['copyfromset'] = 'Skopiuj filtry ze zbioru';
 $labels['none'] = '- brak -';
+$labels['filterdisabled'] = 'Filtr wyłączony';
 
 $messages = array();
 $messages['filterunknownerror'] = 'Nieznany błąd serwera';
diff --git a/plugins/managesieve/managesieve.js b/plugins/managesieve/managesieve.js
index 99b820f..08954c1 100644
--- a/plugins/managesieve/managesieve.js
+++ b/plugins/managesieve/managesieve.js
@@ -26,9 +26,10 @@
 
     if (rcmail.env.action == 'plugin.managesieve')
       {
-	if (rcmail.gui_objects.sieveform)
+	if (rcmail.gui_objects.sieveform) {
 	  rcmail.enable_command('plugin.managesieve-save', true);
-	else {
+	}
+        else {
 	  rcmail.enable_command('plugin.managesieve-del', 'plugin.managesieve-up',
 	    'plugin.managesieve-down', false);
           rcmail.enable_command('plugin.managesieve-add', 'plugin.managesieve-setadd', !rcmail.env.sieveconnerror);
@@ -47,6 +48,8 @@
     	    rcmail.filters_list.focus();
 	  }
       }
+    if (rcmail.gui_objects.sieveform && rcmail.env.rule_disabled)
+      $('#disabled').attr('checked', true);
   });
 
   /*********************************************************/
@@ -91,7 +94,7 @@
 	return i;
     }
 
-  rcube_webmail.prototype.managesieve_updatelist = function(action, name, id)
+  rcube_webmail.prototype.managesieve_updatelist = function(action, name, id, disabled)
     {
     this.set_busy(true);
 
@@ -114,7 +117,7 @@
 
       case 'down':
         var rows = this.filters_list.rows;
-	var from;
+	var from, fromstatus, status;
 
 	// we need only to replace filter names...
         for (var i=0; i<rows.length; i++)
@@ -122,11 +125,15 @@
 	  if (rows[i]==null) { // removed row
 	    continue;
           } else if (rows[i].uid == id) {
-	    from = rows[i].obj.cells[0];
+	    from = rows[i].obj;
+            fromstatus = $(from).hasClass('disabled');
 	  } else if (rows[i].uid == id+1){
 	    name = rows[i].obj.cells[0].innerHTML;
-	    rows[i].obj.cells[0].innerHTML = from.innerHTML;
-	    from.innerHTML = name;
+            status = $(rows[i].obj).hasClass('disabled');
+	    rows[i].obj.cells[0].innerHTML = from.cells[0].innerHTML;
+	    from.cells[0].innerHTML = name;
+            $(from)[status?'addClass':'removeClass']('disabled');
+            $(rows[i].obj)[fromstatus?'addClass':'removeClass']('disabled');
 	    this.filters_list.highlight_row(i);
 	    break;
 	  }
@@ -137,7 +144,7 @@
 
       case 'up':
         var rows = this.filters_list.rows;
-	var from;
+	var from, status, fromstatus;
 
 	// we need only to replace filter names...
         for (var i=0; i<rows.length; i++)
@@ -145,12 +152,16 @@
 	  if (rows[i]==null) { // removed row
 	    continue;
           } else if (rows[i].uid == id-1) {
-	    from = rows[i].obj.cells[0];
+	    from = rows[i].obj;
+            fromstatus = $(from).hasClass('disabled');
 	    this.filters_list.highlight_row(i);
 	  } else if (rows[i].uid == id) {
 	    name = rows[i].obj.cells[0].innerHTML;
-	    rows[i].obj.cells[0].innerHTML = from.innerHTML;
-	    from.innerHTML = name;
+            status = $(rows[i].obj).hasClass('disabled');
+	    rows[i].obj.cells[0].innerHTML = from.cells[0].innerHTML;
+	    from.cells[0].innerHTML = name;
+            $(from)[status?'addClass':'removeClass']('disabled');
+            $(rows[i].obj)[fromstatus?'addClass':'removeClass']('disabled');
 	    break;
 	  }
 	}
@@ -164,6 +175,10 @@
 	  if (rows[i] && rows[i].uid == id)
 	    {
 	    rows[i].obj.cells[0].innerHTML = name;
+            if (disabled)
+              $(rows[i].obj).addClass('disabled');
+            else
+              $(rows[i].obj).removeClass('disabled');
 	    break;
 	    }
         break;
@@ -186,6 +201,8 @@
     	    td = parent.document.createElement('td');
     	    new_row.appendChild(td);
 	    list.insert_row(new_row, false);
+            if (disabled)
+              $(new_row).addClass('disabled');
 
     	    if (row.cells[0].className)
     	      td.className = row.cells[0].className;
diff --git a/plugins/managesieve/managesieve.php b/plugins/managesieve/managesieve.php
index e88fcff..4c50616 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 2.2
+ * @version 2.3
  * @author Aleksander 'A.L.E.C' Machniak <alec@alec.pl>
  *
  * Configuration (see config.inc.php.dist)
@@ -46,9 +46,7 @@
   
   function managesieve_start()
   {
-    $rcmail = rcmail::get_instance();
-    $this->rc = &$rcmail;
-
+    $this->rc = rcmail::get_instance();
     $this->load_config();
 
     // register UI objects
@@ -302,6 +300,7 @@
       foreach ($sizeitems as $item)
 	$items[] = $item;
 
+      $this->form['disabled'] = $_POST['_disabled'] ? true : false;
       $this->form['join'] = $join=='allof' ? true : false;
       $this->form['name'] = $name;
       $this->form['tests'] = array();
@@ -486,8 +485,10 @@
 	if ($save && $fid !== false)
 	{
 	  $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
-	  $this->rc->output->add_script(sprintf("rcmail.managesieve_updatelist('%s', '%s', %d);",
-	    isset($new) ? 'add' : 'update', Q($this->form['name']), $fid), 'foot');
+	  $this->rc->output->add_script(
+            sprintf("rcmail.managesieve_updatelist('%s', '%s', %d, %d);",
+	      isset($new) ? 'add' : 'update', Q($this->form['name']), $fid, $this->form['disabled']),
+              'foot');
 	}
 	else
 	{
@@ -504,10 +505,12 @@
   {
     // Handle form action 
     if (isset($_GET['_framed']) || isset($_POST['_framed'])) {
-      if (isset($_GET['_newset']) || isset($_POST['_newset']))
+      if (isset($_GET['_newset']) || isset($_POST['_newset'])) {
         $this->rc->output->send('managesieve.setedit');
-      else
+      }
+      else {
         $this->rc->output->send('managesieve.filteredit');
+      }
     } else {
       $this->rc->output->set_pagetitle($this->gettext('filters'));
       $this->rc->output->send('managesieve.managesieve');
@@ -525,8 +528,12 @@
     $a_show_cols = array('managesieve.filtername');
 
     foreach($this->script as $idx => $filter)
-      $result[] = array('managesieve.filtername' => $filter['name'], 'id' => $idx);
-    
+      $result[] = array(
+        'managesieve.filtername' => $filter['name'],
+        'id' => $idx,
+        'class' => $filter['disabled'] ? 'disabled' : '',
+      );
+
     // create XHTML table
     $out = rcube_table_output($attrib, $result, $a_show_cols, 'id');
 
@@ -722,7 +729,10 @@
     $out .= "</div>\n";
 
     $out .= "</fieldset>\n";
-
+    
+    if ($scr['disabled']) {
+      $this->rc->output->set_env('rule_disabled', true);
+    }
     $this->rc->output->add_label('managesieve.ruledeleteconfirm');
     $this->rc->output->add_label('managesieve.actiondeleteconfirm');
     $this->rc->output->add_gui_object('sieveform', 'filterform');
diff --git a/plugins/managesieve/skins/default/managesieve.css b/plugins/managesieve/skins/default/managesieve.css
index 295c3f6..9f72e4a 100644
--- a/plugins/managesieve/skins/default/managesieve.css
+++ b/plugins/managesieve/skins/default/managesieve.css
@@ -5,7 +5,6 @@
 {
   position: absolute;
   left: 20px;
-  width: 220px;
   top: 120px;
   bottom: 30px;
   border: 1px solid #999999;
@@ -28,6 +27,11 @@
   cursor: pointer;
 }
 
+#filters-table tbody tr.disabled td
+{
+  color: #999999;
+}
+
 #filtersbuttons
 {
   position: absolute;
@@ -38,7 +42,7 @@
 #filtersetsbuttons
 {
   position: absolute;
-  left: 250px;
+  left: 230px;
   top: 85px;
 }
 
@@ -131,7 +135,7 @@
 #filtersetselect
 {
   position: absolute;
-  left: 380px;
+  left: 360px;
   top: 90px;
 }
 
@@ -139,7 +143,6 @@
 {
   position: absolute;
   top: 120px;
-  left: 250px;
   right: 20px;
   bottom: 30px;
   border: 1px solid #999999;
@@ -168,12 +171,6 @@
   white-space: nowrap;
   background-color: #F9F9F9;
   padding: 20px 10px 10px 10px;
-}
-
-#filter-form input, select
-{
-  font-size: 10pt;
-  font-family: inherit;
 }
 
 fieldset
@@ -248,3 +245,24 @@
   font-size: 10px;
   white-space: nowrap;
 }
+
+#footer
+{
+  padding-top: 5px;
+  width: 100%;
+}
+  
+#footer .footerleft
+{
+  padding-left: 2px;
+  white-space: nowrap;
+  float: left;
+}
+
+#footer .footerright
+{
+  padding-right: 2px;
+  white-space: nowrap;
+  text-align: right;
+  float: right;
+}
diff --git a/plugins/managesieve/skins/default/templates/filteredit.html b/plugins/managesieve/skins/default/templates/filteredit.html
index 164b91c..81c6e6b 100644
--- a/plugins/managesieve/skins/default/templates/filteredit.html
+++ b/plugins/managesieve/skins/default/templates/filteredit.html
@@ -99,9 +99,15 @@
 <div id="filter-form">
 <roundcube:object name="filterform" />
 
-<p>
+<div id="footer">
+<div class="footerleft">
 <roundcube:button command="plugin.managesieve-save" type="input" class="button mainaction" label="save" />
-</p>
+</div>
+<div class="footerright">
+<label for="disabled"><roundcube:label name="managesieve.filterdisabled" /></label>
+<input type="checkbox" id="disabled" name="_disabled" value="1" />
+</div>
+</div>
 
 </form>
 </div>
diff --git a/plugins/managesieve/skins/default/templates/managesieve.html b/plugins/managesieve/skins/default/templates/managesieve.html
index 0913ef5..f99466e 100644
--- a/plugins/managesieve/skins/default/templates/managesieve.html
+++ b/plugins/managesieve/skins/default/templates/managesieve.html
@@ -5,6 +5,15 @@
 <roundcube:include file="/includes/links.html" />
 <link rel="stylesheet" type="text/css" href="/this/managesieve.css" />
 <script type="text/javascript" src="/functions.js"></script>
+<script type="text/javascript" src="/splitter.js"></script>
+
+<style type="text/css">
+#filterslist { width: <roundcube:exp expression="!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter-5 : 210" />px; }
+#filter-box { left: <roundcube:exp expression="!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter+5 : 220" />px;
+<roundcube:exp expression="browser:ie ? ('width:expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter+5 : 220).')+\\'px\\');') : ''" />
+}
+</style>
+
 </head>
 <body>
 
@@ -32,7 +41,10 @@
 <div id="filterslist">
 <roundcube:object name="filterslist" id="filters-table" class="records-table" cellspacing="0" summary="Filters list" />
 </div>
-
+<script type="text/javascript">
+  var sieveviewsplit = new rcube_splitter({id:'sieveviewsplitter', p1: 'filterslist', p2: 'filter-box', orientation: 'v', relative: true, start: 215});
+  rcmail.add_onload('sieveviewsplit.init()');
+</script>
 <div id="filter-box">
 <roundcube:object name="filterframe" id="filter-frame" width="100%" height="100%" frameborder="0" src="/watermark.html" />
 </div>

--
Gitblit v1.9.1