Code

New sieve filter, not yet finished.
authorhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 22 Feb 2007 07:19:36 +0000 (07:19 +0000)
committerhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 22 Feb 2007 07:19:36 +0000 (07:19 +0000)
git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@5727 594d385d-05f5-0310-b6e9-bd551577e9d8

include/sieve/class_My_Parser.inc [new file with mode: 0644]
include/sieve/class_My_Tree.inc [new file with mode: 0644]
include/sieve/class_semantics.inc
include/sieve/class_sieveElement.inc [new file with mode: 0644]
include/sieve/class_sieveElements.inc [new file with mode: 0644]
include/sieve/class_sieveManagement.inc [new file with mode: 0644]

diff --git a/include/sieve/class_My_Parser.inc b/include/sieve/class_My_Parser.inc
new file mode 100644 (file)
index 0000000..703d44a
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+
+class My_Parser extends Parser 
+{
+       function parse($script) 
+       {
+        $this->status_text = "incomplete";
+        $this->script_ = $script;
+        $this->tree_ = new My_Tree(Scanner::scriptStart());
+        $this->tree_->setDumpFunc(array(&$this, 'dumpToken_'));
+        $this->scanner_ = new Scanner($this->script_);
+        $this->scanner_->setCommentFunc(array($this, 'comment_'));
+
+        if ($this->commands_($this->tree_->getRoot()) &&
+            $this->scanner_->nextTokenIs('script-end'))
+        {
+            return $this->success_('success');
+        }
+
+        return $this->status_;
+       }
+
+       function dumpToken_(&$token)
+       {
+               if (is_array($token))
+               {
+                       $str = "<" . $token['text'] . "> ";
+                       foreach ($token as $k => $v)
+                       {
+                               $str .= " $k:$v";
+                       }
+                       return $str;
+               }
+               return strval($token);
+       }
+}
+?>
diff --git a/include/sieve/class_My_Tree.inc b/include/sieve/class_My_Tree.inc
new file mode 100644 (file)
index 0000000..396634a
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+
+class My_Tree extends Tree
+{
+  var $dumpFn_;
+  var $dump_;
+
+  var $mode_stack = array();
+  var $pap             = array();
+
+
+  function dump()
+  {
+    error_reporting(E_ALL);    
+    $this->dump_ = "";
+    $this->mode_stack = array();
+    $this->pap = array();
+    $this->doDump_(0, '', true);
+
+    $this->dump_ ="<table width='100%'><tr><td style='background-color:#BBBBBB;border: solid 2px #FFFFFF;padding-left:20px;'>";
+    foreach($this->pap as $object){
+      if(is_object($object)){
+        $this->dump_ .= $object->execute()."<br>"; 
+      }
+    }
+    $this->dump_ .= "</td></tr></table>";
+    return $this->dump_;
+  }
+
+
+  /* This function walks through the object tree generated by the "Parse" class.
+   * All Commands will be resolved and grouped. So the Commands and their 
+   *  parameter are combined. Like "IF" and ":comparator"...
+   */  
+  function doDump_($node_id, $prefix, $last,$num = 1)
+  {
+    /* Indicates that current comman will only be valid for a single line. 
+     *  this command type will be removed from mode_stack after displaying it.
+     */
+    $rewoke_last = FALSE;
+
+    /* Get node */ 
+    $node = $this->nodes_[$node_id];
+
+    /* This closes the last mode */
+    if($node['class'] == "block-start"){
+      $tmp = array_pop($this->mode_stack);
+      $this->handle_elements($tmp);
+      $this->handle_elements(array("TYPE" => "block_start"));
+    }
+
+    /* This closes the last mode */
+    if($node['class'] == "block-end"){
+      $tmp = array_pop($this->mode_stack);
+      $this->handle_elements($tmp);
+      $this->handle_elements(array("TYPE" => "block_end"));
+    }
+
+    /* Semicolon indicates a new command */
+    if($node['class'] == "semicolon"){
+      $tmp =array_pop($this->mode_stack);
+      $this->handle_elements($tmp);
+    }
+
+    /* Handle comments */
+    if($node['class'] == "comment"){
+      $this->mode_stack[] = array("TYPE" => $node['class']);
+      $rewoke_last = TRUE;
+    }
+
+    /* Handle identifiers */
+    $identifiers = array("if","elsif","end","reject","redirect","vacation","keep","discard","comment","fileinto","require");
+    if($node['class'] == "identifier" && in_array($node['text'],$identifiers)){
+      $this->mode_stack[] = array("TYPE" => $node['text']); 
+    }
+
+    /* Add current node to current command stack */
+    end($this->mode_stack);
+    $key = key($this->mode_stack);
+    $this->mode_stack[$key]['ELEMENTS'][] = $node;
+
+    /* Remove last mode from mode stack, cause it was only valid for a single line */
+    if($rewoke_last){
+      $tmp =array_pop($this->mode_stack);
+      $this->handle_elements($tmp);
+    }
+
+    /* If this is a sub element, just call this for all childs */      
+    if(isset($this->childs_[$node_id])){
+      $childs = $this->childs_[$node_id];
+      for ($i=0; $i<count($childs); ++$i)
+      {
+        $c_last = false;
+        if ($i+1 == count($childs))
+        {
+          $c_last = true;
+        }
+        $this->doDump_($childs[$i], "", $num);
+      }
+    }
+  }
+
+
+  function handle_elements($data)
+  {
+    if(!isset($data['TYPE'])){
+      return;
+    }
+    $type = $data['TYPE'];
+    
+    $class_name= "sieve_".$type ;
+    if(class_exists($class_name)){
+      $this->pap[] = new $class_name($data);
+    }else{
+      echo "<font color='red'>Missing : ".$class_name."</font>"."<br>";
+    }
+  }
+}
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
index e4b1f4c19bc7f7b72dece8bd4338f58359547f12..80e893ebc9bb6af397d74229fc87ed3ca939f026 100644 (file)
@@ -16,6 +16,7 @@ class Semantics
        function Semantics($command)
        {
                $this->command_ = $command;
+
                $this->unknown = false;
                switch ($command)
                {
@@ -329,6 +330,11 @@ class Semantics
        function setRequire_($text)
        {
                global $requires_;
+
+               if(!is_array($requires_)){
+                       $requires_ = array();
+               }
+
                array_push($requires_, $text);
                return true;
        }
@@ -550,4 +556,4 @@ class Semantics
        }
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/include/sieve/class_sieveElement.inc b/include/sieve/class_sieveElement.inc
new file mode 100644 (file)
index 0000000..b6fde6f
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+class sieveElement 
+{
+       
+       var $name                       = "Unknown";
+       var $responsible_for= array();  
+
+  var $data ="";
+
+       function sieveElement()
+       {
+       
+       }
+
+  function resolve_to_object($data)
+  {
+    $this->data = @nl2br($data->dumpParseTree());
+  }
+
+  function execute()
+  {
+    return($this->data);
+  }
+}      
+
+
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/include/sieve/class_sieveElements.inc b/include/sieve/class_sieveElements.inc
new file mode 100644 (file)
index 0000000..1bb693a
--- /dev/null
@@ -0,0 +1,321 @@
+<?php
+
+
+class sieve_element
+{
+
+  function execute()
+  {
+    return("NIY<br>");
+  }
+}
+
+class sieve_elsif extends sieve_if {}
+class sieve_if extends sieve_element
+{
+
+  /* Contains all tests with an uniqe id */
+  var $test_list = array();
+      
+  /* Available test types */
+  var $TESTS = array("address","allof","anyof","exists","false","header","not","size","true","envelope");
+  
+  var $elements = array();
+
+
+  function sieve_if($elements)
+  {
+    $this->elements = $elements;
+    $this->_parse($elements);
+  }
+
+  function execute()
+  {
+    return("-> "._("Condition"));
+  }
+
+
+  function _parse($data,$id = 0)
+  {
+    /* Objects that could be tested */
+    $av_methods   = array("address","allof","anyof","exists","false","header","not","size","true","envelope");
+
+    /* Tests that could be used */
+    $av_match_type= array(":is",":contains",":matches",":over",":count",":value");
+
+    /* Variable initialization */
+    $test_method    = ""; // The object that we want to test, like 'header'
+    $match_type     = ""; // The operator like :contains
+    $obj_attribute  = ""; // The attribute we want to check, like 'from'
+    $obj_match_value= ""; // The value that we want to match for.
+    $comparator     = ""; // The comperator specifies the type of values that should be matched.
+
+    $node = $data['ELEMENTS'][$id];
+
+    /* Skip the if / else identifier */
+    if($node ['class'] == "identifier" && in_array($node['text'],array("if","elsif"))){
+      $id ++;
+      $node = $data['ELEMENTS'][$id];
+    }
+
+    /* Get current command like "allof" or "header" */
+    if($node ['class'] == "identifier" && in_array($node['text'],$av_methods)){
+      $test_method = $node['text'];
+    }
+
+    echo $id;
+
+    /* switch different types */
+    switch($test_method)
+    {
+      case "allof"  : $this->_parse($elements,$id);
+      case "anyof"  : $this->_parse($elements,$id);
+
+      case "address" : 
+      {
+        /* header :comparator <string> :optional-operator :operator attribute match-value */
+        $tmp = array();
+        $tmp['OPTIONAL_OP']     ="";
+        $tmp['COMPARATOR']      ="";
+        $tmp['OPERATOR']        ="";
+        $tmp['ATTRIBUTE']       ="";
+        $tmp['MATCH-VALUE']     ="";
+        
+
+      }
+      default : echo $test_method."<br>" ;
+    }
+  }
+};
+
+
+class sieve_comment extends sieve_element
+{
+  var $data = "";
+    
+  function sieve_comment($data)
+  {
+    foreach($data['ELEMENTS'] as $node){
+       $this->data .= $node['text'];
+    }
+  }
+
+  function execute()
+  {
+    return(_("Comment")."&nbsp;<input type='text' name='comment_' value='".$this->data."'>");
+  }
+}
+
+
+class sieve_require extends sieve_element
+{
+  var $data = array();
+
+  function sieve_require($data)
+  {
+    foreach($data['ELEMENTS'] as $node ){
+      if(in_array($node['class'],array("quoted-string","text"))){
+        $this->data[] = preg_replace("/\"/","",$node['text']);
+      }
+    }
+  }
+
+  function execute()
+  {
+    $str = _("Sieve includes");
+    foreach($this->data as $req){
+      $str .= "&nbsp;<i>".$req."</i>";
+    }
+    return($str);
+  }
+}
+
+class sieve_discard extends sieve_element
+{
+  var $data = array();
+
+  function sieve_discard($data)
+  {
+  }
+
+  function execute()
+  {
+    $str = _("Discard mail");
+    return($str);
+  }
+}
+
+
+
+class sieve_reject extends sieve_element
+{
+  var $data = array();
+
+  function sieve_reject($data)
+  {
+    $str = "";
+    foreach($data['ELEMENTS'] as $node ){
+      if(in_array($node['class'],array("quoted-string","text"))){
+        $str .= $node['text'];
+      }
+    }
+    $this->data = preg_replace("/\"/","",$str);
+  }
+
+  function execute()
+  {
+    $str = _("Reject mail");
+    $str .= "&nbsp;<textarea name='test' style='width:90%'>".$this->data."</textarea>";
+    return($str);
+  }
+}
+
+class sieve_redirect extends sieve_element
+{
+  var $data = array();
+
+  function sieve_redirect($data)
+  {
+    foreach($data['ELEMENTS'] as $node ){
+      if(in_array($node['class'],array("quoted-string","text"))){
+        $this->data[] = $node['text'];
+      }
+    }
+  }
+
+  function execute()
+  {
+    $str = _("Redirect to");
+    foreach($this->data as $dest){
+      $str .= "<input type='text' name='bal' value='".$dest."'><br> ";
+    }
+    return($str);
+  }
+}
+
+class sieve_fileinto extends sieve_element
+{
+  var $data = array();
+
+  function sieve_fileinto($data)
+  {
+    foreach($data['ELEMENTS'] as $node ){
+      if(in_array($node['class'],array("quoted-string","text"))){
+        $this->data[] = preg_replace("/\"/","",$node['text']);
+      }
+    }
+  }
+
+  function execute()
+  {
+    $str = _("File into");
+
+    $str .= "<select name='test'>";
+    foreach($this->data as $folder){
+      $str .= "<option>".$folder."</option>";
+    }
+    $str .= "</select>";
+
+    return($str);
+  }
+}
+
+class sieve_vacation extends sieve_element 
+{
+  var $days     = FALSE;
+  var $subject  = FALSE;
+  var $from     = "";
+  var $mime     = "";
+  var $hanlde   = "";
+  var $reason   = "";
+  var $addresses= array();
+
+  function sieve_vacation($data)
+  {
+    /* Usage:   vacation [":days" number] [":subject" string]
+       [":from" string] [":addresses" string-list]
+       [":mime"] [":handle" string] <reason: string> */
+
+    /* Not all attribute types are supported by the sieve class right now */
+    $known_attrs = array(":days",":subject",":from",":mime",":handle");
+
+    /* Walk through elements */
+    for($i = 0 ; $i < count($data['ELEMENTS']) ; $i ++){
+
+      /* get current element */
+      $node = $data['ELEMENTS'][$i];
+
+      /* Check if tag is in the specified list of attributes */
+      if($node['class'] == "tag" && in_array($node['text'],$known_attrs)){
+
+        $var = preg_replace("/\:/","",$node['text']);
+        $this->$var = $data['ELEMENTS'][$i+1]['text'];
+        $i ++;
+      }
+
+      /* Check for addresses */
+      if($node['class'] == "tag" && $node['text'] == ":addresses") {
+        $this->addresses = array();
+        $i ++;
+
+        /* Multiple or single address given */
+        if($data['ELEMENTS'][$i]['class'] == "left-bracket"){
+          while($data['ELEMENTS'][$i]['class'] != "right-bracket" && ($i < count($data['ELEMENTS']))){
+            $i ++;
+            if($data['ELEMENTS'][$i]['class'] == "quoted-string"){
+              $this->addresses[] = preg_replace("/\"/i","",$data['ELEMENTS'][$i]['text']);
+            }
+          }
+        }else{
+          $this->addresses[] = $data['ELEMENTS'][$i]['text'] ;
+        }
+      }
+
+      /* Add the vacation message */
+      if($node['class'] == "quoted-string"){
+        $this->reason = $node['text'];
+      }
+    }
+  }
+
+
+  function execute()
+  {
+    $str ="";
+    $str .="<b>"._("Vacation message")."</b>";
+    foreach($this->addresses as $addr){ 
+      $str .="<br><input type='text' value='".$addr."' style='width:50%;'>";
+    }
+    $str .="<br><textarea style='width:100%;height:60px;'>".$this->reason."</textarea>";
+    
+    return($str);
+  }
+}
+
+class sieve_block_start extends sieve_element 
+{
+  function execute()
+  {
+    return("<table width='100%'> <tr><td style='background-color:#BBBBBB;border: solid 2px #FFFFFF;padding-left:20px;'>");
+  }
+}
+
+class sieve_block_end extends sieve_element 
+{
+  function execute()
+  {
+    return("</td></tr></table>");
+  }
+}
+
+/* This class handles the keep statement */
+class sieve_keep extends sieve_element 
+{
+  function execute()
+  {
+    return("->  "._("Keep message"));
+  }
+}
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/include/sieve/class_sieveManagement.inc b/include/sieve/class_sieveManagement.inc
new file mode 100644 (file)
index 0000000..945a6d2
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+/*
+   This code is part of GOsa (https://gosa.gonicus.de)
+   Copyright (C) 2003-2007 - Fabian Hickert <hickert@gonicus.de>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+class sieveManagement extends plugin
+{
+  var $parent = NULL;
+  var $scripts= array();  
+
+  
+  function sieveManagement($config,$dn,$parent)
+  {
+    $this->parent = $parent;
+    plugin::plugin($config,$dn);
+
+
+    /* Connect to sieve class and try to get all available sieve scripts */
+    $cfg=  $this->config->data['SERVERS']['IMAP'][$this->parent->gosaMailServer];
+    
+    /* Log into the mail server */
+    $sieve= new sieve($cfg["sieve_server"], $cfg["sieve_port"], $this->parent->uid,
+        $cfg["password"], $cfg["admin"]);
+
+    /* Try to login */
+    if (!$sieve->sieve_login()){
+      print_red(sprintf(_("Can't log into SIEVE server. Server says '%s'."),
+            to_string($sieve->error_raw)));
+      return;
+    }
+
+    /* Get all sieve scripts names */
+    if($sieve->sieve_listscripts()){
+      if (is_array($sieve->response)){
+        foreach($sieve->response as $key => $name){
+          $this->scripts[$key]['NAME'] = $name;
+        }
+      } 
+    }
+
+    /* Get script contents */
+    foreach($this->scripts as $key => $script){
+      $p = new My_Parser;
+      $sieve->sieve_getscript($script['NAME']);
+
+      $script = "";
+      foreach($sieve->response as $line){
+        $script.=$line;
+      }
+
+      $this->scripts[$key]['SCRIPT'] = $script;
+      $this->scripts[$key]['MSG']   = "";
+      $ret = $p->parse($script);
+      if(!$ret){
+        $this->scripts[$key]['MSG']   = "<font color='red'>".$p->status_text."</font>";
+        $this->scripts[$key]['STATUS'] = FALSE;
+      }else{
+        $this->scripts[$key]['STATUS'] = TRUE;
+      }
+      $this->scripts[$key]['PARSER'] = $p;
+    }
+  }
+
+  function execute()
+  {
+    $once = TRUE;
+    foreach($_POST as $name => $value){
+      if(preg_match("/^editscript_/",$name) && $once){
+        $script = preg_replace("/^editscript_/","",$name);
+        $script = preg_replace("/_(x|y)/","",$script);
+        $once = FALSE;
+
+        $obj_handler = new sieveElement;
+        $data = $this->scripts[$script]['PARSER'];
+        $obj_handler->resolve_to_object($data);
+        return($obj_handler->execute());
+      }
+    }
+
+
+    $List = new divSelectBox("sieveManagement");
+
+    foreach($this->scripts as $key => $script){
+  
+      $field1 = array("string" => $script['NAME']);  
+
+      if($script['STATUS']){
+        $field2 = array("string" => _("Parse successful"));
+      }else{
+        $field2 = array("string" => _("Parse failed") .$script['MSG']);
+      }
+
+      $field3 = array("string" => _("Script length")."&nbsp;:&nbsp;".strlen($script['SCRIPT']));
+      $field4 = array("string" => "<input type='image' name='editscript_".$key."' src='images/edit.png'>");
+
+      $List ->AddEntry(array($field1,$field2,$field3,$field4)); 
+    }
+
+    return($List->DrawList());
+  }
+
+  function save_object()
+  {
+    
+  }
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>