[Svn] r3376 - in trunk/roundcubemail: . plugins/managesieve plugins/managesieve/lib plugins/managesieve/localization plugins/managesieve/skins/default plugins/managesieve/skins/default/templates

trac at roundcube.net trac at roundcube.net
Thu Mar 18 09:53:33 CET 2010


Author: alec
Date: 2010-03-18 03:53:32 -0500 (Thu, 18 Mar 2010)
New Revision: 3376

Modified:
   trunk/roundcubemail/CHANGELOG
   trunk/roundcubemail/plugins/managesieve/Changelog
   trunk/roundcubemail/plugins/managesieve/lib/rcube_sieve.php
   trunk/roundcubemail/plugins/managesieve/localization/en_US.inc
   trunk/roundcubemail/plugins/managesieve/localization/pl_PL.inc
   trunk/roundcubemail/plugins/managesieve/managesieve.js
   trunk/roundcubemail/plugins/managesieve/managesieve.php
   trunk/roundcubemail/plugins/managesieve/skins/default/managesieve.css
   trunk/roundcubemail/plugins/managesieve/skins/default/templates/filteredit.html
   trunk/roundcubemail/plugins/managesieve/skins/default/templates/managesieve.html
Log:
- 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


Modified: trunk/roundcubemail/CHANGELOG
===================================================================
--- trunk/roundcubemail/CHANGELOG	2010-03-17 18:21:07 UTC (rev 3375)
+++ trunk/roundcubemail/CHANGELOG	2010-03-18 08:53:32 UTC (rev 3376)
@@ -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

Modified: trunk/roundcubemail/plugins/managesieve/Changelog
===================================================================
--- trunk/roundcubemail/plugins/managesieve/Changelog	2010-03-17 18:21:07 UTC (rev 3375)
+++ trunk/roundcubemail/plugins/managesieve/Changelog	2010-03-18 08:53:32 UTC (rev 3376)
@@ -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)

Modified: trunk/roundcubemail/plugins/managesieve/lib/rcube_sieve.php
===================================================================
--- trunk/roundcubemail/plugins/managesieve/lib/rcube_sieve.php	2010-03-17 18:21:07 UTC (rev 3375)
+++ trunk/roundcubemail/plugins/managesieve/lib/rcube_sieve.php	2010-03-18 08:53:32 UTC (rev 3376)
@@ -58,6 +58,10 @@
         $this->disabled = $disabled;
     }
 
+    public function __destruct() {
+        $this->sieve->disconnect();
+    }
+
     /**
     * Getter for error code
     */
@@ -221,15 +225,25 @@
 	// 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;
 
     	return true;
@@ -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++;
+	        $i++;
 	    }
+
+//            $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";
   
-	  $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['t