Code

Moved kolab
authorcajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 17 Jan 2008 08:43:34 +0000 (08:43 +0000)
committercajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 17 Jan 2008 08:43:34 +0000 (08:43 +0000)
git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@8435 594d385d-05f5-0310-b6e9-bd551577e9d8

65 files changed:
gosa-core/plugins/personal/connectivity/class_kolabAccount.inc [deleted file]
gosa-core/plugins/personal/connectivity/kolab.tpl [deleted file]
gosa-plugins/kolab/personal/connectivity/class_kolabAccount.inc [new file with mode: 0644]
gosa-plugins/kolab/personal/connectivity/kolab.tpl [new file with mode: 0644]
gosa-plugins/kolab/personal/mail/class_mail-methods-golab.inc [new file with mode: 0644]
gosa-plugins/kolab/personal/mail/class_mail-methods-kolab.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/class_mail-methods-golab.inc [deleted file]
gosa-plugins/mail/personal/mail/class_mail-methods-kolab.inc [deleted file]
gosa-plugins/mail/personal/mail/sieve/class_My_Parser.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_My_Scanner.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_My_Tree.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_parser.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_scanner.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_semantics.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieve.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_End.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_Start.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Comment.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Discard.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Else_Elsif.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Fileinto.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_If.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Keep.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Redirect.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Reject.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Require.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Stop.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Vacation.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_sieveManagement.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/class_tree.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/libsieve.inc [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/add_element.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/block_indent_start.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/block_indent_stop.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/create_script.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/edit_frame_base.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_address.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_allof.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_anyof.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_block_end.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_block_start.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_boolean.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_comment.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_discard.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_else.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_elsif.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_envelope.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_exists.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_fileinto.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_header.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_if.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_keep.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_redirect.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_reject.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_require.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_size.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_stop.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/element_vacation.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/import_script.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/management.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/object_container.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/object_container_clear.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/object_test_container.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/remove_script.tpl [new file with mode: 0644]
gosa-plugins/mail/personal/mail/sieve/templates/select_test_type.tpl [new file with mode: 0644]

diff --git a/gosa-core/plugins/personal/connectivity/class_kolabAccount.inc b/gosa-core/plugins/personal/connectivity/class_kolabAccount.inc
deleted file mode 100644 (file)
index a9149d4..0000000
+++ /dev/null
@@ -1,602 +0,0 @@
-<?php
-class kolabAccount extends plugin
-{
-  /* Definitions */
-  var $plHeadline       = "Kolab";
-  var $plDescription    = "This does something";
-
-  /* Kolab attributes */
-  var $kolabInvitationPolicy  = array();
-  var $kolabFreeBusyFuture    = 60;
-  var $unrestrictedMailSize   = 0;
-  var $calFBURL               = "";
-  var $kolabDelegate          = array();
-
-  /* attribute list for save action */
-  var $attributes     = array("kolabFreeBusyFuture", "unrestrictedMailSize", "calFBURL","kolabDelegate","kolabInvitationPolicy");
-  var $objectclasses  = array("kolabInetOrgPerson");
-
-  /* Helper */
-  var $imapping     = array();
-  var $mail_Account = false;
-  var $ReadOnly     = false;
-  var $view_logged  = FALSE;
-  var $uid          = "";
-
-  var $multiple_support = TRUE;
-
-
-  /*! \brief Initialize Plugin 
-      @param  $config   GOsa configuration object
-      @param  $dn       DN of the currently edited object
-      @param  $parent   The parent object, used to fetch Attributes.
-   */
-  function kolabAccount (&$config, $dn= NULL,$parent = NULL)
-  {
-    plugin::plugin ($config, $dn, $parent);
-
-    /* Setting uid to default */
-    if(isset($this->attrs['uid'][0])){
-      $this->uid = $this->attrs['uid'][0];
-    }
-
-    /* Pull arrays */
-    foreach(array("kolabDelegate", "kolabInvitationPolicy") as $attr){
-      if (isset($this->attrs["$attr"]["count"])){
-        $tmp = array();
-        for ($i= 0; $i<$this->attrs["$attr"]["count"]; $i++){
-          $tmp[]=$this->attrs["$attr"][$i];
-        }
-        $this->$attr = $tmp;
-      }
-    }
-
-    /* If this one is empty, preset with ACT_MANUAL for anonymous users */
-    if (count ($this->kolabInvitationPolicy) == 0){
-       $this->kolabInvitationPolicy= array("ACT_MANUAL");
-    }
-
-    /* Check is account state */
-    $this->is_account = false;
-    if(count($this->kolabDelegate)){
-      $this->is_account = true;
-    }
-    foreach(array("calFBURL","unrestrictedMailSize") as $attr){
-      if(!empty($this->$attr)){
-        $this->is_account = true;
-      }
-    } 
-
-    /* Transfer account states for this union */
-    if (isset($this->parent->by_object['mailAccount']) && $this->parent->by_object['mailAccount']->is_account){
-      $this->mail_Account = true;
-     }elseif( isset($this->attrs) && isset($this->attrs['kolabHomeServer'])){
-       $this->mail_Account= true;
-     }else{
-       $this->is_account  = false;
-      $this->mail_Account = false;
-    }
-  }
-
-    
-  /*! \brief Create thml output 
-   */
-  function execute()
-  {
-         /* Call parent execute */
-       plugin::execute();
-
-    /* Log view */
-    if($this->is_account && !$this->view_logged){
-      $this->view_logged = TRUE;
-      new log("view","users/".get_class($this),$this->dn);
-    }
-
-    /* Show tab dialog headers */
-    $display= "";
-
-    /* Show main page */
-    $smarty= get_smarty();
-
-    /* Load attributes */
-    foreach($this->attributes as $val){
-      $smarty->assign("$val", $this->$val);
-    }
-
-    $tmp = $this->plInfo();
-    foreach($tmp['plProvidedAcls'] as $acl => $description){
-      $smarty->assign($acl."ACL",$this->getacl($acl,$this->ReadOnly));
-      $smarty->assign($acl."_W", $this->acl_is_writeable($acl,$this->ReadOnly));
-    }
-    $smarty->assign("is_account" ,  $this->is_account); 
-
-    if($this->ReadOnly){
-      $smarty->assign("is_removeable",false); 
-      $smarty->assign("is_createable",false); 
-    }else{
-      $smarty->assign("is_removeable",$this->acl_is_removeable()); 
-      $smarty->assign("is_createable",$this->acl_is_createable()); 
-    }
-
-    /* Check for invitation action */
-    $nr= 0;
-  
-    foreach($_POST as $name => $value){
-      if(preg_match("/add_inv_/",$name)){
-        $this->kolabInvitationPolicy[]= ": ACT_MANUAL";
-      }
-    }
-    foreach($_POST as $name => $value){
-      if(preg_match("/del_inv_/",$name)){
-
-        $id = preg_replace("/del_inv_/","",$name);
-        $id = preg_replace("/_(x|y)$/","",$id);
-  
-        $new= array();
-        foreach ($this->kolabInvitationPolicy as $entry){
-          if (!preg_match("/^".$this->imapping[$id].":/", $entry)){
-            $new[]= $entry;
-          }
-        }
-        $this->kolabInvitationPolicy= $new;
-      }
-    }
-
-    /* Unify addresses */
-    $new= array();
-    foreach($this->kolabInvitationPolicy as $value){
-      $address= preg_replace('/^([^:]+:).*$/', '\1', $value);
-      $new[$address]= $value;
-    }
-    $this->kolabInvitationPolicy= array();
-    foreach($new as $value){
-      $this->kolabInvitationPolicy[]= $value;
-    }
-
-    /* Add delegation */
-    if (isset($_POST['add_delegation'])){
-      if ($_POST['delegate_address'] != ""){
-
-        /* Valid email address specified? */
-        $address= $_POST['delegate_address'];
-        $valid= FALSE;
-        if (!tests::is_email($address)){
-          if (!tests::is_email($address, TRUE)){
-              msg_dialog::display(_("Error"), _("Cannot add invalid mail address!"), ERROR_DIALOG);
-          }
-        } else {
-
-          $ldap= $this->config->get_ldap_link();
-          $ldap->cd ($this->config->current['BASE']);
-          $ldap->search('(mail='.$address.')',array("mail"));
-          if ($ldap->count() == 0){
-            msg_dialog::display(_("Error"), _("Primary mail address already in use by another user!"), ERROR_DIALOG);
-          } else {
-            $valid= TRUE;
-          }
-        }
-
-        if ($valid){
-          /* Add it */
-          if ($this->acl_is_writeable("kolabDelegate")){
-            $this->addDelegate ($address);
-            $this->is_modified= TRUE;
-          }
-
-        }
-      }
-    }
-
-    /* Delete forward email addresses */
-    if ((isset($_POST['delete_delegation'])) && (isset($_POST['delegate_list']))){
-      if (count($_POST['delegate_list']) && $this->acl_is_writeable("kolabDelegate")){
-        $this->delDelegate ($_POST['delegate_list']);
-      }
-    }
-
-    /* Assemble policies */
-    $policies= array( 'ACT_ALWAYS_ACCEPT'       => _("Always accept"),
-                      'ACT_ALWAYS_REJECT'       => _("Always reject"),
-                      'ACT_REJECT_IF_CONFLICTS' => _("Reject if conflicts"),
-                      'ACT_MANUAL_IF_CONFLICTS' => _("Manual if conflicts"),
-                      'ACT_MANUAL'              => _("Manual"));
-    $smarty->assign('policies', $policies);
-
-    /* Adjust checkbox */
-    if ($this->unrestrictedMailSize){
-      $smarty->assign('unrestrictedMailSizeState', "checked");
-    } else {
-      $smarty->assign('unrestrictedMailSizeState', "");
-    }
-
-    /* Transfer delegation list */
-    if (!count($this->kolabDelegate)){
-      /* Smarty will produce <option value=""></option> and tidy don't like that, so tell smarty to create no option (array();)*/
-      $smarty->assign("kolabDelegate", array());
-    } else {
-      $smarty->assign("kolabDelegate", $this->kolabDelegate);
-    }
-
-    $smarty->assign("mail_account",$this->mail_Account);
-
-    /* Create InvitationPolicy table */
-    $invitation= "";
-    $this->imapping= array();
-    $nr= 0;
-    $changeState  = "";
-    foreach ($this->kolabInvitationPolicy as $entry){
-
-      if($this->acl_is_writeable("kolabInvitationPolicy")){
-        $changeState .= "changeState('address".$nr."'); \n changeState('policy".$nr."'); \n
-          changeState('add".$nr."'); \n changeState('remove".$nr."'); \n";
-      }
-
-      if(!$this->acl_is_writeable("kolabInvitationPolicy") && !$this->multiple_support_active){
-        $dis = " disabled ";
-      }else{
-        if($this->is_account || $this->multiple_support_active){
-          $dis = " ";
-        }else{
-          $dis = " disabled ";
-        }
-      }
-      $invitation.= "<tr><td>";
-
-      if(!$this->acl_is_readable("kolabInvitationPolicy"))    {
-      }
-
-      /* The default entry does not have colons... */
-      if (!preg_match('/:/', $entry)){
-        $invitation.= _("Anonymous");
-        $name= "";
-        $mode= $entry;
-      } else {
-        $name= preg_replace('/:.*$/', '', $entry);
-        $mode= preg_replace('/^[^:]*: */', '', $entry);
-
-        if(!$this->acl_is_readable("kolabInvitationPolicy")){
-          $name='';
-        }
-        $invitation.= "<input name=\"address$nr\" size=16 maxlength=60  value=\"$name\" id='address".$nr."' ".$dis.">";
-      }
-      $invitation.= "</td>";
-
-      /* Add mode switch */
-      $invitation.= "<td><select size=\"1\" name=\"policy$nr\" id='policy".$nr."' ".$dis.">";
-      foreach($policies as $key => $value){
-        if ($key == $mode){
-          $invitation.= "<option value=\"$key\" selected>$value</option>";
-        } else {
-          $invitation.= "<option value=\"$key\">$value</option>";
-        }
-      }
-      
-      /* Assign buttons */
-      $button= "";
-      if ($nr == count($this->kolabInvitationPolicy)-1){
-        $button= "<input type='image' name=\"add_inv_".$nr."\" src='images/list_new.png' id='add".$nr."' ".$dis.">";
-      }
-      if ($nr != 0) {
-        $button.= "<input type='image' name=\"del_inv_".$nr."\" src='images/edittrash.png' id='remove".$nr."' ".$dis.">";
-      }
-      
-      $invitation.= "</select>&nbsp;</td>
-                    <td>$button</td>
-                  </tr>\n";
-      $this->imapping[$nr]= $name;
-      $nr++;
-    }
-    $smarty->assign("invitation", $invitation);
-    $smarty->assign("changeState", $changeState);
-    $smarty->assign("kolabState",$this->is_account);
-
-  
-    $smarty->assign("multiple_support",$this->multiple_support_active);
-    foreach($this->attributes as $attr){
-      $smarty->assign("use_".$attr,in_array($attr,$this->multi_boxes));
-    }
-    foreach(array("kolabState") as $attr){
-      $smarty->assign("use_".$attr,in_array($attr,$this->multi_boxes));
-    }
-
-    if($this->multiple_support_active){
-    }
-
-
-    $display.= $smarty->fetch (get_template_path('kolab.tpl', TRUE, dirname(__FILE__)));
-    return ($display);
-  }
-
-  function remove_from_parent()
-  {
-    if(!$this->initially_was_account){
-      return;
-    }
-  
-    /* Optionally execute a command after we're done */
-    plugin::remove_from_parent();
-    
-    if(!in_array("kolabInetOrgPerson",$this->attrs['objectClass'])){
-      $this->attrs['objectClass'][] = "kolabInetOrgPerson";
-    }
-
-    $ldap = $this->config->get_ldap_linK(); 
-    $ldap->cd($this->config->current['BASE']);
-    $ldap->cd ($this->dn);
-    $ldap->modify($this->attrs);
-
-    /* Log last action */
-    new log("remove","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
-
-    $this->handle_post_events('remove',array("uid" => $this->uid));
-    show_ldap_error($ldap->get_error(), sprintf(_("Removing of user/kolab account with dn '%s' failed."),$this->dn));
-  }
-
-
-  function check()
-  {
-    /* Call common method to give check the hook */
-    $message= plugin::check();
-
-    /* FBFuture is in days... */
-    if ($this->kolabFreeBusyFuture != "" && !preg_match('/^[0-9]+$/', $this->kolabFreeBusyFuture)){
-      $message[]= _("The value specified as Free Busy future needs to be an integer.");
-    }
-
-    /* Check for URL scheme... */
-    if(!empty($this->calFBURL) && !preg_match("/http+(s)*:\/\//",$this->calFBURL)){
-      $message[]= _("The value specified as Free Busy Information URL is invalid.");
-    }
-
-    /* Check invitation policy for existing mail addresses */
-    foreach($this->kolabInvitationPolicy as $policy){
-      
-      /* Ignore anonymous string */
-      if (!preg_match('/:/', $policy)){
-        continue;
-      }
-      
-      $address= preg_replace('/^([^:]+).*$/', '\1', $policy);
-      if (!tests::is_email($address)){
-        if (!tests::is_email($address, TRUE)){
-          $message[]= sprintf(_("The invitation policy entry for address '%s' is not valid."), $address);
-        }
-      } else {
-
-        $ldap= $this->config->get_ldap_link();
-        $ldap->cd ($this->config->current['BASE']);
-        $ldap->search('(mail='.$address.')',array("mail"));
-        if ($ldap->count() == 0){
-          $message[]= sprintf(_("There's no mail user with address '%s' for your invitation policy!"), $address);
-        } else {
-          $valid= TRUE;
-        }
-      }
-    }
-
-    return ($message);
-  }
-
-  /* Save data to object */
-  function save_object()
-  {
-    /* Do we need to flip is_account state? */
-    if (isset($_POST['connectivityTab'])){
-
-      if(isset($_POST["kolabState"])){
-        if($this->acl_is_createable()){
-          $this->is_account = true;
-        }
-      }else{
-        if($this->acl_is_removeable()){
-          $this->is_account = false;
-        }
-      }
-      if ($this->acl_is_writeable("unrestrictedMailSize")){
-        if (isset($_POST['unrestrictedMailSize']) && $_POST['unrestrictedMailSize'] == 1){
-          $this->unrestrictedMailSize= 1;
-        } else {
-          $this->unrestrictedMailSize= 0;
-        }
-      }
-    }
-
-    plugin::save_object();
-
-    /* Save changes done in invitation policies */
-    if($this->acl_is_writeable("kolabInvitationPolicy")){
-
-      $nr= 0;
-      $this->kolabInvitationPolicy= array();
-      while (isset($_POST["policy$nr"])){
-
-        /* Anonymous? */
-        if (!isset($_POST["address$nr"])){
-          $this->kolabInvitationPolicy[]= $_POST["policy$nr"];
-        } else {
-          $this->kolabInvitationPolicy[]= $_POST["address$nr"].": ".$_POST["policy$nr"];
-        }
-
-        $nr++;
-      }
-
-      /* If this one is empty, preset with ACT_MANUAL for anonymous users */
-      if (count ($this->kolabInvitationPolicy) == 0){
-        $this->kolabInvitationPolicy= array("ACT_MANUAL");
-      }
-    }
-  }
-
-
-  /* Save to LDAP */
-  function save()
-  {
-    /* Check mailmethod before doing something useful */
-    plugin::save();
-
-    /* Transfer arrays */
-    $this->attrs['kolabDelegate']= $this->kolabDelegate;
-    $this->attrs['kolabInvitationPolicy']= $this->kolabInvitationPolicy;
-
-    /* unrestrictedMailSize is boolean */
-    if($this->attrs['unrestrictedMailSize']){
-      $this->attrs['unrestrictedMailSize'] = "TRUE";
-    }else{
-      $this->attrs['unrestrictedMailSize'] = "FALSE";
-    }
-  
-    /* Write back to ldap */
-    $ldap= $this->config->get_ldap_link();
-    $ldap->cd($this->dn);
-    $this->cleanup();
-    $ldap->modify ($this->attrs); 
-
-    /* Log last action */
-    if($this->initially_was_account){
-      new log("modify","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
-    }else{
-      new log("create","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
-    }
-
-    show_ldap_error($ldap->get_error(), sprintf(_("Saving of user/kolab account with dn '%s' failed."),$this->dn));
-
-    /* Optionally execute a command after we're done */
-    if ($this->initially_was_account == $this->is_account){
-      if ($this->is_modified){
-        $this->handle_post_events("modify",array("uid" => $this->uid));
-      }
-    } else {
-      $this->handle_post_events("add",array("uid" => $this->uid));
-    }
-  }
-
-
-  /* Add entry to delegation list */
-  function addDelegate($address)
-  {
-    $this->kolabDelegate[]= $address;
-    $this->kolabDelegate= array_unique ($this->kolabDelegate);
-
-    sort ($this->kolabDelegate);
-    reset ($this->kolabDelegate);
-    $this->is_modified= TRUE;
-  }
-
-  function delDelegate($addresses)
-  {
-    $this->kolabDelegate= array_remove_entries ($addresses, $this->kolabDelegate);
-    $this->is_modified= TRUE;
-  }
-
-
-  /* Return plugin informations for acl handling  */
-  static function plInfo()
-  {
-    return (array(     
-          "plShortName"     => _("Kolab"),
-          "plDescription"   => _("Kolab account settings")."&nbsp;:&nbsp;<u>"._("Connectivity addon")."</u>",
-          "plSelfModify"    => TRUE,
-          "plDepends"       => array("user"),
-          "plPriority"      => 20,                                 // Position in tabs
-          "plSection"     => array("personal" => _("My account")),
-          "plCategory"    => array("users"),
-          "plOptions"       => array(),
-
-          "plProvidedAcls"  => array(
-            "kolabFreeBusyFuture"   => _("Free busy future"),
-            "unrestrictedMailSize"  => _("Mail size restriction"),
-            "calFBURL"              => _("Free busy information"),
-            "kolabDelegate"         => _("Delegations"),
-            "kolabInvitationPolicy" => _("Invitation policy"))
-          ));
-  }
-
-
-  /*! \brief  Enable multiple edit support. \
-              Also sets $this->mail_account to TRUE, which simulates \
-              a valid mail extension.
-   */
-  public function enable_multiple_support()
-  {
-    plugin::enable_multiple_support();
-    $this->mail_Account = TRUE;
-  }
-
-
-  /*! \brief  Save html POSTs in multiple edit.
-   */
-  public function multiple_save_object()
-  {
-    if (isset($_POST['connectivityTab'])){
-      plugin::multiple_save_object();
-      if(isset($_POST['use_kolabState'])){
-        $this->multi_boxes[] = "kolabState";
-      }
-      $this->save_object();
-    }
-  }
-
-
-  /*! \brief  Returns all modified values. \
-              All selected an modified values will be returned \
-              in an array.
-      @return array   Returns an array containing all attribute modifications  
-   */
-  public function get_multi_edit_values()
-  {
-    $ret = plugin::get_multi_edit_values();
-    if(in_array("kolabState",$this->multi_boxes)){
-      $ret['is_account'] = $this->is_account;
-    }
-
-    print_a($ret);
-  
-    return($ret);
-  }
-
-  /*! \brief  Sets modified attributes in mutliple edit. \
-              All collected values from "get_multi_edit_values()" \
-              will be applied to this plugin.
-      @param  array   An array containing modified attributes returned by get_multi_edit_values();
-   */
-  public function set_multi_edit_values($values)
-  {
-    plugin::set_multi_edit_values($values);
-    if(isset($values['is_account'])){
-      $this->is_account = $values['is_account'];
-    }
-  }
-
-
-  /*! \brief  Initialize multiple edit ui for this plugin. \
-              This function sets plugin defaults in multiple edit.
-      @param  array   Attributes used in all object 
-      @param  array   All used attributes.
-   */
-  public function init_multiple_support($attrs,$all)
-  {
-    plugin::init_multiple_support($attrs,$all);
-    if(isset($attrs['objectClass']) && in_array("kolabInetOrgPerson",$attrs['objectClass'])){
-      $this->is_account = TRUE;
-    }
-
-    /* Pull arrays */
-    foreach(array("kolabDelegate", "kolabInvitationPolicy") as $attr){
-      if (isset($this->multi_attrs["$attr"]["count"])){
-        $tmp = array();
-        for ($i= 0; $i<$this->multi_attrs["$attr"]["count"]; $i++){
-          $tmp[]=$this->multi_attrs["$attr"][$i];
-        }
-        $this->$attr = $tmp;
-      }
-    }
-
-    /* If this one is empty, preset with ACT_MANUAL for anonymous users */
-    if (count ($this->kolabInvitationPolicy) == 0){
-       $this->kolabInvitationPolicy= array("ACT_MANUAL");
-    }
-  }
-}
-
-// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
-?>
diff --git a/gosa-core/plugins/personal/connectivity/kolab.tpl b/gosa-core/plugins/personal/connectivity/kolab.tpl
deleted file mode 100644 (file)
index c05bfb1..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-
-{if !$mail_account}
-       <h2>{t}Kolab account{/t}</h2>
-       {t}The kolab account is currently disabled. It's features can be adjusted if you add a mail account.{/t}
-{else}
-
-<h2>
-{if $multiple_support}
-
-<input type="checkbox" name="use_kolabState" value="1" {if $use_kolabState} checked {/if}
-       class="center" onClick="changeState('kolabState');">
-<input type="checkbox" id="kolabState" name="kolabState" value="1" {if $kolabState} checked {/if}
-    class="center" {if  !$use_kolabState} disabled {/if}>
-
-{else}
-<input type="checkbox" id="kolabState" name="kolabState" value="1" {if $kolabState} checked {/if}
-       class="center" 
-       {if (!$is_account && $is_createable) || ($is_account && $is_removeable)}
-       {else}
-               disabled        
-       {/if}
-       onClick="
-       {if $kolabDelegate_W}
-       changeState('delegate_list');
-       changeState('delegate_address');
-       changeState('add_delegation');
-       changeState('delete_delegation');
-       {/if}
-       {if $unrestrictedMailSize_W}
-       changeState('unrestrictedMailSize');
-       {/if}
-       {if $calFBURL_W}
-       changeState('calFBURL');
-       {/if}
-       {if $kolabFreeBusyFuture_W}
-       changeState('kolabFreeBusyFuture');
-       {/if}
-       {if $kolabInvitationPolicy_W}
-       {$changeState}
-       {/if}">
-{/if}
-
-{t}Kolab account{/t}</h2>
-<table summary="" style="width:100%">
- <tr>
-  <td style="width:50%; vertical-align:top;">
-
-{if $multiple_support}
-       <input type="checkbox" name="use_kolabDelegate" {if $use_kolabDelegate} checked {/if}
-               class="center" onClick="changeState('delegate_list');">
-       <b><LABEL for="delegate_list">{t}Delegations{/t}</LABEL></b><br>
-       <select id="delegate_list" style="width:350px; height:100px;" name="delegate_list[]" size=15 multiple 
-               {if !$use_kolabDelegate }disabled{/if} >
-               {html_options values=$kolabDelegate output=$kolabDelegate}
-               <option disabled>&nbsp;</option>
-       </select>
-   <br>
-   <input name="delegate_address" size=30 align=middle maxlength=60 value="" id="delegate_address">
-   <input type=submit value="{t}Add{/t}" name="add_delegation" id="add_delegation">&nbsp;
-   <input type=submit value="{t}Delete{/t}" name="delete_delegation" id="delete_delegation">
-
-{else}
-   <b><LABEL for="delegate_list">{t}Delegations{/t}</LABEL></b><br>
-       {render acl=$kolabDelegateACL}
-          <select id="delegate_list" style="width:350px; height:100px;" name="delegate_list[]" size=15 multiple 
-                {if !$kolabState }disabled{/if} >
-               {html_options values=$kolabDelegate output=$kolabDelegate}
-               <option disabled>&nbsp;</option>
-          </select>
-       {/render}
-          <br>
-       {render acl=$kolabDelegateACL}
-          <input name="delegate_address" size=30 align=middle maxlength=60 {if !$kolabState} disabled {/if} value="" id="delegate_address">
-       {/render}
-       {render acl=$kolabDelegateACL}
-          <input type=submit value="{t}Add{/t}" name="add_delegation" {if !$kolabState} disabled {/if} id="add_delegation">&nbsp;
-       {/render}
-       {render acl=$kolabDelegateACL}
-          <input type=submit value="{t}Delete{/t}" name="delete_delegation" {if !$kolabState} disabled {/if} id="delete_delegation">
-       {/render}
-{/if}
-
-    <h2>{t}Mail size{/t}</h2>
-{render acl=$unrestrictedMailSizeACL checkbox=$multiple_support checked=$use_unrestrictedMailSize}
-     &nbsp;<input class="center" type="checkbox" id='unrestrictedMailSize' name="unrestrictedMailSize" value="1" 
-               {if !$kolabState && !$multiple_support} disabled {/if} {$unrestrictedMailSizeState}> 
-       {t}No mail size restriction for this account{/t}
-{/render}
-  </td>
-  <td rowspan=2 style="border-left:1px solid #A0A0A0">
-   &nbsp;
-  </td>
-  <td style="vertical-align:top;">
-
- <h2>{t}Free Busy information{/t}</h2>
- <table summary="">
-  <tr>
-   <td><LABEL for="calFBURL">{t}URL{/t}</LABEL></td>
-   <td>
-{render acl=$calFBURLACL checkbox=$multiple_support checked=$use_calFBURL}
-   <input id="calFBURL" name="calFBURL" size=30 maxlength=60 value="{$calFBURL}" 
-       {if !$kolabState && !$multiple_support} disabled {/if}>
-{/render}
-   </td>
-  </tr>
-  <tr>
-  <td><LABEL for="kolabFreeBusyFuture">{t}Future{/t}</LABEL></td>
-  <td>
-{render acl=$kolabFreeBusyFutureACL checkbox=$multiple_support checked=$use_kolabFreeBusyFuture}
-   <input id="kolabFreeBusyFuture" name="kolabFreeBusyFuture" size=5 maxlength=6 
-       {if !$kolabState && !$multiple_support} disabled {/if} value="{$kolabFreeBusyFuture}" > 
-       {t}days{/t}
-{/render}
-   </td>
-  </tr>
- </table>
-
-
-<h2>{t}Invitation policy{/t}</h2>
-{if $multiple_support}
-<input type="checkbox" name="use_kolabInvitationPolicy" {if $use_kolabInvitationPolicy} checked {/if} value="1" class="center">
-{/if}
-{render acl=$kolabInvitationPolicyACL}
- <table summary="">
-   {$invitation}
- </table>
-{/render}
-
-
-  </td>
- </tr>
-</table>
-
-{/if}
diff --git a/gosa-plugins/kolab/personal/connectivity/class_kolabAccount.inc b/gosa-plugins/kolab/personal/connectivity/class_kolabAccount.inc
new file mode 100644 (file)
index 0000000..a9149d4
--- /dev/null
@@ -0,0 +1,602 @@
+<?php
+class kolabAccount extends plugin
+{
+  /* Definitions */
+  var $plHeadline       = "Kolab";
+  var $plDescription    = "This does something";
+
+  /* Kolab attributes */
+  var $kolabInvitationPolicy  = array();
+  var $kolabFreeBusyFuture    = 60;
+  var $unrestrictedMailSize   = 0;
+  var $calFBURL               = "";
+  var $kolabDelegate          = array();
+
+  /* attribute list for save action */
+  var $attributes     = array("kolabFreeBusyFuture", "unrestrictedMailSize", "calFBURL","kolabDelegate","kolabInvitationPolicy");
+  var $objectclasses  = array("kolabInetOrgPerson");
+
+  /* Helper */
+  var $imapping     = array();
+  var $mail_Account = false;
+  var $ReadOnly     = false;
+  var $view_logged  = FALSE;
+  var $uid          = "";
+
+  var $multiple_support = TRUE;
+
+
+  /*! \brief Initialize Plugin 
+      @param  $config   GOsa configuration object
+      @param  $dn       DN of the currently edited object
+      @param  $parent   The parent object, used to fetch Attributes.
+   */
+  function kolabAccount (&$config, $dn= NULL,$parent = NULL)
+  {
+    plugin::plugin ($config, $dn, $parent);
+
+    /* Setting uid to default */
+    if(isset($this->attrs['uid'][0])){
+      $this->uid = $this->attrs['uid'][0];
+    }
+
+    /* Pull arrays */
+    foreach(array("kolabDelegate", "kolabInvitationPolicy") as $attr){
+      if (isset($this->attrs["$attr"]["count"])){
+        $tmp = array();
+        for ($i= 0; $i<$this->attrs["$attr"]["count"]; $i++){
+          $tmp[]=$this->attrs["$attr"][$i];
+        }
+        $this->$attr = $tmp;
+      }
+    }
+
+    /* If this one is empty, preset with ACT_MANUAL for anonymous users */
+    if (count ($this->kolabInvitationPolicy) == 0){
+       $this->kolabInvitationPolicy= array("ACT_MANUAL");
+    }
+
+    /* Check is account state */
+    $this->is_account = false;
+    if(count($this->kolabDelegate)){
+      $this->is_account = true;
+    }
+    foreach(array("calFBURL","unrestrictedMailSize") as $attr){
+      if(!empty($this->$attr)){
+        $this->is_account = true;
+      }
+    } 
+
+    /* Transfer account states for this union */
+    if (isset($this->parent->by_object['mailAccount']) && $this->parent->by_object['mailAccount']->is_account){
+      $this->mail_Account = true;
+     }elseif( isset($this->attrs) && isset($this->attrs['kolabHomeServer'])){
+       $this->mail_Account= true;
+     }else{
+       $this->is_account  = false;
+      $this->mail_Account = false;
+    }
+  }
+
+    
+  /*! \brief Create thml output 
+   */
+  function execute()
+  {
+         /* Call parent execute */
+       plugin::execute();
+
+    /* Log view */
+    if($this->is_account && !$this->view_logged){
+      $this->view_logged = TRUE;
+      new log("view","users/".get_class($this),$this->dn);
+    }
+
+    /* Show tab dialog headers */
+    $display= "";
+
+    /* Show main page */
+    $smarty= get_smarty();
+
+    /* Load attributes */
+    foreach($this->attributes as $val){
+      $smarty->assign("$val", $this->$val);
+    }
+
+    $tmp = $this->plInfo();
+    foreach($tmp['plProvidedAcls'] as $acl => $description){
+      $smarty->assign($acl."ACL",$this->getacl($acl,$this->ReadOnly));
+      $smarty->assign($acl."_W", $this->acl_is_writeable($acl,$this->ReadOnly));
+    }
+    $smarty->assign("is_account" ,  $this->is_account); 
+
+    if($this->ReadOnly){
+      $smarty->assign("is_removeable",false); 
+      $smarty->assign("is_createable",false); 
+    }else{
+      $smarty->assign("is_removeable",$this->acl_is_removeable()); 
+      $smarty->assign("is_createable",$this->acl_is_createable()); 
+    }
+
+    /* Check for invitation action */
+    $nr= 0;
+  
+    foreach($_POST as $name => $value){
+      if(preg_match("/add_inv_/",$name)){
+        $this->kolabInvitationPolicy[]= ": ACT_MANUAL";
+      }
+    }
+    foreach($_POST as $name => $value){
+      if(preg_match("/del_inv_/",$name)){
+
+        $id = preg_replace("/del_inv_/","",$name);
+        $id = preg_replace("/_(x|y)$/","",$id);
+  
+        $new= array();
+        foreach ($this->kolabInvitationPolicy as $entry){
+          if (!preg_match("/^".$this->imapping[$id].":/", $entry)){
+            $new[]= $entry;
+          }
+        }
+        $this->kolabInvitationPolicy= $new;
+      }
+    }
+
+    /* Unify addresses */
+    $new= array();
+    foreach($this->kolabInvitationPolicy as $value){
+      $address= preg_replace('/^([^:]+:).*$/', '\1', $value);
+      $new[$address]= $value;
+    }
+    $this->kolabInvitationPolicy= array();
+    foreach($new as $value){
+      $this->kolabInvitationPolicy[]= $value;
+    }
+
+    /* Add delegation */
+    if (isset($_POST['add_delegation'])){
+      if ($_POST['delegate_address'] != ""){
+
+        /* Valid email address specified? */
+        $address= $_POST['delegate_address'];
+        $valid= FALSE;
+        if (!tests::is_email($address)){
+          if (!tests::is_email($address, TRUE)){
+              msg_dialog::display(_("Error"), _("Cannot add invalid mail address!"), ERROR_DIALOG);
+          }
+        } else {
+
+          $ldap= $this->config->get_ldap_link();
+          $ldap->cd ($this->config->current['BASE']);
+          $ldap->search('(mail='.$address.')',array("mail"));
+          if ($ldap->count() == 0){
+            msg_dialog::display(_("Error"), _("Primary mail address already in use by another user!"), ERROR_DIALOG);
+          } else {
+            $valid= TRUE;
+          }
+        }
+
+        if ($valid){
+          /* Add it */
+          if ($this->acl_is_writeable("kolabDelegate")){
+            $this->addDelegate ($address);
+            $this->is_modified= TRUE;
+          }
+
+        }
+      }
+    }
+
+    /* Delete forward email addresses */
+    if ((isset($_POST['delete_delegation'])) && (isset($_POST['delegate_list']))){
+      if (count($_POST['delegate_list']) && $this->acl_is_writeable("kolabDelegate")){
+        $this->delDelegate ($_POST['delegate_list']);
+      }
+    }
+
+    /* Assemble policies */
+    $policies= array( 'ACT_ALWAYS_ACCEPT'       => _("Always accept"),
+                      'ACT_ALWAYS_REJECT'       => _("Always reject"),
+                      'ACT_REJECT_IF_CONFLICTS' => _("Reject if conflicts"),
+                      'ACT_MANUAL_IF_CONFLICTS' => _("Manual if conflicts"),
+                      'ACT_MANUAL'              => _("Manual"));
+    $smarty->assign('policies', $policies);
+
+    /* Adjust checkbox */
+    if ($this->unrestrictedMailSize){
+      $smarty->assign('unrestrictedMailSizeState', "checked");
+    } else {
+      $smarty->assign('unrestrictedMailSizeState', "");
+    }
+
+    /* Transfer delegation list */
+    if (!count($this->kolabDelegate)){
+      /* Smarty will produce <option value=""></option> and tidy don't like that, so tell smarty to create no option (array();)*/
+      $smarty->assign("kolabDelegate", array());
+    } else {
+      $smarty->assign("kolabDelegate", $this->kolabDelegate);
+    }
+
+    $smarty->assign("mail_account",$this->mail_Account);
+
+    /* Create InvitationPolicy table */
+    $invitation= "";
+    $this->imapping= array();
+    $nr= 0;
+    $changeState  = "";
+    foreach ($this->kolabInvitationPolicy as $entry){
+
+      if($this->acl_is_writeable("kolabInvitationPolicy")){
+        $changeState .= "changeState('address".$nr."'); \n changeState('policy".$nr."'); \n
+          changeState('add".$nr."'); \n changeState('remove".$nr."'); \n";
+      }
+
+      if(!$this->acl_is_writeable("kolabInvitationPolicy") && !$this->multiple_support_active){
+        $dis = " disabled ";
+      }else{
+        if($this->is_account || $this->multiple_support_active){
+          $dis = " ";
+        }else{
+          $dis = " disabled ";
+        }
+      }
+      $invitation.= "<tr><td>";
+
+      if(!$this->acl_is_readable("kolabInvitationPolicy"))    {
+      }
+
+      /* The default entry does not have colons... */
+      if (!preg_match('/:/', $entry)){
+        $invitation.= _("Anonymous");
+        $name= "";
+        $mode= $entry;
+      } else {
+        $name= preg_replace('/:.*$/', '', $entry);
+        $mode= preg_replace('/^[^:]*: */', '', $entry);
+
+        if(!$this->acl_is_readable("kolabInvitationPolicy")){
+          $name='';
+        }
+        $invitation.= "<input name=\"address$nr\" size=16 maxlength=60  value=\"$name\" id='address".$nr."' ".$dis.">";
+      }
+      $invitation.= "</td>";
+
+      /* Add mode switch */
+      $invitation.= "<td><select size=\"1\" name=\"policy$nr\" id='policy".$nr."' ".$dis.">";
+      foreach($policies as $key => $value){
+        if ($key == $mode){
+          $invitation.= "<option value=\"$key\" selected>$value</option>";
+        } else {
+          $invitation.= "<option value=\"$key\">$value</option>";
+        }
+      }
+      
+      /* Assign buttons */
+      $button= "";
+      if ($nr == count($this->kolabInvitationPolicy)-1){
+        $button= "<input type='image' name=\"add_inv_".$nr."\" src='images/list_new.png' id='add".$nr."' ".$dis.">";
+      }
+      if ($nr != 0) {
+        $button.= "<input type='image' name=\"del_inv_".$nr."\" src='images/edittrash.png' id='remove".$nr."' ".$dis.">";
+      }
+      
+      $invitation.= "</select>&nbsp;</td>
+                    <td>$button</td>
+                  </tr>\n";
+      $this->imapping[$nr]= $name;
+      $nr++;
+    }
+    $smarty->assign("invitation", $invitation);
+    $smarty->assign("changeState", $changeState);
+    $smarty->assign("kolabState",$this->is_account);
+
+  
+    $smarty->assign("multiple_support",$this->multiple_support_active);
+    foreach($this->attributes as $attr){
+      $smarty->assign("use_".$attr,in_array($attr,$this->multi_boxes));
+    }
+    foreach(array("kolabState") as $attr){
+      $smarty->assign("use_".$attr,in_array($attr,$this->multi_boxes));
+    }
+
+    if($this->multiple_support_active){
+    }
+
+
+    $display.= $smarty->fetch (get_template_path('kolab.tpl', TRUE, dirname(__FILE__)));
+    return ($display);
+  }
+
+  function remove_from_parent()
+  {
+    if(!$this->initially_was_account){
+      return;
+    }
+  
+    /* Optionally execute a command after we're done */
+    plugin::remove_from_parent();
+    
+    if(!in_array("kolabInetOrgPerson",$this->attrs['objectClass'])){
+      $this->attrs['objectClass'][] = "kolabInetOrgPerson";
+    }
+
+    $ldap = $this->config->get_ldap_linK(); 
+    $ldap->cd($this->config->current['BASE']);
+    $ldap->cd ($this->dn);
+    $ldap->modify($this->attrs);
+
+    /* Log last action */
+    new log("remove","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
+
+    $this->handle_post_events('remove',array("uid" => $this->uid));
+    show_ldap_error($ldap->get_error(), sprintf(_("Removing of user/kolab account with dn '%s' failed."),$this->dn));
+  }
+
+
+  function check()
+  {
+    /* Call common method to give check the hook */
+    $message= plugin::check();
+
+    /* FBFuture is in days... */
+    if ($this->kolabFreeBusyFuture != "" && !preg_match('/^[0-9]+$/', $this->kolabFreeBusyFuture)){
+      $message[]= _("The value specified as Free Busy future needs to be an integer.");
+    }
+
+    /* Check for URL scheme... */
+    if(!empty($this->calFBURL) && !preg_match("/http+(s)*:\/\//",$this->calFBURL)){
+      $message[]= _("The value specified as Free Busy Information URL is invalid.");
+    }
+
+    /* Check invitation policy for existing mail addresses */
+    foreach($this->kolabInvitationPolicy as $policy){
+      
+      /* Ignore anonymous string */
+      if (!preg_match('/:/', $policy)){
+        continue;
+      }
+      
+      $address= preg_replace('/^([^:]+).*$/', '\1', $policy);
+      if (!tests::is_email($address)){
+        if (!tests::is_email($address, TRUE)){
+          $message[]= sprintf(_("The invitation policy entry for address '%s' is not valid."), $address);
+        }
+      } else {
+
+        $ldap= $this->config->get_ldap_link();
+        $ldap->cd ($this->config->current['BASE']);
+        $ldap->search('(mail='.$address.')',array("mail"));
+        if ($ldap->count() == 0){
+          $message[]= sprintf(_("There's no mail user with address '%s' for your invitation policy!"), $address);
+        } else {
+          $valid= TRUE;
+        }
+      }
+    }
+
+    return ($message);
+  }
+
+  /* Save data to object */
+  function save_object()
+  {
+    /* Do we need to flip is_account state? */
+    if (isset($_POST['connectivityTab'])){
+
+      if(isset($_POST["kolabState"])){
+        if($this->acl_is_createable()){
+          $this->is_account = true;
+        }
+      }else{
+        if($this->acl_is_removeable()){
+          $this->is_account = false;
+        }
+      }
+      if ($this->acl_is_writeable("unrestrictedMailSize")){
+        if (isset($_POST['unrestrictedMailSize']) && $_POST['unrestrictedMailSize'] == 1){
+          $this->unrestrictedMailSize= 1;
+        } else {
+          $this->unrestrictedMailSize= 0;
+        }
+      }
+    }
+
+    plugin::save_object();
+
+    /* Save changes done in invitation policies */
+    if($this->acl_is_writeable("kolabInvitationPolicy")){
+
+      $nr= 0;
+      $this->kolabInvitationPolicy= array();
+      while (isset($_POST["policy$nr"])){
+
+        /* Anonymous? */
+        if (!isset($_POST["address$nr"])){
+          $this->kolabInvitationPolicy[]= $_POST["policy$nr"];
+        } else {
+          $this->kolabInvitationPolicy[]= $_POST["address$nr"].": ".$_POST["policy$nr"];
+        }
+
+        $nr++;
+      }
+
+      /* If this one is empty, preset with ACT_MANUAL for anonymous users */
+      if (count ($this->kolabInvitationPolicy) == 0){
+        $this->kolabInvitationPolicy= array("ACT_MANUAL");
+      }
+    }
+  }
+
+
+  /* Save to LDAP */
+  function save()
+  {
+    /* Check mailmethod before doing something useful */
+    plugin::save();
+
+    /* Transfer arrays */
+    $this->attrs['kolabDelegate']= $this->kolabDelegate;
+    $this->attrs['kolabInvitationPolicy']= $this->kolabInvitationPolicy;
+
+    /* unrestrictedMailSize is boolean */
+    if($this->attrs['unrestrictedMailSize']){
+      $this->attrs['unrestrictedMailSize'] = "TRUE";
+    }else{
+      $this->attrs['unrestrictedMailSize'] = "FALSE";
+    }
+  
+    /* Write back to ldap */
+    $ldap= $this->config->get_ldap_link();
+    $ldap->cd($this->dn);
+    $this->cleanup();
+    $ldap->modify ($this->attrs); 
+
+    /* Log last action */
+    if($this->initially_was_account){
+      new log("modify","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
+    }else{
+      new log("create","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
+    }
+
+    show_ldap_error($ldap->get_error(), sprintf(_("Saving of user/kolab account with dn '%s' failed."),$this->dn));
+
+    /* Optionally execute a command after we're done */
+    if ($this->initially_was_account == $this->is_account){
+      if ($this->is_modified){
+        $this->handle_post_events("modify",array("uid" => $this->uid));
+      }
+    } else {
+      $this->handle_post_events("add",array("uid" => $this->uid));
+    }
+  }
+
+
+  /* Add entry to delegation list */
+  function addDelegate($address)
+  {
+    $this->kolabDelegate[]= $address;
+    $this->kolabDelegate= array_unique ($this->kolabDelegate);
+
+    sort ($this->kolabDelegate);
+    reset ($this->kolabDelegate);
+    $this->is_modified= TRUE;
+  }
+
+  function delDelegate($addresses)
+  {
+    $this->kolabDelegate= array_remove_entries ($addresses, $this->kolabDelegate);
+    $this->is_modified= TRUE;
+  }
+
+
+  /* Return plugin informations for acl handling  */
+  static function plInfo()
+  {
+    return (array(     
+          "plShortName"     => _("Kolab"),
+          "plDescription"   => _("Kolab account settings")."&nbsp;:&nbsp;<u>"._("Connectivity addon")."</u>",
+          "plSelfModify"    => TRUE,
+          "plDepends"       => array("user"),
+          "plPriority"      => 20,                                 // Position in tabs
+          "plSection"     => array("personal" => _("My account")),
+          "plCategory"    => array("users"),
+          "plOptions"       => array(),
+
+          "plProvidedAcls"  => array(
+            "kolabFreeBusyFuture"   => _("Free busy future"),
+            "unrestrictedMailSize"  => _("Mail size restriction"),
+            "calFBURL"              => _("Free busy information"),
+            "kolabDelegate"         => _("Delegations"),
+            "kolabInvitationPolicy" => _("Invitation policy"))
+          ));
+  }
+
+
+  /*! \brief  Enable multiple edit support. \
+              Also sets $this->mail_account to TRUE, which simulates \
+              a valid mail extension.
+   */
+  public function enable_multiple_support()
+  {
+    plugin::enable_multiple_support();
+    $this->mail_Account = TRUE;
+  }
+
+
+  /*! \brief  Save html POSTs in multiple edit.
+   */
+  public function multiple_save_object()
+  {
+    if (isset($_POST['connectivityTab'])){
+      plugin::multiple_save_object();
+      if(isset($_POST['use_kolabState'])){
+        $this->multi_boxes[] = "kolabState";
+      }
+      $this->save_object();
+    }
+  }
+
+
+  /*! \brief  Returns all modified values. \
+              All selected an modified values will be returned \
+              in an array.
+      @return array   Returns an array containing all attribute modifications  
+   */
+  public function get_multi_edit_values()
+  {
+    $ret = plugin::get_multi_edit_values();
+    if(in_array("kolabState",$this->multi_boxes)){
+      $ret['is_account'] = $this->is_account;
+    }
+
+    print_a($ret);
+  
+    return($ret);
+  }
+
+  /*! \brief  Sets modified attributes in mutliple edit. \
+              All collected values from "get_multi_edit_values()" \
+              will be applied to this plugin.
+      @param  array   An array containing modified attributes returned by get_multi_edit_values();
+   */
+  public function set_multi_edit_values($values)
+  {
+    plugin::set_multi_edit_values($values);
+    if(isset($values['is_account'])){
+      $this->is_account = $values['is_account'];
+    }
+  }
+
+
+  /*! \brief  Initialize multiple edit ui for this plugin. \
+              This function sets plugin defaults in multiple edit.
+      @param  array   Attributes used in all object 
+      @param  array   All used attributes.
+   */
+  public function init_multiple_support($attrs,$all)
+  {
+    plugin::init_multiple_support($attrs,$all);
+    if(isset($attrs['objectClass']) && in_array("kolabInetOrgPerson",$attrs['objectClass'])){
+      $this->is_account = TRUE;
+    }
+
+    /* Pull arrays */
+    foreach(array("kolabDelegate", "kolabInvitationPolicy") as $attr){
+      if (isset($this->multi_attrs["$attr"]["count"])){
+        $tmp = array();
+        for ($i= 0; $i<$this->multi_attrs["$attr"]["count"]; $i++){
+          $tmp[]=$this->multi_attrs["$attr"][$i];
+        }
+        $this->$attr = $tmp;
+      }
+    }
+
+    /* If this one is empty, preset with ACT_MANUAL for anonymous users */
+    if (count ($this->kolabInvitationPolicy) == 0){
+       $this->kolabInvitationPolicy= array("ACT_MANUAL");
+    }
+  }
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/kolab/personal/connectivity/kolab.tpl b/gosa-plugins/kolab/personal/connectivity/kolab.tpl
new file mode 100644 (file)
index 0000000..c05bfb1
--- /dev/null
@@ -0,0 +1,134 @@
+
+{if !$mail_account}
+       <h2>{t}Kolab account{/t}</h2>
+       {t}The kolab account is currently disabled. It's features can be adjusted if you add a mail account.{/t}
+{else}
+
+<h2>
+{if $multiple_support}
+
+<input type="checkbox" name="use_kolabState" value="1" {if $use_kolabState} checked {/if}
+       class="center" onClick="changeState('kolabState');">
+<input type="checkbox" id="kolabState" name="kolabState" value="1" {if $kolabState} checked {/if}
+    class="center" {if  !$use_kolabState} disabled {/if}>
+
+{else}
+<input type="checkbox" id="kolabState" name="kolabState" value="1" {if $kolabState} checked {/if}
+       class="center" 
+       {if (!$is_account && $is_createable) || ($is_account && $is_removeable)}
+       {else}
+               disabled        
+       {/if}
+       onClick="
+       {if $kolabDelegate_W}
+       changeState('delegate_list');
+       changeState('delegate_address');
+       changeState('add_delegation');
+       changeState('delete_delegation');
+       {/if}
+       {if $unrestrictedMailSize_W}
+       changeState('unrestrictedMailSize');
+       {/if}
+       {if $calFBURL_W}
+       changeState('calFBURL');
+       {/if}
+       {if $kolabFreeBusyFuture_W}
+       changeState('kolabFreeBusyFuture');
+       {/if}
+       {if $kolabInvitationPolicy_W}
+       {$changeState}
+       {/if}">
+{/if}
+
+{t}Kolab account{/t}</h2>
+<table summary="" style="width:100%">
+ <tr>
+  <td style="width:50%; vertical-align:top;">
+
+{if $multiple_support}
+       <input type="checkbox" name="use_kolabDelegate" {if $use_kolabDelegate} checked {/if}
+               class="center" onClick="changeState('delegate_list');">
+       <b><LABEL for="delegate_list">{t}Delegations{/t}</LABEL></b><br>
+       <select id="delegate_list" style="width:350px; height:100px;" name="delegate_list[]" size=15 multiple 
+               {if !$use_kolabDelegate }disabled{/if} >
+               {html_options values=$kolabDelegate output=$kolabDelegate}
+               <option disabled>&nbsp;</option>
+       </select>
+   <br>
+   <input name="delegate_address" size=30 align=middle maxlength=60 value="" id="delegate_address">
+   <input type=submit value="{t}Add{/t}" name="add_delegation" id="add_delegation">&nbsp;
+   <input type=submit value="{t}Delete{/t}" name="delete_delegation" id="delete_delegation">
+
+{else}
+   <b><LABEL for="delegate_list">{t}Delegations{/t}</LABEL></b><br>
+       {render acl=$kolabDelegateACL}
+          <select id="delegate_list" style="width:350px; height:100px;" name="delegate_list[]" size=15 multiple 
+                {if !$kolabState }disabled{/if} >
+               {html_options values=$kolabDelegate output=$kolabDelegate}
+               <option disabled>&nbsp;</option>
+          </select>
+       {/render}
+          <br>
+       {render acl=$kolabDelegateACL}
+          <input name="delegate_address" size=30 align=middle maxlength=60 {if !$kolabState} disabled {/if} value="" id="delegate_address">
+       {/render}
+       {render acl=$kolabDelegateACL}
+          <input type=submit value="{t}Add{/t}" name="add_delegation" {if !$kolabState} disabled {/if} id="add_delegation">&nbsp;
+       {/render}
+       {render acl=$kolabDelegateACL}
+          <input type=submit value="{t}Delete{/t}" name="delete_delegation" {if !$kolabState} disabled {/if} id="delete_delegation">
+       {/render}
+{/if}
+
+    <h2>{t}Mail size{/t}</h2>
+{render acl=$unrestrictedMailSizeACL checkbox=$multiple_support checked=$use_unrestrictedMailSize}
+     &nbsp;<input class="center" type="checkbox" id='unrestrictedMailSize' name="unrestrictedMailSize" value="1" 
+               {if !$kolabState && !$multiple_support} disabled {/if} {$unrestrictedMailSizeState}> 
+       {t}No mail size restriction for this account{/t}
+{/render}
+  </td>
+  <td rowspan=2 style="border-left:1px solid #A0A0A0">
+   &nbsp;
+  </td>
+  <td style="vertical-align:top;">
+
+ <h2>{t}Free Busy information{/t}</h2>
+ <table summary="">
+  <tr>
+   <td><LABEL for="calFBURL">{t}URL{/t}</LABEL></td>
+   <td>
+{render acl=$calFBURLACL checkbox=$multiple_support checked=$use_calFBURL}
+   <input id="calFBURL" name="calFBURL" size=30 maxlength=60 value="{$calFBURL}" 
+       {if !$kolabState && !$multiple_support} disabled {/if}>
+{/render}
+   </td>
+  </tr>
+  <tr>
+  <td><LABEL for="kolabFreeBusyFuture">{t}Future{/t}</LABEL></td>
+  <td>
+{render acl=$kolabFreeBusyFutureACL checkbox=$multiple_support checked=$use_kolabFreeBusyFuture}
+   <input id="kolabFreeBusyFuture" name="kolabFreeBusyFuture" size=5 maxlength=6 
+       {if !$kolabState && !$multiple_support} disabled {/if} value="{$kolabFreeBusyFuture}" > 
+       {t}days{/t}
+{/render}
+   </td>
+  </tr>
+ </table>
+
+
+<h2>{t}Invitation policy{/t}</h2>
+{if $multiple_support}
+<input type="checkbox" name="use_kolabInvitationPolicy" {if $use_kolabInvitationPolicy} checked {/if} value="1" class="center">
+{/if}
+{render acl=$kolabInvitationPolicyACL}
+ <table summary="">
+   {$invitation}
+ </table>
+{/render}
+
+
+  </td>
+ </tr>
+</table>
+
+{/if}
diff --git a/gosa-plugins/kolab/personal/mail/class_mail-methods-golab.inc b/gosa-plugins/kolab/personal/mail/class_mail-methods-golab.inc
new file mode 100644 (file)
index 0000000..dc75674
--- /dev/null
@@ -0,0 +1,261 @@
+<?php
+/*
+   This code is part of GOsa (https://gosa.gonicus.de)
+   Copyright (C) 2004  Cajus Pollmeier
+
+   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 mailMethodGolab extends mailMethodCyrus
+{
+  var $mbox= "-";
+  var $config;
+  var $gosaMailServer= "";
+  var $uattrib= "mail";
+
+  var $attribute_map= array("gosaMailAlternateAddress"  =>  "alias",
+                            "gosaMailQuota"             =>  "cyrus-userquota",
+                            "gosaMailServer"            =>  "kolabHomeServer");
+
+  function mailMethodGolab(&$config)
+  {
+    $this->config= $config->data['SERVERS']['IMAP'];
+  }
+
+  function updateMailbox($folder)
+  {
+  }
+
+  function setQuota($folder, $gosaMailQuota)
+  {
+    return (TRUE);
+  }
+
+  /* Get quota and divide it by 1024, because in gosa we display in MB
+      but we get Kb */
+  function getQuota($folder)
+  {
+    $result= array('quotaUsage' => '', 'gosaMailQuota' => '');
+
+    /* Only use lower case folder names, if folder name is like "@domain.com" */
+    if(preg_match("/@/",$folder)){
+      $folder = strtolower($folder);
+    }
+
+    error_reporting(0);  
+  
+    /* Load quota settings */
+    $quota_value = @imap_get_quota($this->mbox, $folder);
+    if(is_array($quota_value)) {
+      if (isset($quota_value["STORAGE"]) && is_array($quota_value["STORAGE"])){
+        /* use for PHP >= 4.3 */
+        $result['quotaUsage']=    (int) ($quota_value["STORAGE"]['usage'] / 1024);
+        $result['gosaMailQuota']= (int) ($quota_value["STORAGE"]['limit'] / 1024);
+      } else {
+        /* backward icompatible */
+        $result['quotaUsage']=    (int) ($quota_value['usage'] / 1024);
+        $result['gosaMailQuota']= (int) ($quota_value['limit'] / 1024);
+      }
+    }elseif(!$quota_value){
+      return(false);
+    }
+
+    error_reporting(E_ALL | E_STRICT); 
+    return ($result);
+  }
+
+
+  function fixAttributesOnLoad(&$mailObject)
+  {
+    /* Kolab shared folder names are like ' shared.uid@server.de ' 
+        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
+        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
+    if(get_class($mailObject) == "mailgroup"){
+     $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
+    }
+
+    /* Convert attributes and objectClasses */
+    foreach ($this->attribute_map as $dest => $source){
+      /* Hickert 11.11.05 : Alternate email addresses were saved, but not displayed again.
+      if (isset($mailObject->attrs[$source])){
+        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
+        unset ($mailObject->attrs[$source]);
+      */
+
+      if (isset($mailObject->attrs[$source])){
+        unset($mailObject->attrs[$source]['count']);
+        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
+        $mailObject->$dest=        $mailObject->attrs[$source];
+
+        unset ($mailObject->$dest['count']);
+        unset ($mailObject->attrs[$source]);
+      }
+    }
+
+    /* Adjust server name if needed */
+    foreach ($mailObject->config->data['SERVERS']['IMAP'] as $srv => $dummy){
+      if (preg_match("%".$mailObject->attrs['gosaMailServer'][0]."$%", $srv)){
+        $mailObject->attrs['gosaMailServer']= array(0 => $srv, "count" => 1);
+        break;
+      }
+    }
+  }
+
+
+  function fixAttributesOnStore(&$mailObject)
+  {
+    global $config;
+  
+    /* If quota is empty, remove quota restrictions by setting quota to 0 */
+    if(isset($mailObject->gosaMailQuota) && (empty($mailObject->gosaMailQuota))){
+      $mailObject->attrs['gosaMailQuota'] = 0;
+    }
+
+    /* Convert attributes and objectClasses */
+    foreach ($this->attribute_map as $source => $dest){
+      if (isset($mailObject->attrs[$source])){
+        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
+        unset ($mailObject->attrs[$source]);
+      }
+    }
+    $objectclasses= array();
+    foreach ($mailObject->attrs['objectClass'] as $oc){
+      if ($oc !=  'kolabInetOrgPerson' && $oc !=  'kolabSharedFolder'){
+        $objectclasses[]= $oc;
+      }
+    }
+    $mailObject->attrs['objectClass']= $objectclasses;
+    if (in_array("posixGroup", $mailObject->attrs['objectClass'])){
+  
+      /* Add kolabSharedFoleder Class */
+      $mailObject->attrs['objectClass'][]= 'kolabSharedFolder';
+
+      /* Work on acl attribute */
+      $new_acl= array();
+      foreach ($mailObject->attrs['acl'] as $uacl){
+
+        /* Get user=(mail) & acls  */
+        list($user, $acl) = split(" ", $uacl);
+      
+        /* Add al users which have seperated acls 
+           %members% are all users in this group, 
+           which have the standard group acl
+        */
+        if ($user != "%members%"){
+          $new_acl[$user]= $uacl;
+        } else {
+        
+          /* All groupmembers will be added */
+          $ldap = $config->get_ldap_link();
+          $ldap->cd($config->current['BASE']);
+          foreach ($mailObject->members as $member){
+
+            /* Get user mail address .... */
+            $ldap->search("(&(objectClass=person)(|(uid=".$member.")(mail=".$member.")))",array("mail"));
+            $res = $ldap->fetch();
+
+            /* Default mail address is set to uid - 
+               So if there is no mail address defined the uid is added 
+             */
+            $mail = $member;
+
+            /* Use mail address if it is available */
+            if(isset($res['mail'][0])){
+              $mail = $res['mail'][0];
+            }
+
+            /* only append this mail/permission string to acl,
+               if there arn't already some (special) configs for this user */
+            $found =false;
+            foreach($mailObject->imapacl as $mailA => $acl){
+              if(strtolower(trim($mailA))==strtolower(trim($mail))){
+                $found = true;
+              }
+            }
+
+            /* Skipp user, with no email adress too */     
+            if($member == $mail){
+              $found = true;
+            }
+   
+            /* Append new user acl */
+            if(!$found){
+              $new_acl[$member]= "$mail $acl";
+            }
+
+            /* Old line */
+            //  $new_acl[$member]= "$member $acl";
+          }
+        }
+      }
+      /* Save shared folder target */
+      $mailObject->attrs['gosaSharedFolderTarget']= "kolab+".$mailObject->mail;
+
+      /* Kolab shared folder names are like ' shared.uid@server.de ' 
+        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
+        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
+      $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
+  
+      /* Assign new acls */
+      $mailObject->attrs['acl']= array();
+      foreach ($new_acl as $key => $value){
+        $mailObject->attrs['acl'][]= $value;
+      }
+    } else {
+      $mailObject->attrs['objectClass'][]= 'kolabInetOrgPerson';
+    }
+
+    /* Remove imap:// tagging */
+    $mailObject->attrs['kolabHomeServer']= preg_replace('%imap://%', '', $mailObject->attrs['kolabHomeServer']);
+    $mailObject->attrs['gosaMailServer']= $mailObject->attrs['kolabHomeServer'];
+    $mailObject->attrs['kolabDeleteFlag']= array();
+  }
+
+  function fixAttributesOnRemove(&$mailObject)
+  {
+    /* Add attribute for object deletion and remove GOsa specific
+       values from entry. */
+    foreach($this->attribute_map as $kolabAttr){
+      $mailObject->attrs[$kolabAttr] = array();
+    }  
+
+    /* Only add kolab delete Flag in case of an user.mailAccount */
+    if(!in_array("posixGroup", $mailObject->attrs['objectClass'])){
+      $mailObject->attrs['kolabDeleteFlag']= preg_replace('%imap://%', '', $mailObject->gosaMailServer);
+    }else{
+      /* Kolab shared folder names are like ' shared.uid@server.de ' 
+        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
+        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
+      $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
+      
+    }
+  }
+
+
+  function deleteMailbox($folder)
+  {
+    /* Remove shared folders and skip removing users. 
+       KolabD is not able to remove shared folders yet, so we do it instead */
+    if(!(preg_match("/^user\//",$folder))){
+      return mailMethodCyrus::deleteMailbox($folder);
+    }
+    return (TRUE);
+  }
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/kolab/personal/mail/class_mail-methods-kolab.inc b/gosa-plugins/kolab/personal/mail/class_mail-methods-kolab.inc
new file mode 100644 (file)
index 0000000..c060604
--- /dev/null
@@ -0,0 +1,267 @@
+<?php
+/*
+   This code is part of GOsa (https://gosa.gonicus.de)
+   Copyright (C) 2004  Cajus Pollmeier
+
+   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 mailMethodKolab extends mailMethodCyrus
+{
+  var $mbox= "-";
+  var $config;
+  var $gosaMailServer= "";
+  var $uattrib= "mail";
+
+  var $attribute_map= array("gosaMailAlternateAddress"  =>  "alias",
+                            "gosaMailQuota"             =>  "cyrus-userquota",
+                            "gosaMailServer"            =>  "kolabHomeServer");
+
+  function mailMethodKolab(&$config)
+  {
+    $this->config= $config->data['SERVERS']['IMAP'];
+  }
+
+  function updateMailbox($folder)
+  {
+  }
+
+  function setQuota($folder, $gosaMailQuota)
+  {
+    return (TRUE);
+  }
+
+  /* Get quota and divide it by 1024, because in gosa we display in MB
+      but we get Kb */
+  function getQuota($folder)
+  {
+    $result= array('quotaUsage' => '', 'gosaMailQuota' => '');
+
+    /* Only use lower case folder names, if folder name is like "@domain.com" */
+    if(preg_match("/@/",$folder)){
+      $folder = strtolower($folder);
+    }
+
+    error_reporting(0);  
+  
+    /* Load quota settings */
+    $quota_value = @imap_get_quota($this->mbox, $folder);
+    if(is_array($quota_value)) {
+      if (isset($quota_value["STORAGE"]) && is_array($quota_value["STORAGE"])){
+        /* use for PHP >= 4.3 */
+        $result['quotaUsage']=    (int) ($quota_value["STORAGE"]['usage'] / 1024);
+        $result['gosaMailQuota']= (int) ($quota_value["STORAGE"]['limit'] / 1024);
+      } else {
+        /* backward icompatible */
+        $result['quotaUsage']=    (int) ($quota_value['usage'] / 1024);
+        $result['gosaMailQuota']= (int) ($quota_value['limit'] / 1024);
+      }
+    }elseif(!$quota_value){
+      return(false);
+    }
+
+    error_reporting(E_ALL | E_STRICT); 
+    return ($result);
+  }
+
+
+  function fixAttributesOnLoad(&$mailObject)
+  {
+    /* Kolab shared folder names are like ' shared.uid@server.de ' 
+        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
+        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
+    if(get_class($mailObject) == "mailgroup"){
+     $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
+    }
+
+    /* Convert attributes and objectClasses */
+    foreach ($this->attribute_map as $dest => $source){
+      /* Hickert 11.11.05 : Alternate email addresses were saved, but not displayed again.
+      if (isset($mailObject->attrs[$source])){
+        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
+        unset ($mailObject->attrs[$source]);
+      */
+
+      if (isset($mailObject->attrs[$source])){
+        unset($mailObject->attrs[$source]['count']);
+        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
+        $mailObject->$dest=        $mailObject->attrs[$source];
+
+        /* Ensure that cleanup will recognize the ampped attributes too */
+        if(isset($mailObject->saved_attributes)){
+          $mailObject->saved_attributes[$dest] = $mailObject->attrs[$source];
+          $mailObject->saved_attributes[$source] = $mailObject->attrs[$source];
+        }       
+
+        unset ($mailObject->$dest['count']);
+        unset ($mailObject->attrs[$source]);
+      }
+    }
+
+    /* Adjust server name if needed */
+    foreach ($mailObject->config->data['SERVERS']['IMAP'] as $srv => $dummy){
+      if (preg_match("%".$mailObject->attrs['gosaMailServer'][0]."$%", $srv)){
+        $mailObject->attrs['gosaMailServer']= array(0 => $srv, "count" => 1);
+        break;
+      }
+    }
+  }
+
+
+  function fixAttributesOnStore(&$mailObject)
+  {
+    global $config;
+  
+    /* If quota is empty, remove quota restrictions by setting quota to 0 */
+    if(isset($mailObject->gosaMailQuota) && (empty($mailObject->gosaMailQuota))){
+      $mailObject->attrs['gosaMailQuota'] = 0;
+    }
+
+    /* Convert attributes and objectClasses */
+    foreach ($this->attribute_map as $source => $dest){
+      if (isset($mailObject->attrs[$source])){
+        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
+        unset ($mailObject->attrs[$source]);
+      }
+    }
+    $objectclasses= array();
+    foreach ($mailObject->attrs['objectClass'] as $oc){
+      if ($oc !=  'kolabInetOrgPerson' && $oc !=  'kolabSharedFolder'){
+        $objectclasses[]= $oc;
+      }
+    }
+    $mailObject->attrs['objectClass']= $objectclasses;
+    if (in_array("posixGroup", $mailObject->attrs['objectClass'])){
+  
+      /* Add kolabSharedFoleder Class */
+      $mailObject->attrs['objectClass'][]= 'kolabSharedFolder';
+
+      /* Work on acl attribute */
+      $new_acl= array();
+      foreach ($mailObject->attrs['acl'] as $uacl){
+
+        /* Get user=(mail) & acls  */
+        list($user, $acl) = split(" ", $uacl);
+      
+        /* Add al users which have seperated acls 
+           %members% are all users in this group, 
+           which have the standard group acl
+        */
+        if ($user != "%members%"){
+          $new_acl[$user]= $uacl;
+        } else {
+        
+          /* All groupmembers will be added */
+          $ldap = $config->get_ldap_link();
+          $ldap->cd($config->current['BASE']);
+          foreach ($mailObject->members as $member){
+
+            /* Get user mail address .... */
+            $ldap->search("(&(objectClass=person)(|(uid=".$member.")(mail=".$member.")))",array("mail"));
+            $res = $ldap->fetch();
+
+            /* Default mail address is set to uid - 
+               So if there is no mail address defined the uid is added 
+             */
+            $mail = $member;
+
+            /* Use mail address if it is available */
+            if(isset($res['mail'][0])){
+              $mail = $res['mail'][0];
+            }
+
+            /* only append this mail/permission string to acl,
+               if there arn't already some (special) configs for this user */
+            $found =false;
+            foreach($mailObject->imapacl as $mailA => $acl){
+              if(strtolower(trim($mailA))==strtolower(trim($mail))){
+                $found = true;
+              }
+            }
+
+            /* Skipp user, with no email adress too */     
+            if($member == $mail){
+              $found = true;
+            }
+   
+            /* Append new user acl */
+            if(!$found){
+              $new_acl[$member]= "$mail $acl";
+            }
+
+            /* Old line */
+            //  $new_acl[$member]= "$member $acl";
+          }
+        }
+      }
+      /* Save shared folder target */
+      $mailObject->attrs['gosaSharedFolderTarget']= "kolab+shared.".$mailObject->mail;
+
+      /* Kolab shared folder names are like ' shared.uid@server.de ' 
+        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
+        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
+      $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
+  
+      /* Assign new acls */
+      $mailObject->attrs['acl']= array();
+      foreach ($new_acl as $key => $value){
+        $mailObject->attrs['acl'][]= $value;
+      }
+    } else {
+      $mailObject->attrs['objectClass'][]= 'kolabInetOrgPerson';
+    }
+
+    /* Remove imap:// tagging */
+    $mailObject->attrs['kolabHomeServer']= preg_replace('%imap://%', '', $mailObject->attrs['kolabHomeServer']);
+    $mailObject->attrs['gosaMailServer']= $mailObject->attrs['kolabHomeServer'];
+    $mailObject->attrs['kolabDeleteFlag']= array();
+  }
+
+  function fixAttributesOnRemove(&$mailObject)
+  {
+    /* Add attribute for object deletion and remove GOsa specific
+       values from entry. */
+    foreach($this->attribute_map as $kolabAttr){
+      $mailObject->attrs[$kolabAttr] = array();
+    }  
+
+    /* Only add kolab delete Flag in case of an user.mailAccount */
+    if(!in_array("posixGroup", $mailObject->attrs['objectClass'])){
+      $mailObject->attrs['kolabDeleteFlag']= preg_replace('%imap://%', '', $mailObject->gosaMailServer);
+    }else{
+      /* Kolab shared folder names are like ' shared.uid@server.de ' 
+        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
+        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
+      $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
+      
+    }
+  }
+
+
+  function deleteMailbox($folder)
+  {
+    /* Remove shared folders and skip removing users. 
+       KolabD is not able to remove shared folders yet, so we do it instead */
+    if(preg_match("/^shared/",$folder)){
+      return mailMethodCyrus::deleteMailbox($folder);
+    }
+    return (TRUE);
+  }
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/class_mail-methods-golab.inc b/gosa-plugins/mail/personal/mail/class_mail-methods-golab.inc
deleted file mode 100644 (file)
index dc75674..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-<?php
-/*
-   This code is part of GOsa (https://gosa.gonicus.de)
-   Copyright (C) 2004  Cajus Pollmeier
-
-   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 mailMethodGolab extends mailMethodCyrus
-{
-  var $mbox= "-";
-  var $config;
-  var $gosaMailServer= "";
-  var $uattrib= "mail";
-
-  var $attribute_map= array("gosaMailAlternateAddress"  =>  "alias",
-                            "gosaMailQuota"             =>  "cyrus-userquota",
-                            "gosaMailServer"            =>  "kolabHomeServer");
-
-  function mailMethodGolab(&$config)
-  {
-    $this->config= $config->data['SERVERS']['IMAP'];
-  }
-
-  function updateMailbox($folder)
-  {
-  }
-
-  function setQuota($folder, $gosaMailQuota)
-  {
-    return (TRUE);
-  }
-
-  /* Get quota and divide it by 1024, because in gosa we display in MB
-      but we get Kb */
-  function getQuota($folder)
-  {
-    $result= array('quotaUsage' => '', 'gosaMailQuota' => '');
-
-    /* Only use lower case folder names, if folder name is like "@domain.com" */
-    if(preg_match("/@/",$folder)){
-      $folder = strtolower($folder);
-    }
-
-    error_reporting(0);  
-  
-    /* Load quota settings */
-    $quota_value = @imap_get_quota($this->mbox, $folder);
-    if(is_array($quota_value)) {
-      if (isset($quota_value["STORAGE"]) && is_array($quota_value["STORAGE"])){
-        /* use for PHP >= 4.3 */
-        $result['quotaUsage']=    (int) ($quota_value["STORAGE"]['usage'] / 1024);
-        $result['gosaMailQuota']= (int) ($quota_value["STORAGE"]['limit'] / 1024);
-      } else {
-        /* backward icompatible */
-        $result['quotaUsage']=    (int) ($quota_value['usage'] / 1024);
-        $result['gosaMailQuota']= (int) ($quota_value['limit'] / 1024);
-      }
-    }elseif(!$quota_value){
-      return(false);
-    }
-
-    error_reporting(E_ALL | E_STRICT); 
-    return ($result);
-  }
-
-
-  function fixAttributesOnLoad(&$mailObject)
-  {
-    /* Kolab shared folder names are like ' shared.uid@server.de ' 
-        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
-        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
-    if(get_class($mailObject) == "mailgroup"){
-     $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
-    }
-
-    /* Convert attributes and objectClasses */
-    foreach ($this->attribute_map as $dest => $source){
-      /* Hickert 11.11.05 : Alternate email addresses were saved, but not displayed again.
-      if (isset($mailObject->attrs[$source])){
-        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
-        unset ($mailObject->attrs[$source]);
-      */
-
-      if (isset($mailObject->attrs[$source])){
-        unset($mailObject->attrs[$source]['count']);
-        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
-        $mailObject->$dest=        $mailObject->attrs[$source];
-
-        unset ($mailObject->$dest['count']);
-        unset ($mailObject->attrs[$source]);
-      }
-    }
-
-    /* Adjust server name if needed */
-    foreach ($mailObject->config->data['SERVERS']['IMAP'] as $srv => $dummy){
-      if (preg_match("%".$mailObject->attrs['gosaMailServer'][0]."$%", $srv)){
-        $mailObject->attrs['gosaMailServer']= array(0 => $srv, "count" => 1);
-        break;
-      }
-    }
-  }
-
-
-  function fixAttributesOnStore(&$mailObject)
-  {
-    global $config;
-  
-    /* If quota is empty, remove quota restrictions by setting quota to 0 */
-    if(isset($mailObject->gosaMailQuota) && (empty($mailObject->gosaMailQuota))){
-      $mailObject->attrs['gosaMailQuota'] = 0;
-    }
-
-    /* Convert attributes and objectClasses */
-    foreach ($this->attribute_map as $source => $dest){
-      if (isset($mailObject->attrs[$source])){
-        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
-        unset ($mailObject->attrs[$source]);
-      }
-    }
-    $objectclasses= array();
-    foreach ($mailObject->attrs['objectClass'] as $oc){
-      if ($oc !=  'kolabInetOrgPerson' && $oc !=  'kolabSharedFolder'){
-        $objectclasses[]= $oc;
-      }
-    }
-    $mailObject->attrs['objectClass']= $objectclasses;
-    if (in_array("posixGroup", $mailObject->attrs['objectClass'])){
-  
-      /* Add kolabSharedFoleder Class */
-      $mailObject->attrs['objectClass'][]= 'kolabSharedFolder';
-
-      /* Work on acl attribute */
-      $new_acl= array();
-      foreach ($mailObject->attrs['acl'] as $uacl){
-
-        /* Get user=(mail) & acls  */
-        list($user, $acl) = split(" ", $uacl);
-      
-        /* Add al users which have seperated acls 
-           %members% are all users in this group, 
-           which have the standard group acl
-        */
-        if ($user != "%members%"){
-          $new_acl[$user]= $uacl;
-        } else {
-        
-          /* All groupmembers will be added */
-          $ldap = $config->get_ldap_link();
-          $ldap->cd($config->current['BASE']);
-          foreach ($mailObject->members as $member){
-
-            /* Get user mail address .... */
-            $ldap->search("(&(objectClass=person)(|(uid=".$member.")(mail=".$member.")))",array("mail"));
-            $res = $ldap->fetch();
-
-            /* Default mail address is set to uid - 
-               So if there is no mail address defined the uid is added 
-             */
-            $mail = $member;
-
-            /* Use mail address if it is available */
-            if(isset($res['mail'][0])){
-              $mail = $res['mail'][0];
-            }
-
-            /* only append this mail/permission string to acl,
-               if there arn't already some (special) configs for this user */
-            $found =false;
-            foreach($mailObject->imapacl as $mailA => $acl){
-              if(strtolower(trim($mailA))==strtolower(trim($mail))){
-                $found = true;
-              }
-            }
-
-            /* Skipp user, with no email adress too */     
-            if($member == $mail){
-              $found = true;
-            }
-   
-            /* Append new user acl */
-            if(!$found){
-              $new_acl[$member]= "$mail $acl";
-            }
-
-            /* Old line */
-            //  $new_acl[$member]= "$member $acl";
-          }
-        }
-      }
-      /* Save shared folder target */
-      $mailObject->attrs['gosaSharedFolderTarget']= "kolab+".$mailObject->mail;
-
-      /* Kolab shared folder names are like ' shared.uid@server.de ' 
-        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
-        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
-      $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
-  
-      /* Assign new acls */
-      $mailObject->attrs['acl']= array();
-      foreach ($new_acl as $key => $value){
-        $mailObject->attrs['acl'][]= $value;
-      }
-    } else {
-      $mailObject->attrs['objectClass'][]= 'kolabInetOrgPerson';
-    }
-
-    /* Remove imap:// tagging */
-    $mailObject->attrs['kolabHomeServer']= preg_replace('%imap://%', '', $mailObject->attrs['kolabHomeServer']);
-    $mailObject->attrs['gosaMailServer']= $mailObject->attrs['kolabHomeServer'];
-    $mailObject->attrs['kolabDeleteFlag']= array();
-  }
-
-  function fixAttributesOnRemove(&$mailObject)
-  {
-    /* Add attribute for object deletion and remove GOsa specific
-       values from entry. */
-    foreach($this->attribute_map as $kolabAttr){
-      $mailObject->attrs[$kolabAttr] = array();
-    }  
-
-    /* Only add kolab delete Flag in case of an user.mailAccount */
-    if(!in_array("posixGroup", $mailObject->attrs['objectClass'])){
-      $mailObject->attrs['kolabDeleteFlag']= preg_replace('%imap://%', '', $mailObject->gosaMailServer);
-    }else{
-      /* Kolab shared folder names are like ' shared.uid@server.de ' 
-        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
-        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
-      $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
-      
-    }
-  }
-
-
-  function deleteMailbox($folder)
-  {
-    /* Remove shared folders and skip removing users. 
-       KolabD is not able to remove shared folders yet, so we do it instead */
-    if(!(preg_match("/^user\//",$folder))){
-      return mailMethodCyrus::deleteMailbox($folder);
-    }
-    return (TRUE);
-  }
-}
-
-// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
-?>
diff --git a/gosa-plugins/mail/personal/mail/class_mail-methods-kolab.inc b/gosa-plugins/mail/personal/mail/class_mail-methods-kolab.inc
deleted file mode 100644 (file)
index c060604..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-<?php
-/*
-   This code is part of GOsa (https://gosa.gonicus.de)
-   Copyright (C) 2004  Cajus Pollmeier
-
-   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 mailMethodKolab extends mailMethodCyrus
-{
-  var $mbox= "-";
-  var $config;
-  var $gosaMailServer= "";
-  var $uattrib= "mail";
-
-  var $attribute_map= array("gosaMailAlternateAddress"  =>  "alias",
-                            "gosaMailQuota"             =>  "cyrus-userquota",
-                            "gosaMailServer"            =>  "kolabHomeServer");
-
-  function mailMethodKolab(&$config)
-  {
-    $this->config= $config->data['SERVERS']['IMAP'];
-  }
-
-  function updateMailbox($folder)
-  {
-  }
-
-  function setQuota($folder, $gosaMailQuota)
-  {
-    return (TRUE);
-  }
-
-  /* Get quota and divide it by 1024, because in gosa we display in MB
-      but we get Kb */
-  function getQuota($folder)
-  {
-    $result= array('quotaUsage' => '', 'gosaMailQuota' => '');
-
-    /* Only use lower case folder names, if folder name is like "@domain.com" */
-    if(preg_match("/@/",$folder)){
-      $folder = strtolower($folder);
-    }
-
-    error_reporting(0);  
-  
-    /* Load quota settings */
-    $quota_value = @imap_get_quota($this->mbox, $folder);
-    if(is_array($quota_value)) {
-      if (isset($quota_value["STORAGE"]) && is_array($quota_value["STORAGE"])){
-        /* use for PHP >= 4.3 */
-        $result['quotaUsage']=    (int) ($quota_value["STORAGE"]['usage'] / 1024);
-        $result['gosaMailQuota']= (int) ($quota_value["STORAGE"]['limit'] / 1024);
-      } else {
-        /* backward icompatible */
-        $result['quotaUsage']=    (int) ($quota_value['usage'] / 1024);
-        $result['gosaMailQuota']= (int) ($quota_value['limit'] / 1024);
-      }
-    }elseif(!$quota_value){
-      return(false);
-    }
-
-    error_reporting(E_ALL | E_STRICT); 
-    return ($result);
-  }
-
-
-  function fixAttributesOnLoad(&$mailObject)
-  {
-    /* Kolab shared folder names are like ' shared.uid@server.de ' 
-        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
-        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
-    if(get_class($mailObject) == "mailgroup"){
-     $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
-    }
-
-    /* Convert attributes and objectClasses */
-    foreach ($this->attribute_map as $dest => $source){
-      /* Hickert 11.11.05 : Alternate email addresses were saved, but not displayed again.
-      if (isset($mailObject->attrs[$source])){
-        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
-        unset ($mailObject->attrs[$source]);
-      */
-
-      if (isset($mailObject->attrs[$source])){
-        unset($mailObject->attrs[$source]['count']);
-        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
-        $mailObject->$dest=        $mailObject->attrs[$source];
-
-        /* Ensure that cleanup will recognize the ampped attributes too */
-        if(isset($mailObject->saved_attributes)){
-          $mailObject->saved_attributes[$dest] = $mailObject->attrs[$source];
-          $mailObject->saved_attributes[$source] = $mailObject->attrs[$source];
-        }       
-
-        unset ($mailObject->$dest['count']);
-        unset ($mailObject->attrs[$source]);
-      }
-    }
-
-    /* Adjust server name if needed */
-    foreach ($mailObject->config->data['SERVERS']['IMAP'] as $srv => $dummy){
-      if (preg_match("%".$mailObject->attrs['gosaMailServer'][0]."$%", $srv)){
-        $mailObject->attrs['gosaMailServer']= array(0 => $srv, "count" => 1);
-        break;
-      }
-    }
-  }
-
-
-  function fixAttributesOnStore(&$mailObject)
-  {
-    global $config;
-  
-    /* If quota is empty, remove quota restrictions by setting quota to 0 */
-    if(isset($mailObject->gosaMailQuota) && (empty($mailObject->gosaMailQuota))){
-      $mailObject->attrs['gosaMailQuota'] = 0;
-    }
-
-    /* Convert attributes and objectClasses */
-    foreach ($this->attribute_map as $source => $dest){
-      if (isset($mailObject->attrs[$source])){
-        $mailObject->attrs[$dest]= $mailObject->attrs[$source];
-        unset ($mailObject->attrs[$source]);
-      }
-    }
-    $objectclasses= array();
-    foreach ($mailObject->attrs['objectClass'] as $oc){
-      if ($oc !=  'kolabInetOrgPerson' && $oc !=  'kolabSharedFolder'){
-        $objectclasses[]= $oc;
-      }
-    }
-    $mailObject->attrs['objectClass']= $objectclasses;
-    if (in_array("posixGroup", $mailObject->attrs['objectClass'])){
-  
-      /* Add kolabSharedFoleder Class */
-      $mailObject->attrs['objectClass'][]= 'kolabSharedFolder';
-
-      /* Work on acl attribute */
-      $new_acl= array();
-      foreach ($mailObject->attrs['acl'] as $uacl){
-
-        /* Get user=(mail) & acls  */
-        list($user, $acl) = split(" ", $uacl);
-      
-        /* Add al users which have seperated acls 
-           %members% are all users in this group, 
-           which have the standard group acl
-        */
-        if ($user != "%members%"){
-          $new_acl[$user]= $uacl;
-        } else {
-        
-          /* All groupmembers will be added */
-          $ldap = $config->get_ldap_link();
-          $ldap->cd($config->current['BASE']);
-          foreach ($mailObject->members as $member){
-
-            /* Get user mail address .... */
-            $ldap->search("(&(objectClass=person)(|(uid=".$member.")(mail=".$member.")))",array("mail"));
-            $res = $ldap->fetch();
-
-            /* Default mail address is set to uid - 
-               So if there is no mail address defined the uid is added 
-             */
-            $mail = $member;
-
-            /* Use mail address if it is available */
-            if(isset($res['mail'][0])){
-              $mail = $res['mail'][0];
-            }
-
-            /* only append this mail/permission string to acl,
-               if there arn't already some (special) configs for this user */
-            $found =false;
-            foreach($mailObject->imapacl as $mailA => $acl){
-              if(strtolower(trim($mailA))==strtolower(trim($mail))){
-                $found = true;
-              }
-            }
-
-            /* Skipp user, with no email adress too */     
-            if($member == $mail){
-              $found = true;
-            }
-   
-            /* Append new user acl */
-            if(!$found){
-              $new_acl[$member]= "$mail $acl";
-            }
-
-            /* Old line */
-            //  $new_acl[$member]= "$member $acl";
-          }
-        }
-      }
-      /* Save shared folder target */
-      $mailObject->attrs['gosaSharedFolderTarget']= "kolab+shared.".$mailObject->mail;
-
-      /* Kolab shared folder names are like ' shared.uid@server.de ' 
-        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
-        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
-      $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
-  
-      /* Assign new acls */
-      $mailObject->attrs['acl']= array();
-      foreach ($new_acl as $key => $value){
-        $mailObject->attrs['acl'][]= $value;
-      }
-    } else {
-      $mailObject->attrs['objectClass'][]= 'kolabInetOrgPerson';
-    }
-
-    /* Remove imap:// tagging */
-    $mailObject->attrs['kolabHomeServer']= preg_replace('%imap://%', '', $mailObject->attrs['kolabHomeServer']);
-    $mailObject->attrs['gosaMailServer']= $mailObject->attrs['kolabHomeServer'];
-    $mailObject->attrs['kolabDeleteFlag']= array();
-  }
-
-  function fixAttributesOnRemove(&$mailObject)
-  {
-    /* Add attribute for object deletion and remove GOsa specific
-       values from entry. */
-    foreach($this->attribute_map as $kolabAttr){
-      $mailObject->attrs[$kolabAttr] = array();
-    }  
-
-    /* Only add kolab delete Flag in case of an user.mailAccount */
-    if(!in_array("posixGroup", $mailObject->attrs['objectClass'])){
-      $mailObject->attrs['kolabDeleteFlag']= preg_replace('%imap://%', '', $mailObject->gosaMailServer);
-    }else{
-      /* Kolab shared folder names are like ' shared.uid@server.de ' 
-        So overwrite uid to match these folder names. Else we can't read quota settings etc. 
-        #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/
-      $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail);
-      
-    }
-  }
-
-
-  function deleteMailbox($folder)
-  {
-    /* Remove shared folders and skip removing users. 
-       KolabD is not able to remove shared folders yet, so we do it instead */
-    if(preg_match("/^shared/",$folder)){
-      return mailMethodCyrus::deleteMailbox($folder);
-    }
-    return (TRUE);
-  }
-}
-
-// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
-?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_My_Parser.inc b/gosa-plugins/mail/personal/mail/sieve/class_My_Parser.inc
new file mode 100644 (file)
index 0000000..ac99301
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+
+/* String used to indent the different code blocks */
+define("SIEVE_INDENT_TAB","  ");
+
+
+/* This class is inherited from the original 'Parser'
+ *  class written by Heiko Hund
+ */
+class My_Parser extends Parser 
+{
+       var $parent = NULL;
+       var $registeredExtensions_ =array();
+
+       function My_Parser($parent)
+       {
+               $this->registeredExtensions_ = array();         
+               $this->parent = $parent;
+       }
+
+       function execute()
+       {
+               $ret = $this->dumpParseTree();
+               return($ret);
+       }
+       
+
+       /* Check if there are errors, collect them and return them */
+       function check()
+       {
+               return($this->tree_->check());
+       }
+       
+
+       /* Initiate parser, but use some other 
+     *  classes, that are rewritten.
+     */
+       function parse($script) 
+       {
+               $script = preg_replace("/^###GOSA/","",$script);
+
+               $this->registeredExtensions_ = array();
+        $this->status_text = "incomplete";
+        $this->script_ = $script;
+        $this->tree_ = new My_Tree(@Scanner::scriptStart(),$this);
+        $this->tree_->setDumpFunc(array(&$this, 'dumpToken_'));
+        $this->scanner_ = new My_Scanner($this->script_);
+        $this->scanner_->setCommentFunc(array($this, 'comment_'));
+
+        if ($this->commands_($this->tree_->getRoot()) &&
+            $this->scanner_->nextTokenIs('script-end'))
+        {
+                       $this->scanner_->nextToken(); 
+            return $this->success_('success');
+        }
+
+        return $this->status_;
+       }
+
+       
+       function get_sieve_script()
+       {
+               return("###GOSA\n".$this->tree_->get_sieve_script());
+       }               
+
+       
+       function save_object()
+       {
+               $this->tree_->save_object();
+       }
+
+
+       function dumpParseTree()
+       {
+               return $this->tree_->execute();
+       }
+}
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_My_Scanner.inc b/gosa-plugins/mail/personal/mail/sieve/class_My_Scanner.inc
new file mode 100644 (file)
index 0000000..878927a
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+
+class My_Scanner extends Scanner 
+{
+       function tokenize(&$script)
+       {
+               $pos = 0;
+               $line = 1;
+               $script_length = mb_strlen($script);
+
+               while ($pos < $script_length)
+               {
+                       foreach ($this->token_match_ as $class => $regex)
+                       {
+                               if (preg_match('/^'. $regex .'/', mb_substr($script, $pos), $match))
+                               {
+                                       $length = mb_strlen($match[0]);
+
+                                       if ($class != 'whitespace')
+                                       {
+                                               array_push($this->tokens_, array(
+                                                       'class' => $class,
+                                                       'text'  => chop(mb_substr($script, $pos, $length)),
+                                                       'line'  => $line,
+                                               ));
+                                       }
+                                       if ($class == 'unknown')
+                                       {
+                                               return;
+                                       }
+
+                                       $pos += $length;
+                                       $line += mb_substr_count($match[0], "\n");
+                                       break;
+                               }
+                       }
+               }
+               array_push($this->tokens_, array(
+                       'class' => 'script-end',
+                       'text'  => 'script-end',
+                       'line'  => $line,
+               ));
+       }
+
+       var $commentFn_ = null;
+       var $tokenPos_ = 0;
+       var $tokens_ = array();
+       var $token_match_ = array (
+               'left-bracket'   =>  '\[',
+               'right-bracket'  =>  '\]',
+               'block-start'    =>  '\{',
+               'block-end'      =>  '\}',
+               'left-parant'    =>  '\(',
+               'right-parant'   =>  '\)',
+               'comma'          =>  ',',
+               'semicolon'      =>  ';',
+               'whitespace'     =>  '[ \r\n\t]+',
+               'tag'            =>  ':[[:alpha:]_][[:alnum:]_]*(?=\b)',
+               'quoted-string'  =>  '"(?:\\[\\"]|[^\x00"])*"',
+               'number'         =>  '[[:digit:]]+(?:[KMG])?(?=\b)',
+               'comment'        =>  '(?:\/\*(?:[^\*]|\*(?=[^\/]))*\*\/|#[^\r\n]*\r?\n)',
+#              'multi-line'     =>  'text:[ \t]*(?:#[^\r\n]*)?\r?\n(\.[^\r\n]+\r?\n|[^\.]*\r?\n)*\.\r?\n',
+               'multi-line'     =>  'text:[^;]*',
+               'identifier'     =>  '[[:alpha:]_][[:alnum:]_]*(?=\b)',
+               'unknown token'  =>  '[^ \r\n\t]+'
+       );
+}
+
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_My_Tree.inc b/gosa-plugins/mail/personal/mail/sieve/class_My_Tree.inc
new file mode 100644 (file)
index 0000000..b1b061e
--- /dev/null
@@ -0,0 +1,782 @@
+<?php
+
+/* This class is inherited from the original 'Tree'
+ *  class written by Heiko Hund.
+ * It is partly rewritten to create a useable html interface 
+ *  for each single sieve token. 
+ * This gives us the ability to edit existing sieve filters. 
+ */
+class My_Tree extends Tree
+{
+  var $dumpFn_;
+  var $dump_;
+
+  var $mode_stack = array();
+  var $pap             = array();
+  var $parent = NULL;
+
+  function My_Tree(&$root,$parent)
+  {
+    $this->parent = $parent;
+    $this->_construct($root);
+  }
+
+
+  function execute()
+  {
+    return($this->dump());
+  }
+
+
+  /* Create a html interface for the current sieve filter 
+   */
+  function dump()
+  {
+    /**************
+     * Handle new elements 
+     **************/
+
+    /* Only parse the tokens once */
+    if(!count($this->pap)){
+      $this->dump_ = "";
+      $this->mode_stack = array();
+      $this->pap = array();
+      $this->doDump_(0, '', true);
+
+      /* Add left elements */
+      if(count($this->mode_stack)){
+        foreach($this->mode_stack as $element){
+          $this->handle_elements( $element,preg_replace("/[^0-9]/","",microtime()));
+        }
+      }
+    }
+
+    /* Create html results */
+    $smarty = get_smarty();
+
+    $block_indent_start = $smarty->fetch(get_template_path("templates/block_indent_start.tpl",TRUE,dirname(__FILE__)));
+    $block_indent_stop  = $smarty->fetch(get_template_path("templates/block_indent_stop.tpl",TRUE,dirname(__FILE__))); 
+
+    $this -> dump_ = "";
+    $ends = array();
+    $ends_complete_block = array();
+
+    foreach($this->pap as $key => $object){
+      if(is_object($object)){
+
+        $end = $this->get_block_end($key,false);
+        $end2 = $this->get_block_end($key);
+        if($end != $key && in_array(get_class($object),array("sieve_if"))){
+          $ends_complete_block[$end2] = $end2;
+          $this->dump_ .= "<div style='height:10px;'></div>";
+          $this->dump_ .= "<div class='container_'>";
+        }
+        if(isset($ends[$key])){
+          $this->dump_  .= $block_indent_stop;
+        }
+        $this->dump_ .= preg_replace("/>/",">\n",$object->execute()); 
+        if($end != $key && in_array(get_class($object),array("sieve_if","sieve_else","sieve_elsif"))) {
+          $ends[$end] = $end;  
+          $this->dump_  .= $block_indent_start;
+        }
+
+        if(isset($ends_complete_block[$key])){
+          $this->dump_ .= "</div>";
+          $this->dump_ .= "<div style='height:10px;'></div>";
+        }
+      }
+    }
+    
+    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];
+
+    /* Get last element class and type */
+    $last_class = "";
+    $last_type  = "";
+    if(count($this->mode_stack)){
+      $key = key($this->mode_stack);
+      $tmp = array_reverse($this->mode_stack[$key]['ELEMENTS']);
+      $last_class = $tmp[key($tmp)]['class'];
+      
+      if(isset($this->mode_stack[$key]['TYPE'])){
+        $last_type  = $this->mode_stack[$key]['TYPE'];
+      }
+    }
+
+    /* This closes the last mode */
+    if($node['class'] == "block-start"){
+      $tmp = array_pop($this->mode_stack);
+      $this->handle_elements($tmp,$node_id);
+      $this->handle_elements(array("TYPE" => "block_start"),preg_replace("/[^0-9]/","",microtime()));
+    }
+
+    /* This closes the last mode */
+    if($node['class'] == "block-end"){
+      $tmp = array_pop($this->mode_stack);
+      $this->handle_elements($tmp,$node_id);
+      $this->handle_elements(array("TYPE" => "block_end"),preg_replace("/[^0-9]/","",microtime()));
+    }
+
+    /* Semicolon indicates a new command */
+    if($node['class'] == "semicolon"){
+      $tmp =array_pop($this->mode_stack);
+      $this->handle_elements($tmp,$node_id);
+    }
+
+    /* We can't handle comments within if tag right now */
+    if(!in_array_ics($last_type,array("if","elsif"))){
+
+      /* Comments require special attention.
+       * We do not want to create a single comment element 
+       *  foreach each  "#comment"  string found in the script. 
+       * Sometimes comments are used like this 
+       *   # This is a comment
+       *   #  and it still is a comment 
+       *   #  ...
+       * So we combine them to one single comment.
+       */
+      if($last_class != "comment" && $node['class'] == "comment"){
+        $tmp =array_pop($this->mode_stack);
+        $this->handle_elements($tmp,$node_id);
+        $this->mode_stack[] = array("TYPE" => $node['class']); 
+      }  
+
+      if($last_class == "comment" && $node['class'] != "comment"){
+        $tmp =array_pop($this->mode_stack);
+        $this->handle_elements($tmp,$node_id);
+      }
+    }
+
+    /* Handle identifiers */
+    $identifiers = array("else","if","elsif","end","reject","redirect","vacation","keep","discard","fileinto","require","stop");
+    if($node['class'] == "identifier" && in_array($node['text'],$identifiers)){
+      $this->mode_stack[] = array("TYPE" => $node['text']); 
+    }
+
+    if(!($last_type == "if" && $node['class'] == "comment")){
+      /* 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,$node_id);
+    }
+
+    /* 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);
+      }
+    }
+  }
+
+
+  /* Create a class for each resolved object.
+   * And append this class to a list of objects.
+   */
+  function handle_elements($data,$id)
+  {
+    if(!isset($data['TYPE'])){
+      return;
+    }
+    $type = $data['TYPE'];
+    
+    $class_name= "sieve_".$type ;
+    if(class_exists($class_name)){
+      $this->pap[] = new $class_name($data,$id,$this);
+    }else{
+      echo "<font color='red'>Missing : ".$class_name."</font>"."<br>";
+    }
+  }
+
+  function save_object()
+  {
+    reset($this->pap);
+    foreach($this->pap as $key => $obj){
+
+      if(in_array(get_class($obj),array("sieve_if",
+                                        "sieve_elsif",
+                                        "sieve_vacation",
+                                        "sieve_comment",
+                                        "sieve_reject",
+                                        "sieve_fileinto",
+                                        "sieve_require",
+                                        "sieve_redirect"))){
+
+
+        if(isset($this->pap[$key]) && method_exists($this->pap[$key],"save_object")){
+          $this->pap[$key]->save_object();
+        }
+      }
+    }
+  }
+
+
+  /* Remove the object at the given position */
+  function remove_object($key_id)
+  {
+    if(count($this->pap) == 1){
+      msg_dialog::display(_("Warning"), _("Cannot remove last element!"), ERROR_DIALOG);
+      return;
+    }
+
+    if(!isset($this->pap[$key_id])){
+      trigger_error("Can't remove element with object_id=".$key_id.", there is no object with this identifier. Remove aborted.");
+      return(false);
+    }
+
+    $class = get_class($this->pap[$key_id]);
+    if(in_array($class,array("sieve_if","sieve_elsif","sieve_else"))){
+      $block_start= $key_id;
+      $block_end  = $this->get_block_end($key_id);
+
+      for($i = $block_start ; $i <= $block_end ; $i ++ ){
+        unset($this->pap[$i]);
+      }
+    }else{
+      unset($this->pap[$key_id]);
+    }
+    $tmp = array();
+    foreach($this->pap as $element){
+      $tmp[] = $element;
+    }
+    $this->pap = $tmp;
+  }
+
+
+  /* This function moves a given element to another position.
+   * Single elements like "keep;" will simply be moved one posisition down/up.
+   * Multiple elements like if-elsif-else will be moved as block. 
+   * 
+   *  $key_id     specified the element that should be moved.
+   *  $direction  specifies to move elements "up" or "down"
+   */
+  function move_up_down($key_id,$direction = "down")
+  {
+     
+    /* Get the current element to decide what to move. */ 
+    $e_class = get_class($this->pap[$key_id]);
+      
+    if(in_array($e_class,array("sieve_if"))){
+      $block_start= $key_id;
+      $block_end  = $this->get_block_end($key_id);
+
+      /* Depending on the direction move up down */
+      if($direction == "down"){
+        $next_free  = $this->_get_next_free_move_slot($block_end,$direction); 
+      }else{
+        $next_free  = $this->_get_next_free_move_slot($block_start,$direction); 
+      }
+
+      /* Move the given block */ 
+      $this->move_multiple_elements($block_start,$block_end,$next_free);
+    }
+
+    if(in_array($e_class,array( "sieve_stop",
+                                "sieve_keep",
+                                "sieve_require",
+                                "sieve_comment",
+                                "sieve_vacation",
+                                "sieve_stop",   
+                                "sieve_reject", 
+                                "sieve_fileinto",
+                                "sieve_redirect", 
+                                "sieve_discard"))){
+      $this->move_single_element($key_id,$this->_get_next_free_move_slot($key_id,$direction));
+    }
+  }
+
+  
+  /* Move the given block to position */
+  function move_multiple_elements($start,$end,$to)
+  {
+    /* Use class names for testing */
+    $data = $this->pap;
+
+    /* Get block to move */
+    $block_to_move = array_slice($data,$start, ($end - $start +1));
+
+    /* We want do move this block up */
+    if($end > $to){
+      
+      /* Get start block */
+      $start_block = array_slice($data,0,$to);
+
+      /* Get Get all elements between the block to move 
+       *  and next free position 
+       */
+      $block_to_free = array_slice($data,$to ,$start - $to );  
+      $block_to_end = array_slice($data,$end+1);
+      $new = array();
+      foreach($start_block as $block){
+        $new[] = $block;
+      }
+      foreach($block_to_move as $block){
+        $new[] = $block;
+      }
+      foreach($block_to_free as $block){
+        $new[] = $block;
+      }
+      foreach($block_to_end as $block){
+        $new[] = $block;
+      }
+      $old = $this->pap;
+      $this->pap = $new;
+    }
+    
+
+    /* We want to move this block down. */
+    if($to > $end){
+
+      /* Get start block */
+      $start_block = array_slice($data,0,$start);
+
+      /* Get Get all elements between the block to move 
+       *  and next free position 
+       */
+      $block_to_free = array_slice($data,$end +1,($to - $end  ));  
+
+      /* Get the rest 
+       */
+      $block_to_end = array_slice($data,$to+1);
+
+      $new = array();
+      foreach($start_block as $block){
+        $new[] = $block;
+      }
+      foreach($block_to_free as $block){
+        $new[] = $block;
+      }
+      foreach($block_to_move as $block){
+        $new[] = $block;
+      }
+      foreach($block_to_end as $block){
+        $new[] = $block;
+      }
+      $old = $this->pap;
+      $this->pap = $new;
+    }
+  }  
+
+  
+  /* This function returns the id of the element 
+   *  where the current block ends  
+   */
+  function get_block_end($start,$complete = TRUE)
+  {
+    /* Only execute if this is a really a block element. 
+     * Block elements is only sieve_if
+     */
+    if(in_array(get_class($this->pap[$start]),array("sieve_if","sieve_elsif","sieve_else"))){
+
+      $class      = get_class($this->pap[$start]);
+      $next_class = get_class($this->pap[$start+1]);
+      $block_depth = 0;
+
+      $end = FALSE;
+
+      while(!$end && $start < count($this->pap)){
+        if($class == "sieve_block_start"){
+          $block_depth ++;
+        }
+
+        if($class == "sieve_block_end"){
+          $block_depth --;
+        }
+
+        if($complete){
+          if( $block_depth == 0 && 
+              $class == "sieve_block_end" && 
+              !in_array($next_class,array("sieve_else","sieve_elsif"))){
+            $end = TRUE;
+            $start --;
+          }
+        }else{
+
+          if( $block_depth == 0 && 
+              $class == "sieve_block_end" ){ 
+            $end = TRUE;
+            $start --;
+          }
+        }
+
+        $start ++;       
+        $class      = get_class($this->pap[$start]);
+        
+        if(isset($this->pap[$start+1])){ 
+          $next_class = get_class($this->pap[$start+1]);
+        }else{
+          $next_class ="";
+        }
+      }
+    }
+    return($start);
+  }
+
+
+  /* This function moves the single element at 
+   *  position $from to position $to.
+   */
+  function move_single_element($from,$to)
+  {
+    if($from == $to) {
+      return;
+    }
+
+    $ret = array();
+    $tmp = $this->pap;
+
+    $begin = array();
+    $middle = array();
+    $end = array();
+    $element = $this->pap[$from];
+
+    if($from > $to ){
+
+      /* Get all element in fron to element to move */    
+      if($from  != 0){
+        $begin = array_slice($tmp,0,$to);
+      }
+
+      /* Get all elements between */
+      $middle = array_slice($tmp,$to , ($from - ($to) ));  
+    
+      /* Get the rest */ 
+      $end  = array_slice($tmp,$from+1);
+      foreach($begin as $data){
+        $ret[] = $data;
+      }
+      $ret[] = $element;
+      foreach($middle as $data){
+        $ret[] = $data;
+      }
+      foreach($end as $data){
+        $ret[] = $data;
+      }
+      $this->pap = $ret;
+    }
+    if($from < $to ){
+
+      /* Get all element in fron to element to move */    
+      if($from  != 0){
+        $begin = array_slice($tmp,0,$from);
+      }
+
+      /* Get all elements between */
+      $middle = array_slice($tmp,$from+1 , ($to - ($from)));  
+    
+      /* Get the rest */ 
+      $end  = array_slice($tmp,$to+1);
+      foreach($begin as $data){
+        $ret[] = $data;
+      }
+      foreach($middle as $data){
+        $ret[] = $data;
+      }
+      $ret[] = $element;
+      foreach($end as $data){
+        $ret[] = $data;
+      }
+      $this->pap = $ret;
+    }
+  }
+
+
+  /* Returns the next free position where we 
+   *  can add a new sinle element 
+   *    $key_id     = Current position
+   *    $direction  = Forward or backward.
+   */
+  function _get_next_free_move_slot($key_id,$direction,$include_self = FALSE)
+  {
+    $last_class = "";
+    $current_class ="";
+    $next_class = "";
+
+    /* After this elements we can add new elements 
+     *  without having any trouble.
+     */
+    $allowed_to_add_after = array("sieve_keep",
+                                  "sieve_require", 
+                                  "sieve_stop", 
+                                  "sieve_reject", 
+                                  "sieve_fileinto", 
+                                  "sieve_redirect", 
+                                  "sieve_discard",
+                                  "sieve_comment",
+                                  "sieve_block_start"
+                                 );
+
+    /* Before this elements we can add new elements 
+     *  without having any trouble.
+     */
+    $allowed_to_add_before = array("sieve_keep",
+                                  "sieve_require", 
+                                  "sieve_stop", 
+                                  "sieve_reject", 
+                                  "sieve_fileinto", 
+                                  "sieve_comment",
+                                  "sieve_redirect", 
+                                  "sieve_discard",
+                                  "sieve_if", 
+                                  "sieve_block_end"
+                                 );
+
+    if($direction == "down"){
+    
+      $test = $this->pap;
+      while($key_id < count($test)){
+        if(($key_id+1) == count($test)) {
+          return($key_id);
+        }
+
+        if(!$include_self){
+          $key_id ++;
+        }
+        $include_self = FALSE;
+        $current_class  = get_class($test[$key_id]);
+        if(in_array($current_class, $allowed_to_add_after)){
+          return($key_id);
+        } 
+      } 
+    }else{
+  
+      $test = $this->pap;
+      if($key_id == 0) {
+        return($key_id);
+      }
+      if(!$include_self){
+        $key_id --;
+      }
+      while($key_id >=0 ){
+        $current_class  = get_class($test[$key_id]);
+        if(in_array($current_class, $allowed_to_add_before)){
+          return($key_id);
+        } 
+        $key_id --;
+      }
+      return(0);
+    }
+  }
+
+
+  /* Need to be reviewed */
+  function get_sieve_script()
+  {
+    $tmp ="";
+    if(count($this->pap)){
+      $buffer = "";    
+      foreach($this->pap as $part)  {
+        if(get_class($part) == "sieve_block_end"){
+          $buffer = substr($buffer,0,strlen($buffer)-(strlen(SIEVE_INDENT_TAB)));
+        }
+        $tmp2 = $part->get_sieve_script_part();
+
+        $tmp3 = split("\n",$tmp2);
+        foreach($tmp3 as $str){
+          $str2 = trim($str);
+
+          /* If the current line only contains an '.'    
+           *  we must skip the line indent. 
+           * The text: statement uses a single '.' to mark the text end.
+           * This '.' must be the only char in the current line, no
+           *  whitespaces are allowed here.
+           */
+          if($str2 == "."){
+            $tmp.=$str."\n";
+          }else{
+            $tmp.= $buffer.$str."\n";
+          }
+        }
+        if(get_class($part) == "sieve_block_start"){
+          $buffer .= SIEVE_INDENT_TAB;
+        }
+      }
+    }
+    if(!preg_match("/Generated by GOsa - Gonicus System Administrator/",$tmp)){
+#      $tmp = "#Generated by GOsa - Gonicus System Administrator \n ".$tmp;
+    }
+    return($tmp);
+  }
+
+  function check()
+  {
+    $msgs = array();
+
+    /* Some logical checks. 
+     *  like :  only sieve_comment can appear before require.
+     */
+
+    /* Ensure that there are no command before require 
+     *  - Get id of last require tag
+     *  - Collect object types in from of this tag. 
+     *  - Check if there are tags collected that are not allowed 
+     */
+    $last_found_at = -1; 
+    $objs = array();
+    foreach($this->pap as $key => $obj){
+      if(get_class($obj) == "sieve_require"){
+        $last_found_at = $key;
+      }
+    }
+    foreach($this->pap as $key => $obj){
+      if($key == $last_found_at) break;  
+      if(!in_array(get_class($obj),array("sieve_comment","sieve_require"))){
+        $objs[] = get_class($obj);
+      }
+    }
+    if(count($objs) && $last_found_at != -1){
+      $str = _("Require must be the first command in the script.");  
+      $msgs[] = $str;
+      msg_dialog::display(_("Error"), $str, ERROR_DIALOG);
+    }
+
+    foreach($this->pap as $obj){
+      $o_msgs = $obj->check();
+      foreach($o_msgs as $o_msg){
+        $msgs[] = $o_msg;
+      }
+    }
+    return($msgs);
+  }
+
+
+  /* We are forced to add a new require.
+   *  This function is called by the 
+   *  sieveElement_Classes->parent->add_require()  
+   */ 
+  function add_require($str)
+  {
+    $require_id = -1;
+    foreach($this->pap as $key => $obj){
+      if(get_class($obj) == "sieve_require"){
+        $require_id = $key;
+      }
+    }
+
+    /* No require found, add one */
+    if($require_id == -1){
+      $require = new sieve_require(NULL,preg_replace("/[^0-9]/","",microtime()),$this);
+      $require -> Add_Require($str);
+      $new = array();
+      $new[] = $require;
+      foreach($this->pap as $obj){
+        $new[] = $obj;
+      }
+      $this->pap = $new;
+    } else { 
+      $this->pap[$require_id]->Add_Require($str);
+    } 
+  }
+}
+
+
+/* Create valid sieve string/string-list 
+ *  out of a given array
+ */
+function sieve_create_strings($data,$force_string = FALSE)
+{
+  $ret = "";
+  if(is_array($data)){
+    if(count($data) == 1){
+      $ret = "\"";
+      foreach($data as $dat){
+        $ret .=$dat;
+      }
+      $ret.="\"";
+    }else{
+      foreach($data as $dat){
+        $ret.= "\"";
+        $ret.=$dat;
+        $ret.="\", ";
+      }
+      $ret = preg_replace("/,$/","",trim($ret));
+      $ret = "[".$ret."]";
+    }
+#      $ret = preg_replace("/\"\"/","\"",$ret);
+  }else{
+
+    $Multiline = preg_match("/\n/",$data);
+    $data = preg_replace("/\r/","",$data);;
+
+    if($Multiline && !$force_string){
+      $ret = "text: \r\n".$data."\r\n.\r\n";
+    }else{
+      $ret = "\"".$data."\"";
+      $ret = preg_replace("/\"\"/","\"",$ret);
+    }
+  }
+  $ret = preg_replace("/\n/","\r\n",$ret);
+
+  return($ret);
+}
+
+/* This checks if there is a string at the current position 
+ *  in the token array. 
+ * If there is a string list at the current position,
+ *  this function will return a complete list of all
+ *  strings used in this list.
+ * It also returns an offset of the last token position 
+ */
+function sieve_get_strings($data,$id)
+{
+  $ret = array();
+  if($data[$id]['class'] == "left-bracket"){
+    while(isset($data[$id]) && $data[$id]['class']  != "right-bracket" && $id < count($data)){
+
+      if($data[$id]['class'] == "quoted-string"){
+        $text = $data[$id]['text']; 
+        $text= preg_replace("/^\"/","",$text);
+        $text= preg_replace("/\"$/","",$text);
+        $ret[] = $text;
+      }
+
+      $id ++;
+    }
+  }elseif($data[$id]['class'] == "quoted-string"){
+    $text = $data[$id]['text']; 
+    $text= preg_replace("/^\"/","",$text);
+    $text= preg_replace("/\"$/","",$text);
+    $ret[] = $text;
+  }elseif($data[$id]['class'] == "number"){
+    $ret[] = $data[$id]['text'];
+  }elseif($data[$id]['class'] == "multi-line"){
+    $str = trim(preg_replace("/^text:/","",$data[$id]['text']));
+    $str = trim(preg_replace("/\.$/","",$str));
+    $ret[] = $str;
+  }
+
+  return(array("OFFSET" => $id, "STRINGS" => $ret));
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_parser.inc b/gosa-plugins/mail/personal/mail/sieve/class_parser.inc
new file mode 100644 (file)
index 0000000..3458952
--- /dev/null
@@ -0,0 +1,365 @@
+<?php
+
+#include_once 'class.tree.php';
+#include_once 'class.scanner.php';
+#include_once 'class.semantics.php';
+
+class Parser
+{
+       var $scanner_;
+       var $script_;
+       var $tree_;
+       var $status_;
+       var $registeredExtensions_;
+
+       var $status_text;
+
+       function parse($script)
+       {
+               $this->registeredExtensions_ = array();
+               $this->status_text = "incomplete";
+
+               $this->script_ = $script;
+               $this->tree_ = new 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 dumpParseTree()
+       {
+               return $this->tree_->dump();
+       }
+
+       function dumpToken_(&$token)
+       {
+               if (is_array($token))
+               {
+                       $str = "<" . $token['text'] . "> ";
+                       foreach ($token as $k => $v)
+                       {
+                               $str .= " $k:$v";
+                       }
+                       return $str;
+               }
+
+               return strval($token);
+       }
+
+       function getPrevTokenText_($parent_id)
+       {
+               $childs = $this->tree_->getChilds($parent_id);
+
+               for ($i=count($childs); $i>0; --$i)
+               {
+                       $prev = $this->tree_->getNode($childs[$i-1]);
+
+                       if (in_array($prev['text'], array('{', '(', ',')))
+                       {
+                               // use command owning a block or list
+                               $prev = $this->tree_->getNode($parent_id);
+                       }
+
+                       if ($prev['class'] != 'comment')
+                       {
+                               return $prev['text'];
+                       }
+               }
+
+               $prev = $this->tree_->getNode($parent_id);
+               return $prev['text'];
+       }
+
+       function getSemantics_($token_text)
+       {
+               $semantics = new Semantics($token_text);
+               $semantics->setExtensionFuncs(array(&$this, 'registerExtension_'), array(&$this, 'isExtensionRegistered_'));
+               return $semantics;
+       }
+
+       function registerExtension_($extension)
+       {
+               array_push($this->registeredExtensions_, str_replace('"', '', $extension));
+       }
+
+       function isExtensionRegistered_($extension)
+       {
+               return (in_array($extension, $this->registeredExtensions_) ? true : false);
+       }
+
+       function success_($text = null)
+       {
+               if ($text != null)
+               {
+                       $this->status_text = $text;
+               }
+
+               return $this->status_ = true;
+       }
+
+       function error_($text, $token = null)
+       {
+               if ($token != null)
+               {
+                       $text = 'line '. $token['line'] .': '. $token['class'] . " where $text expected near ". $token['text'];
+               }
+
+               $this->status_text = $text;
+               return $this->status_ = false;
+       }
+
+       function done_()
+       {
+               $this->status_ = true;
+               return false;
+       }
+
+       /*******************************************************************************
+        * methods for recursive descent start below
+        */
+
+       function comment_($token)
+       {
+               $this->tree_->addChild($token);
+       }
+
+       function commands_($parent_id)
+       {
+               while ($this->command_($parent_id))
+                       ;
+
+               return $this->status_;
+       }
+
+       function command_($parent_id)
+       {
+               if (!$this->scanner_->nextTokenIs('identifier'))
+               {
+                       if ($this->scanner_->nextTokenIs(array('block-end', 'script-end')))
+                       {
+                               return $this->done_();
+                       }
+                       return $this->error_('identifier', $this->scanner_->peekNextToken());
+               }
+
+               // Get and check a command token
+               $token = $this->scanner_->nextToken();
+               $semantics = $this->getSemantics_($token['text']);
+               if (!$semantics->validCommand($this->getPrevTokenText_($parent_id), $token['line']))
+               {
+                       return $this->error_($semantics->message);
+               }
+
+               // Process eventual arguments
+               $this_node = $this->tree_->addChildTo($parent_id, $token);
+               if ($this->arguments_($this_node, $semantics) == false)
+               {
+                       return false;
+               }
+
+               $token = $this->scanner_->nextToken();
+               if ($token['class'] != 'semicolon')
+               {
+                       if (!$semantics->validToken($token['class'], $token['text'], $token['line']))
+                       {
+                               return $this->error_($semantics->message);
+                       }
+
+                       if ($token['class'] == 'block-start')
+                       {
+                               $this->tree_->addChildTo($this_node, $token);
+                               $ret = $this->block_($this_node, $semantics);
+                               return $ret;
+                       }
+
+                       return $this->error_('semicolon', $token);
+               }
+
+               $this->tree_->addChildTo($this_node, $token);
+               return $this->success_();
+       }
+
+       function arguments_($parent_id, &$semantics)
+       {
+               while ($this->argument_($parent_id, &$semantics))
+                       ;
+
+               if ($this->status_ == true)
+               {
+                       $this->testlist_($parent_id, $semantics);
+               }
+
+               return $this->status_;
+       }
+
+       function argument_($parent_id, &$semantics)
+       {
+               if ($this->scanner_->nextTokenIs(array('number', 'tag')))
+               {
+                       // Check if semantics allow a number or tag
+                       $token = $this->scanner_->nextToken();
+                       if (!$semantics->validToken($token['class'], $token['text'], $token['line']))
+                       {
+                               return $this->error_($semantics->message);
+                       }
+
+                       $this->tree_->addChildTo($parent_id, $token);
+                       return $this->success_();
+               }
+
+               return $this->stringlist_($parent_id, &$semantics);
+       }
+
+       function stringlist_($parent_id, &$semantics)
+       {
+               if (!$this->scanner_->nextTokenIs('left-bracket'))
+               {
+                       return $this->string_($parent_id, &$semantics);
+               }
+
+               $token = $this->scanner_->nextToken();
+               if (!$semantics->startStringList($token['line']))
+               {
+                       return $this->error_($semantics->message);
+               }
+               $this->tree_->addChildTo($parent_id, $token);
+
+               while ($token['class'] != 'right-bracket')
+               {
+                       if (!$this->string_($parent_id, &$semantics))
+                       {
+                               return $this->status_;
+                       }
+
+                       $token = $this->scanner_->nextToken();
+
+                       if ($token['class'] != 'comma' && $token['class'] != 'right-bracket')
+                       {
+                               return $this->error_('comma or closing bracket', $token);
+                       }
+
+                       $this->tree_->addChildTo($parent_id, $token);
+               }
+
+               $semantics->endStringList();
+               return $this->success_();
+       }
+
+       function string_($parent_id, &$semantics)
+       {
+               if (!$this->scanner_->nextTokenIs(array('quoted-string', 'multi-line')))
+               {
+                       return $this->done_();
+               }
+
+               $token = $this->scanner_->nextToken();
+               if (!$semantics->validToken('string', $token['text'], $token['line']))
+               {
+                       return $this->error_($semantics->message);
+               }
+
+               $this->tree_->addChildTo($parent_id, $token);
+               return $this->success_();
+       }
+
+       function testlist_($parent_id, &$semantics)
+       {
+               if (!$this->scanner_->nextTokenIs('left-parant'))
+               {
+                       return $this->test_($parent_id, $semantics);
+               }
+
+               $token = $this->scanner_->nextToken();
+               if (!$semantics->validToken($token['class'], $token['text'], $token['line']))
+               {
+                       return $this->error_($semantics->message);
+               }
+               $this->tree_->addChildTo($parent_id, $token);
+
+               while ($token['class'] != 'right-parant')
+               {
+                       if (!$this->test_($parent_id, $semantics))
+                       {
+                               return $this->status_;
+                       }
+
+                       $token = $this->scanner_->nextToken();
+
+                       if ($token['class'] != 'comma' && $token['class'] != 'right-parant')
+                       {
+                               return $this->error_('comma or closing paranthesis', $token);
+                       }
+
+                       $this->tree_->addChildTo($parent_id, $token);
+               }
+
+               return $this->success_();
+       }
+
+       function test_($parent_id, &$semantics)
+       {
+               if (!$this->scanner_->nextTokenIs('identifier'))
+               {
+                       // There is no test
+                       return $this->done_();
+               }
+
+               // Check if semantics allow an identifier
+               $token = $this->scanner_->nextToken();
+               if (!$semantics->validToken($token['class'], $token['text'], $token['line']))
+               {
+                       return $this->error_($semantics->message);
+               }
+
+               // Get semantics for this test command
+               $this_semantics = $this->getSemantics_($token['text']);
+               if (!$this_semantics->validCommand($this->getPrevTokenText_($parent_id), $token['line']))
+               {
+                       return $this->error_($this_semantics->message);
+               }
+
+               $this_node = $this->tree_->addChildTo($parent_id, $token);
+
+               // Consume eventual argument tokens
+               if (!$this->arguments_($this_node, $this_semantics))
+               {
+                       return false;
+               }
+
+               // Check if arguments were all there
+               $token = $this->scanner_->peekNextToken();
+               if (!$this_semantics->done($token['class'], $token['text'], $token['line']))
+               {
+                       return $this->error_($this_semantics->message);
+               }
+
+               return true;
+       }
+
+       function block_($parent_id, &$semantics)
+       {
+               if ($this->commands_($parent_id, $semantics))
+               {
+                       $token = $this->scanner_->nextToken();
+       
+                       if ($token['class'] != 'block-end')
+                       {
+                               return $this->error_('closing curly brace', $token);
+                       }
+       
+                       $this->tree_->addChildTo($parent_id, $token);
+                       return $this->success_();
+               }
+               return $this->status_;
+       }
+}
+
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_scanner.inc b/gosa-plugins/mail/personal/mail/sieve/class_scanner.inc
new file mode 100644 (file)
index 0000000..3e22bb1
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+
+class Scanner
+{
+       function Scanner(&$script)
+       {
+               $this->_construct($script);
+       }
+
+       function _construct(&$script)
+       {
+               if ($script === null)
+               {
+                       return;
+               }
+
+               $this->tokenize($script);
+       }
+
+       function setCommentFunc($callback)
+       {
+               if ($callback == null || is_callable($callback))
+               {
+                       $this->commentFn_ = $callback;
+               }
+       }
+
+       function tokenize(&$script)
+       {
+               $pos = 0;
+               $line = 1;
+               $script_length = mb_strlen($script);
+
+               while ($pos < $script_length)
+               {
+                       foreach ($this->token_match_ as $class => $regex)
+                       {
+                               if (preg_match('/^'. $regex .'/', mb_substr($script, $pos), $match))
+                               {
+                                       $length = mb_strlen($match[0]);
+
+                                       if ($class != 'whitespace')
+                                       {
+                                               array_push($this->tokens_, array(
+                                                       'class' => $class,
+                                                       'text'  => chop(mb_substr($script, $pos, $length)),
+                                                       'line'  => $line,
+                                               ));
+                                       }
+                                       if ($class == 'unknown')
+                                       {
+                                               return;
+                                       }
+
+                                       $pos += $length;
+                                       $line += mb_substr_count($match[0], "\n");
+                                       break;
+                               }
+                       }
+               }
+
+               array_push($this->tokens_, array(
+                       'class' => 'script-end',
+                       'text'  => 'script-end',
+                       'line'  => $line,
+               ));
+       }
+
+       function nextTokenIs($class)
+       {
+               $offset = 0;
+               do
+               {
+                       $next = $this->tokens_[$this->tokenPos_ + $offset++]['class'];
+               }
+               while ($next == 'comment');
+
+               if (is_array($class))
+               {
+                       return in_array($next, $class);
+               }
+               else if (is_string($class))
+               {
+                       return (strcmp($next, $class) == 0);
+               }
+               return false;
+       }
+
+       function peekNextToken()
+       {
+               return $this->tokens_[$this->tokenPos_];
+       }
+
+       function nextToken()
+       {
+               $token = $this->tokens_[$this->tokenPos_++];
+               while ($token['class'] == 'comment')
+               {
+                       if ($this->commentFn_ != null)
+                       {
+                               call_user_func($this->commentFn_, $token);
+                       }
+                       $token = $this->tokens_[$this->tokenPos_++];
+               }
+               return $token;
+       }
+
+       function scriptStart()
+       {
+               return array(
+                       'class' => 'script-start',
+                       'text'  => 'script-start',
+                       'line'  => 1,
+               );
+       }
+
+       var $commentFn_ = null;
+       var $tokenPos_ = 0;
+       var $tokens_ = array();
+       var $token_match_ = array (
+               'left-bracket'   =>  '\[',
+               'right-bracket'  =>  '\]',
+               'block-start'    =>  '\{',
+               'block-end'      =>  '\}',
+               'left-parant'    =>  '\(',
+               'right-parant'   =>  '\)',
+               'comma'          =>  ',',
+               'semicolon'      =>  ';',
+               'whitespace'     =>  '[ \r\n\t]+',
+               'tag'            =>  ':[[:alpha:]_][[:alnum:]_]*(?=\b)',
+               'quoted-string'  =>  '"(?:\\[\\"]|[^\x00"])*"',
+               'number'         =>  '[[:digit:]]+(?:[KMG])?(?=\b)',
+               'comment'        =>  '(?:\/\*(?:[^\*]|\*(?=[^\/]))*\*\/|#[^\r\n]*\r?\n)',
+               'multi-line'     =>  'text:[ \t]*(?:#[^\r\n]*)?\r?\n(\.[^\r\n]+\r?\n|[^\.]*\r?\n)*\.\r?\n',
+               'identifier'     =>  '[[:alpha:]_][[:alnum:]_]*(?=\b)',
+               'unknown token'  =>  '[^ \r\n\t]+'
+       );
+}
+
+?>
\ No newline at end of file
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_semantics.inc b/gosa-plugins/mail/personal/mail/sieve/class_semantics.inc
new file mode 100644 (file)
index 0000000..1c00051
--- /dev/null
@@ -0,0 +1,613 @@
+<?php
+
+class Semantics
+{
+       var $registerExtensionFn_;
+       var $isExtensionRegisteredFn_;
+
+       var $command_;
+       var $comparator_;
+       var $matchType_;
+       var $s_;
+       var $unknown;
+       var $message;
+       var $nonTestCommands_ = '(require|if|elsif|else|reject|fileinto|redirect|stop|keep|discard|mark|unmark|setflag|addflag|removeflag)';
+       var $testsValidAfter_ = '(if|elsif|anyof|allof|not)';
+       var $testCommands_ = '(address|envelope|header|size|allof|anyof|exists|not|true|false)';
+       var $requireStrings_ = '(envelope|fileinto|reject|vacation|relational|subaddress|regex|imapflags|copy)';
+
+       function Semantics($command)
+       {
+               $this->command_ = $command;
+               $this->unknown = false;
+               switch ($command)
+               {
+
+               /********************
+                * control commands
+                */
+               case 'require':
+                       /* require <capabilities: string-list> */
+                       $this->s_ = array(
+                               'valid_after' => '(script-start|require)',
+                               'arguments' => array(
+                                       array('class' => 'string', 'list' => true, 'name' => 'require-string', 'occurrences' => '1', 'call' => 'setRequire_', 'values' => array(
+                                               array('occurrences' => '+', 'regex' => '"'. $this->requireStrings_ .'"'),
+                                               array('occurrences' => '+', 'regex' => '"comparator-i;(octet|ascii-casemap|ascii-numeric)"')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'if':
+                       /* if <test> <block> */
+                       $this->s_ = array(
+                               'valid_after' => str_replace('(', '(script-start|', $this->nonTestCommands_),
+                               'arguments' => array(
+                                       array('class' => 'identifier', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => $this->testCommands_, 'name' => 'test')
+                                       )),
+                                       array('class' => 'block-start', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => '{', 'name' => 'block')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'elsif':
+                       /* elsif <test> <block> */
+                       $this->s_ = array(
+                               'valid_after' => '(if|elsif)',
+                               'arguments' => array(
+                                       array('class' => 'identifier', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => $this->testCommands_, 'name' => 'test')
+                                       )),
+                                       array('class' => 'block-start', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => '{', 'name' => 'block')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'else':
+                       /* else <block> */
+                       $this->s_ = array(
+                               'valid_after' => '(if|elsif)',
+                               'arguments' => array(
+                                       array('class' => 'block-start', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => '{', 'name' => 'block')
+                                       ))
+                               )
+                       );
+                       break;
+
+
+               /*******************
+                * action commands
+                */
+               case 'discard':
+               case 'keep':
+               case 'stop':
+                       /* discard / keep / stop */
+                       $this->s_ = array(
+                               'valid_after' => str_replace('(', '(script-start|', $this->nonTestCommands_)
+                       );
+                       break;
+
+               case 'fileinto':
+                       /* fileinto [":copy"] <folder: string> */
+                       $this->s_ = array(
+                               'requires' => 'fileinto',
+                               'valid_after' => $this->nonTestCommands_,
+                               'arguments' => array(
+                                       array('class' => 'tag', 'occurrences' => '?', 'values' => array(
+                                               array('occurrences' => '?', 'regex' => ':copy', 'requires' => 'copy', 'name' => 'copy')
+                                       )),
+                                       array('class' => 'string', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => '".*"', 'name' => 'folder')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'mark':
+               case 'unmark':
+                       /* mark / unmark */
+                       $this->s_ = array(
+                               'requires' => 'imapflags',
+                               'valid_after' => $this->nonTestCommands_
+                       );
+                       break;
+
+               case 'redirect':
+                       /* redirect [":copy"] <address: string> */
+                       $this->s_ = array(
+                               'valid_after' => str_replace('(', '(script-start|', $this->nonTestCommands_),
+                               'arguments' => array(
+                                       array('class' => 'tag', 'occurrences' => '?', 'values' => array(
+                                               array('occurrences' => '?', 'regex' => ':copy', 'requires' => 'copy', 'name' => 'size-type')
+                                       )),
+                                       array('class' => 'string', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => '".*"', 'name' => 'address')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'reject':
+                       /* reject <reason: string> */
+                       $this->s_ = array(
+                               'requires' => 'reject',
+                               'valid_after' => $this->nonTestCommands_,
+                               'arguments' => array(
+                                       array('class' => 'string', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => '("|).*("|)', 'name' => 'reason')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'setflag':
+               case 'addflag':
+               case 'removeflag':
+                       /* setflag <flag-list: string-list> */
+                       /* addflag <flag-list: string-list> */
+                       /* removeflag <flag-list: string-list> */
+                       $this->s_ = array(
+                               'requires' => 'imapflags',
+                               'valid_after' =>$this->nonTestCommands_,
+                               'arguments' => array(
+                                       array('class' => 'string', 'list' => true, 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '+', 'regex' => '".*"', 'name' => 'key')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'vacation':
+                       /* vacation [":days" number] [":addresses" string-list] [":subject" string] [":mime"] <reason: string> */
+                       $this->s_ = array(
+                               'requires' => 'vacation',
+                               'valid_after' => $this->nonTestCommands_,
+                               'arguments' => array(
+                                       array('class' => 'tag', 'occurrences' => '*', 'values' => array(
+                                               array('occurrences' => '?', 'regex' => ':days', 'name' => 'days',
+                                                       'add' => array(
+                                                               array('class' => 'number', 'occurrences' => '1', 'values' => array(
+                                                                       array('occurrences' => '1', 'regex' => '.*', 'name' => 'period')
+                                                               ))
+                                                       )
+                                               ),
+                                               array('occurrences' => '?', 'regex' => ':addresses', 'name' => 'addresses',
+                                                       'add' => array(
+                                                               array('class' => 'string', 'list' => true, 'occurrences' => '1', 'values' => array(
+                                                                       array('occurrences' => '+', 'regex' => '".*"', 'name' => 'address')
+                                                               ))
+                                                       )
+                                               ),
+                                               array('occurrences' => '?', 'regex' => ':subject', 'name' => 'subject',
+                                                       'add' => array(
+                                                               array('class' => 'string', 'occurrences' => '1', 'values' => array(
+                                                                       array('occurrences' => '1', 'regex' => '".*"', 'name' => 'subject')
+                                                               ))
+                                                       )
+                                               ),
+                                               array('occurrences' => '?', 'regex' => ':mime', 'name' => 'mime')
+                                       )),
+                                       array('class' => 'string', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => '.*', 'name' => 'reason')
+                                       ))
+                               )
+                       );
+                       break;
+
+
+               /*****************
+                * test commands
+                */
+               case 'address':
+                       /* address [address-part: tag] [comparator: tag] [match-type: tag] <header-list: string-list> <key-list: string-list> */
+                       $this->s_ = array(
+                               'valid_after' => $this->testsValidAfter_,
+                               'arguments' => array(
+                                       array('class' => 'tag', 'occurrences' => '*', 'post-call' => 'checkTags_', 'values' => array(
+                                               array('occurrences' => '?', 'regex' => ':(is|contains|matches|count|value|regex)', 'call' => 'setMatchType_', 'name' => 'match-type'),
+                                               array('occurrences' => '?', 'regex' => ':(all|localpart|domain|user|detail)', 'call' => 'checkAddrPart_', 'name' => 'address-part'),
+                                               array('occurrences' => '?', 'regex' => ':comparator', 'name' => 'comparator',
+                                                       'add' => array(
+                                                               array('class' => 'string', 'occurrences' => '1', 'call' => 'setComparator_', 'values' => array(
+                                                                       array('occurrences' => '1', 'regex' => '"i;(octet|ascii-casemap)"', 'name' => 'comparator-string'),
+                                                                       array('occurrences' => '1', 'regex' => '"i;ascii-numeric"', 'requires' => 'comparator-i;ascii-numeric', 'name' => 'comparator-string')
+                                                               ))
+                                                       )
+                                               )
+                                       )),
+                                       array('class' => 'string', 'list' => true, 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '+', 'regex' => '".*"', 'name' => 'header')
+                                       )),
+                                       array('class' => 'string', 'list' => true, 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '+', 'regex' => '".*"', 'name' => 'key')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'allof':
+               case 'anyof':
+                       /* allof <tests: test-list>
+                          anyof <tests: test-list> */
+                       $this->s_ = array(
+                               'valid_after' => $this->testsValidAfter_,
+                               'arguments' => array(
+                                       array('class' => 'left-parant', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => '\(', 'name' => 'test-list')
+                                       )),
+                                       array('class' => 'identifier', 'occurrences' => '+', 'values' => array(
+                                               array('occurrences' => '+', 'regex' => $this->testCommands_, 'name' => 'test')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'envelope':
+                       /* envelope [address-part: tag] [comparator: tag] [match-type: tag] <envelope-part: string-list> <key-list: string-list> */
+                       $this->s_ = array(
+                               'requires' => 'envelope',
+                               'valid_after' => $this->testsValidAfter_,
+                               'arguments' => array(
+                                       array('class' => 'tag', 'occurrences' => '*', 'post-call' => 'checkTags_', 'values' => array(
+                                               array('occurrences' => '?', 'regex' => ':(is|contains|matches|count|value|regex)', 'call' => 'setMatchType_', 'name' => 'match-type'),
+                                               array('occurrences' => '?', 'regex' => ':(all|localpart|domain|user|detail)', 'call' => 'checkAddrPart_', 'name' => 'address-part'),
+                                               array('occurrences' => '?', 'regex' => ':comparator', 'name' => 'comparator',
+                                                       'add' => array(
+                                                               array('class' => 'string', 'occurrences' => '1', 'call' => 'setComparator_', 'values' => array(
+                                                                       array('occurrences' => '1', 'regex' => '"i;(octet|ascii-casemap)"', 'name' => 'comparator-string'),
+                                                                       array('occurrences' => '1', 'regex' => '"i;ascii-numeric"', 'requires' => 'comparator-i;ascii-numeric', 'name' => 'comparator-string')
+                                                               ))
+                                                       )
+                                               )
+                                       )),
+                                       array('class' => 'string', 'list' => true, 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '+', 'regex' => '".*"', 'name' => 'envelope-part')
+                                       )),
+                                       array('class' => 'string', 'list' => true, 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '+', 'regex' => '".*"', 'name' => 'key')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'exists':
+                       /* exists <header-names: string-list> */
+                       $this->s_ = array(
+                               'valid_after' => $this->testsValidAfter_,
+                               'arguments' => array(
+                                       array('class' => 'string', 'list' => true, 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '+', 'regex' => '".*"', 'name' => 'header')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'header':
+                       /* header [comparator: tag] [match-type: tag] <header-names: string-list> <key-list: string-list> */
+                       $this->s_ = array(
+                               'valid_after' => $this->testsValidAfter_,
+                               'arguments' => array(
+                                       array('class' => 'tag', 'occurrences' => '*', 'post-call' => 'checkTags_', 'values' => array(
+                                               array('occurrences' => '?', 'regex' => ':(is|contains|matches|count|value|regex)', 'call' => 'setMatchType_', 'name' => 'match-type'),
+                                               array('occurrences' => '?', 'regex' => ':comparator', 'name' => 'comparator',
+                                                       'add' => array(
+                                                               array('class' => 'string', 'occurrences' => '1', 'call' => 'setComparator_', 'values' => array(
+                                                                       array('occurrences' => '1', 'regex' => '"i;(octet|ascii-casemap)"', 'name' => 'comparator-string'),
+                                                                       array('occurrences' => '1', 'regex' => '"i;ascii-numeric"', 'requires' => 'comparator-i;ascii-numeric', 'name' => 'comparator-string')
+                                                               ))
+                                                       )
+                                               )
+                                       )),
+                                       array('class' => 'string', 'list' => true, 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '+', 'regex' => '".*"', 'name' => 'header')
+                                       )),
+                                       array('class' => 'string', 'list' => true, 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '+', 'regex' => '".*"', 'name' => 'key')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'not':
+                       /* not <test> */
+                       $this->s_ = array(
+                               'valid_after' => $this->testsValidAfter_,
+                               'arguments' => array(
+                                       array('class' => 'identifier', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => $this->testCommands_, 'name' => 'test')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'size':
+                       /* size <":over" / ":under"> <limit: number> */
+                       $this->s_ = array(
+                               'valid_after' => $this->testsValidAfter_,
+                               'arguments' => array(
+                                       array('class' => 'tag', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => ':(over|under)', 'name' => 'size-type')
+                                       )),
+                                       array('class' => 'number', 'occurrences' => '1', 'values' => array(
+                                               array('occurrences' => '1', 'regex' => '.*', 'name' => 'limit')
+                                       ))
+                               )
+                       );
+                       break;
+
+               case 'true':
+               case 'false':
+                       /* true / false */
+                       $this->s_ = array(
+                               'valid_after' => $this->testsValidAfter_
+                       );
+                       break;
+
+
+               /********************
+                * unknown commands
+                */
+               default:
+                       $this->unknown = true;
+               }
+       }
+
+       function setExtensionFuncs($setFn, $checkFn)
+       {
+               if (is_callable($setFn) && is_callable($checkFn))
+               {
+                       $this->registerExtensionFn_ = $setFn;
+                       $this->isExtensionRegisteredFn_ = $checkFn;
+               }
+       }
+
+       function setRequire_($extension)
+       {
+               call_user_func($this->registerExtensionFn_, $extension);
+               return true;
+       }
+
+       function wasRequired_($extension)
+       {
+               return call_user_func($this->isExtensionRegisteredFn_, $extension);
+       }
+
+       function setMatchType_($text)
+       {
+               // Do special processing for relational test extension
+               if ($text == ':count' || $text == ':value')
+               {
+                       if (!$this->wasRequired_('relational'))
+                       {
+                               $this->message = 'missing require for match-type '. $text;
+                               return false;
+                       }
+
+                       array_unshift($this->s_['arguments'],
+                               array('class' => 'string', 'occurrences' => '1', 'values' => array(
+                                       array('occurrences' => '1', 'regex' => '"(lt|le|eq|ge|gt|ne)"', 'name' => 'relation-string'),
+                               ))
+                       );
+               }
+               // Do special processing for regex match-type extension
+               else if ($text == ':regex' && !$this->wasRequired_('regex'))
+               {
+                       $this->message = 'missing require for match-type '. $text;
+                       return false;
+               }
+               $this->matchType_ = $text;
+               return true;
+       }
+
+       function setComparator_($text)
+       {
+               $this->comparator_ = $text;
+               return true;
+       }
+
+       function checkAddrPart_($text)
+       {
+               if ($text == ':user' || $text == ':detail')
+               {
+                       if (!$this->wasRequired_('subaddress'))
+                       {
+                               $this->message = 'missing require for tag '. $text;
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       function checkTags_()
+       {
+               if (isset($this->matchType_) &&
+                   $this->matchType_ == ':count' &&
+                   $this->comparator_ != '"i;ascii-numeric"')
+               {
+                       $this->message = 'match-type :count needs comparator i;ascii-numeric';
+                       return false;
+               }
+               return true;
+       }
+
+       function validCommand($prev, $line)
+       {
+               // Check if command is known
+               if ($this->unknown)
+               {
+                       $this->message = 'line '. $line .': unknown command "'. $this->command_ .'"';
+                       return false;
+               }
+
+               // Check if the command needs to be required
+               if (isset($this->s_['requires']) && !$this->wasRequired_($this->s_['requires']))
+               {
+                       $this->message = 'line '. $line .': missing require for command "'. $this->command_ .'"';
+                       return false;
+               }
+
+               // Check if command may appear here
+               if (!ereg($this->s_['valid_after'], $prev))
+               {
+#                      $this->message = 'line '. $line .': "'. $this->command_ .'" may not appear after "'. $prev .'"';
+#                      return false;
+               }
+
+               return true;
+       }
+
+       function validClass_($class, $id)
+       {
+               // Check if command expects any arguments
+               if (!isset($this->s_['arguments']))
+               {
+                       $this->message = $id .' where semicolon expected';
+                       return false;
+               }
+
+               foreach ($this->s_['arguments'] as $arg)
+               {
+                       if ($class == $arg['class'])
+                       {
+                               return true;
+                       }
+
+                       // Is the argument required
+                       if ($arg['occurrences'] != '?' && $arg['occurrences'] != '*')
+                       {
+                               $this->message = $id .' where '. $arg['class'] .' expected';
+                               return false;
+                       }
+
+                       if (isset($arg['post-call']) &&
+                               !call_user_func(array(&$this, $arg['post-call'])))
+                       {
+                               return false;
+                       }
+                       array_shift($this->s_['arguments']);
+               }
+
+               $this->message = 'unexpected '. $id;
+               return false;
+       }
+
+       function startStringList($line)
+       {
+               if (!$this->validClass_('string', 'string'))
+               {
+                       $this->message = 'line '. $line .': '. $this->message;
+                       return false;
+               }
+               else if (!isset($this->s_['arguments'][0]['list']))
+               {
+                       $this->message = 'line '. $line .': '. 'left bracket where '. $this->s_['arguments'][0]['class'] .' expected';
+                       return false;
+               }
+
+               $this->s_['arguments'][0]['occurrences'] = '+';
+               return true;
+       }
+
+       function endStringList()
+       {
+               array_shift($this->s_['arguments']);
+       }
+
+       function validToken($class, &$text, &$line)
+       {
+               $name = $class . ($class != $text ? " $text" : '');
+
+               // Make sure the argument has a valid class
+               if (!$this->validClass_($class, $name))
+               {
+                       $this->message = 'line '. $line .': '. $this->message;
+                       return false;
+               }
+
+               $arg = &$this->s_['arguments'][0];
+               foreach ($arg['values'] as $val)
+               {
+                       if (preg_match('/^'. $val['regex'] .'$/m', $text))
+                       {
+                               // Check if the argument value needs a 'require'
+                               if (isset($val['requires']) && !$this->wasRequired_($val['requires']))
+                               {
+                                       $this->message = 'line '. $line .': missing require for '. $val['name'] .' '. $text;
+                                       return false;
+                               }
+
+                               // Check if a possible value of this argument may occur
+                               if ($val['occurrences'] == '?' || $val['occurrences'] == '1')
+                               {
+                                       $val['occurrences'] = '0';
+                               }
+                               else if ($val['occurrences'] == '+')
+                               {
+                                       $val['occurrences'] = '*';
+                               }
+                               else if ($val['occurrences'] == '0')
+                               {
+                                       $this->message = 'line '. $line .': too many '. $val['name'] .' '. $class .'s near '. $text;
+                                       return false;
+                               }
+
+                               // Call extra processing function if defined
+                               if (isset($val['call']) && !call_user_func(array(&$this, $val['call']), $text) ||
+                                       isset($arg['call']) && !call_user_func(array(&$this, $arg['call']), $text))
+                               {
+                                       $this->message = 'line '. $line .': '. $this->message;
+                                       return false;
+                               }
+
+                               // Set occurrences appropriately
+                               if ($arg['occurrences'] == '?' || $arg['occurrences'] == '1')
+                               {
+                                       array_shift($this->s_['arguments']);
+                               }
+                               else
+                               {
+                                       $arg['occurrences'] = '*';
+                               }
+
+                               // Add argument(s) expected to follow right after this one
+                               if (isset($val['add']))
+                               {
+                                       while ($add_arg = array_pop($val['add']))
+                                       {
+                                               array_unshift($this->s_['arguments'], $add_arg);
+                                       }
+                               }
+
+                               return true;
+                       }
+               }
+
+               $this->message = 'line '. $line .': unexpected '. $name;
+               return false;
+       }
+
+       function done($class, $text, $line)
+       {
+               if (isset($this->s_['arguments']))
+               {
+                       foreach ($this->s_['arguments'] as $arg)
+                       {
+                               if ($arg['occurrences'] == '+' || $arg['occurrences'] == '1')
+                               {
+                                       $this->message = 'line '. $line .': '. $class .' '. $text .' where '. $arg['class'] .' expected';
+                                       return false;
+                               }
+                       }
+               }
+               return true;
+       }
+}
+
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieve.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieve.inc
new file mode 100644 (file)
index 0000000..c45d0f1
--- /dev/null
@@ -0,0 +1,516 @@
+<?php
+
+/*
+ * $Id: class_sieve.inc,v 1.1 2005/02/21 09:33:01 cajus Exp $ 
+ *
+ * Copyright 2001 Dan Ellis <danellis@rushmore.com>
+ *
+ * See the enclosed file COPYING for license information (GPL).  If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ */
+
+// TODO before next release:   remove ::status() and dependencies
+
+
+define ("F_NO", 0);            
+define ("F_OK", 1);
+define ("F_DATA", 2);
+define ("F_HEAD", 3);
+
+define ("EC_NOT_LOGGED_IN", 0);
+define ("EC_QUOTA", 10);
+define ("EC_NOSCRIPTS", 20);
+define ("EC_UNKNOWN", 255);
+/*
+
+SIEVE-PHP.LIB VERSION 0.0.8
+
+(C) 2001 Dan Ellis.
+
+PLEASE READ THE README FILE FOR MORE INFORMATION.
+
+Basically, this is the first re-release.  Things are much better than before.
+
+Notes:
+This program/libary has bugs.
+       .       This was quickly hacked out, so please let me know what is wrong and if you feel ambitious submit
+               a patch :).
+
+Todo:
+       .       Provide better error diagnostics.                       (mostly done with ver 0.0.5)
+       .       Allow other auth mechanisms besides plain               (in progress)
+       .       Have timing mechanism when port problems arise.         (not done yet)
+       .       Maybe add the NOOP function.                            (not done yet)
+       .       Other top secret stuff....                              (some done, believe me?)
+
+Dan Ellis (danellis@rushmore.com)
+
+This program is released under the GNU Public License.
+
+You should have received a copy of the GNU Public
+ License along with this package; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.        
+
+See CHANGES for updates since last release
+
+Contributers of patches:
+       Atif Ghaffar
+       Andrew Sterling Hanenkamp <sterling@hanenkamp.com>
+*/
+
+
+class sieve
+{
+  var $host;
+  var $port;
+  var $user;
+  var $pass;
+  var $auth_types;             /* a comma seperated list of allowed auth types, in order of preference */
+  var $auth_in_use;            /* type of authentication attempted */
+  
+  var $line;
+  var $fp;
+  var $retval;
+  var $tmpfile;
+  var $fh;
+  var $len;
+  var $script;
+
+  var $loggedin;
+  var $capabilities;
+  var $error;
+  var $error_raw;
+  var $responses;
+
+  //maybe we should add an errorlvl that the user will pass to new sieve = sieve(,,,,E_WARN)
+  //so we can decide how to handle certain errors?!?
+
+  //also add a connection type, like PLAIN, MD5, etc...
+
+
+  function get_response()
+  {
+    if($this->loggedin == false or feof($this->fp)){
+        $this->error = EC_NOT_LOGGED_IN;
+        $this->error_raw = "You are not logged in.";
+        return false;
+    }
+
+    unset($this->response);
+    unset($this->error);
+    unset($this->error_raw);
+
+    $this->line=fgets($this->fp,1024);
+    $this->token = split(" ", $this->line, 2);
+
+       if($this->token[0] == "NO"){
+               /* we need to try and extract the error code from here.  There are two possibilites: one, that it will take the form of:
+                  NO ("yyyyy") "zzzzzzz" or, two, NO {yyyyy} "zzzzzzzzzzz" */
+               $this->x = 0;
+               list($this->ltoken, $this->mtoken, $this->rtoken) = split(" ", $this->line." ", 3);
+               if($this->mtoken[0] == "{"){
+                       while($this->mtoken[$this->x] != "}" or $this->err_len < 1){
+                               $this->err_len = substr($this->mtoken, 1, $this->x);
+                               $this->x++;    
+                       }
+                       #print "<br>Trying to receive $this->err_len bytes for result<br>";
+                       $this->line = fgets($this->fp,$this->err_len);
+                       $this->error_raw[]=substr($this->line, 0, strlen($this->line) -2);    //we want to be nice and strip crlf's
+                       $this->err_recv = strlen($this->line);
+
+                       /* Ensure max loop of 1000, to keep the ui from freezing */
+                       $max = 1000;
+                       $cur = 0;
+
+                       while($this->err_recv < ($this->err_len) && ($cur < $max)){
+
+                               $cur ++;
+                               $this->line      = fgets($this->fp,4096);
+                               $this->err_recv += strlen($this->line);
+                               $this->error_raw[]=preg_replace("/\r\n/","",$this->line);    //we want to be nice and strip crlf'
+                       } 
+               } /* end if */
+               elseif($this->mtoken[0] == "("){
+                       switch($this->mtoken){
+                               case "(\"QUOTA\")":
+                    $this->error = EC_QUOTA;
+                    $this->error_raw=$this->rtoken;
+                    break;
+                default:
+                    $this->error = EC_UNKNOWN;
+                    $this->error_raw=$this->rtoken;
+                    break;
+            } /* end switch */
+        } /* end elseif */
+        else{
+            $this->error = EC_UNKNOWN;
+            $this->error_raw = $this->line;
+        }     
+        return false;
+
+    } /* end if */
+    elseif(substr($this->token[0],0,-2) == "OK"){
+         return true;
+    } /* end elseif */
+    elseif($this->token[0][0] == "{"){
+        
+        /* Unable wild assumption:  that the only function that gets here is the get_script(), doesn't really matter though */       
+
+        /* the first line is the len field {xx}, which we don't care about at this point */
+        $this->line = fgets($this->fp,1024);
+        while(substr($this->line,0,2) != "OK" and substr($this->line,0,2) != "NO"){
+            $this->response[]=$this->line;
+            $this->line = fgets($this->fp, 1024);
+        }
+        if(substr($this->line,0,2) == "OK")
+            return true;
+        else
+            return false;
+    } /* end elseif */
+    elseif($this->token[0][0] == "\""){
+
+        /* I'm going under the _assumption_ that the only function that will get here is the listscripts().
+           I could very well be mistaken here, if I am, this part needs some rework */
+
+        $this->found_script=false;        
+
+        while(substr($this->line,0,2) != "OK" and substr($this->line,0,2) != "NO"){
+            $this->found_script=true;
+            list($this->ltoken, $this->rtoken) = explode(" ", $this->line." ",2);
+               //hmmm, a bug in php, if there is no space on explode line, a warning is generated...
+           
+            if(strcmp(rtrim($this->rtoken), "ACTIVE")==0){
+                $this->response["ACTIVE"] = substr(rtrim($this->ltoken),1,-1);  
+            }
+            else
+                $this->response[] = substr(rtrim($this->ltoken),1,-1);
+            $this->line = fgets($this->fp, 1024);
+        } /* end while */
+        
+        return true;
+        
+    } /* end elseif */
+    else{
+            $this->error = EC_UNKNOWN;
+            $this->error_raw = $this->line;
+            print "<b><i>UNKNOWN ERROR (Please report this line to danellis@rushmore.com to include in future releases): $this->line</i></b><br>";
+            return false;
+    } /* end else */   
+  } /* end get_response() */
+
+  function sieve($host, $port, $user, $pass, $auth="", $auth_types="PLAIN DIGEST-MD5")
+  {
+    $this->host=$host;
+    $this->port=$port;
+    $this->user=$user;
+    $this->pass=$pass;
+    if(!strcmp($auth, ""))             /* If there is no auth user, we deem the user itself to be the auth'd user */
+        $this->auth = $this->user;
+    else
+        $this->auth = $auth;
+    $this->auth_types=$auth_types;     /* Allowed authentication types */
+    $this->fp=0;
+    $this->line="";
+    $this->retval="";
+    $this->tmpfile="";
+    $this->fh=0;
+    $this->len=0;
+    $this->capabilities="";
+    $this->loggedin=false;
+    $this->error= "";
+    $this->error_raw="";
+  }
+
+  function parse_for_quotes($string)
+  {
+      /* This function tokenizes a line of input by quote marks and returns them as an array */
+
+      $start = -1;
+      $index = 0;
+
+      for($ptr = 0; $ptr < strlen($string); $ptr++){
+          if($string[$ptr] == '"' and $string[$ptr] != '\\'){
+              if($start == -1){
+                  $start = $ptr;
+              } /* end if */
+              else{
+                  $token[$index++] = substr($string, $start + 1, $ptr - $start - 1);
+                  $found = true;
+                  $start = -1;
+              } /* end else */
+
+          } /* end if */  
+
+      } /* end for */
+
+      if(isset($token))
+          return $token;
+      else
+          return false;
+  } /* end function */            
+
+  function status($string)
+  {
+      //this should probably be replaced by a smarter parser.
+
+      /*  Need to remove this and all dependencies from the class */
+
+      switch (substr($string, 0,2)){
+          case "NO":
+              return F_NO;             //there should be some function to extract the error code from this line
+                                       //NO ("quota") "You are oly allowed x number of scripts"
+              break;
+          case "OK":
+              return F_OK;
+              break;
+          default:
+              switch ($string[0]){
+                  case "{":
+                      //do parse here for {}'s  maybe modify parse_for_quotes to handle any parse delimiter?
+                      return F_HEAD;
+                      break;
+                  default:
+                      return F_DATA;
+                      break;
+              } /* end switch */
+        } /* end switch */
+  } /* end status() */
+
+  function sieve_login()
+  {
+
+    $this->fp=@fsockopen($this->host,$this->port);
+    if($this->fp == false)
+        return false;
+    $this->line=fgets($this->fp,1024);
+
+    //Hack for older versions of Sieve Server.  They do not respond with the Cyrus v2. standard
+    //response.  They repsond as follows: "Cyrus timsieved v1.0.0" "SASL={PLAIN,........}"
+    //So, if we see IMLEMENTATION in the first line, then we are done.
+
+    if(ereg("IMPLEMENTATION",$this->line))
+    {
+      //we're on the Cyrus V2 sieve server
+      while(sieve::status($this->line) == F_DATA){
+
+          $this->item = sieve::parse_for_quotes($this->line);
+
+          if(strcmp($this->item[0], "IMPLEMENTATION") == 0)
+              $this->capabilities["implementation"] = $this->item[1];
+        
+          elseif(strcmp($this->item[0], "SIEVE") == 0 or strcmp($this->item[0], "SASL") == 0){
+
+              if(strcmp($this->item[0], "SIEVE") == 0)
+                  $this->cap_type="modules";
+              else
+                  $this->cap_type="auth";            
+
+              $this->modules = split(" ", $this->item[1]);
+              if(is_array($this->modules)){
+                  foreach($this->modules as $this->module)
+                      $this->capabilities[$this->cap_type][$this->module]=true;
+              } /* end if */
+              elseif(is_string($this->modules))
+                  $this->capabilites[$this->cap_type][$this->modules]=true;
+          }    
+          else{ 
+              $this->capabilities["unknown"][]=$this->line;
+          }    
+      $this->line=fgets($this->fp,1024);
+
+       }// end while
+    }
+    else
+    {
+        //we're on the older Cyrus V1. server  
+        //this version does not support module reporting.  We only have auth types.
+        $this->cap_type="auth";
+       
+        //break apart at the "Cyrus timsieve...." "SASL={......}"
+        $this->item = sieve::parse_for_quotes($this->line);
+
+        $this->capabilities["implementation"] = $this->item[0];
+
+        //we should have "SASL={..........}" now.  Break out the {xx,yyy,zzzz}
+        $this->modules = substr($this->item[1], strpos($this->item[1], "{"),strlen($this->item[1])-1);
+
+        //then split again at the ", " stuff.
+        $this->modules = split($this->modules, ", ");
+        //fill up our $this->modules property
+        if(is_array($this->modules)){
+            foreach($this->modules as $this->module)
+                $this->capabilities[$this->cap_type][$this->module]=true;
+        } /* end if */
+        elseif(is_string($this->modules))
+            $this->capabilites[$this->cap_type][$this->module]=true;
+    }
+
+
+
+
+    if(sieve::status($this->line) == F_NO){            //here we should do some returning of error codes?
+        $this->error=EC_UNKNOWN;
+        $this->error_raw = "Server not allowing connections.";
+        return false;
+    }
+
+    /* decision login to decide what type of authentication to use... */
+
+     /* Loop through each allowed authentication type and see if the server allows the type */
+     foreach(split(" ",$this->auth_types) as $auth_type)
+     {
+        if ($this->capabilities["auth"][$auth_type])
+        {
+            /* We found an auth type that is allowed. */
+            $this->auth_in_use = $auth_type;
+            break;
+        }
+     }
+    
+    /* Fill error message if no auth types are present */
+    if (!isset($this->capabilities["auth"])){
+        $this->error=EC_UNKNOWN;
+       $this->error_raw = "No authentication methods found - please check your sieve setup for missing sasl modules";
+       return false;
+    }
+
+     /* call our authentication program */  
+    return sieve::authenticate();
+
+  }
+
+  function sieve_logout()
+  {
+    if($this->loggedin==false)
+        return false;
+
+    fputs($this->fp,"LOGOUT\r\n");
+    fclose($this->fp);
+    $this->loggedin=false;
+    return true;
+  }
+
+  function sieve_sendscript($scriptname, $script)
+  {
+    if($this->loggedin==false)
+        return false;
+    $this->script=stripslashes($script);
+    $len=strlen($this->script);
+    fputs($this->fp, "PUTSCRIPT \"$scriptname\" {".$len."+}\r\n");
+    fputs($this->fp, "$this->script\r\n");
+  
+    return sieve::get_response();
+
+  }  
+  
+  //it appears the timsieved does not honor the NUMBER type.  see lex.c in timsieved src.
+  //don't expect this function to work yet.  I might have messed something up here, too.
+  function sieve_havespace($scriptname, $scriptsize)
+  {
+    if($this->loggedin==false)
+        return false;
+    fputs($this->fp, "HAVESPACE \"$scriptname\" $scriptsize\r\n");
+    return sieve::get_response();
+
+  }  
+
+  function sieve_setactivescript($scriptname)
+  {
+    if($this->loggedin==false)
+        return false;
+
+    fputs($this->fp, "SETACTIVE \"$scriptname\"\r\n");   
+    return sieve::get_response();
+
+  }
+  
+  function sieve_getscript($scriptname)
+  {
+    unset($this->script);
+    if($this->loggedin==false)
+        return false;
+
+    fputs($this->fp, "GETSCRIPT \"$scriptname\"\r\n");
+    return sieve::get_response();
+   
+  }
+
+
+  function sieve_deletescript($scriptname)
+  {
+    if($this->loggedin==false)
+        return false;
+
+    fputs($this->fp, "DELETESCRIPT \"$scriptname\"\r\n");    
+
+    return sieve::get_response();
+  }
+
+  
+  function sieve_listscripts() 
+   { 
+     fputs($this->fp, "LISTSCRIPTS\r\n"); 
+     sieve::get_response();            //should always return true, even if there are no scripts...
+     if(isset($this->found_script) and $this->found_script)
+         return true;
+     else{
+         $this->error=EC_NOSCRIPTS;    //sieve::getresponse has no way of telling wether a script was found...
+         $this->error_raw="No scripts found for this account.";
+         return false;
+     }
+   }
+
+  function sieve_alive()
+  {
+      if(!isset($this->fp) or $this->fp==0){
+          $this->error = EC_NOT_LOGGED_IN;
+          return false;
+      }
+      elseif(feof($this->fp)){                 
+          $this->error = EC_NOT_LOGGED_IN;
+          return false;
+      }
+      else
+          return true;
+  }
+
+  function authenticate()
+  {
+
+    switch ($this->auth_in_use) {
+    
+        case "PLAIN":
+            $auth=base64_encode("$this->user\0$this->auth\0$this->pass");
+   
+            $this->len=strlen($auth);                  
+            fputs($this->fp, "AUTHENTICATE \"PLAIN\" {".$this->len."+}\r\n");
+            fputs($this->fp, "$auth\r\n");
+
+            $this->line=fgets($this->fp,1024);         
+            while(sieve::status($this->line) == F_DATA)
+               $this->line=fgets($this->fp,1024);
+
+             if(sieve::status($this->line) == F_NO)
+               return false;
+             $this->loggedin=true;
+               return true;    
+             break;
+
+        default:
+            return false;
+            break;
+
+    }//end switch
+
+
+  }//end authenticate()
+
+
+}
+
+
+
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_End.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_End.inc
new file mode 100644 (file)
index 0000000..3bd0b04
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+class sieve_block_end 
+{
+  var $object_id= -1;
+  
+  function sieve_block_end($data = NULL,$object_id)
+  {
+    $this->object_id = $object_id;
+  }
+
+  function execute()
+  {
+    $smarty = get_smarty();
+    return($smarty->fetch(get_template_path("templates/element_block_end.tpl",TRUE,dirname(__FILE__))));
+  }
+  function check()
+  {
+    return(array());
+  }
+
+  function get_sieve_script_part()
+  {
+    return("}");
+  } 
+  function save_object()
+  {
+  }
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_Start.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_Start.inc
new file mode 100644 (file)
index 0000000..e001cdc
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+
+class sieve_block_start 
+{
+  var $object_id= -1;
+  
+  function sieve_block_start($data = NULL,$object_id)
+  {
+    $this->object_id = $object_id;
+  }
+
+  function execute()
+  {
+    $smarty = get_smarty();
+    return($smarty->fetch(get_template_path("templates/element_block_start.tpl",TRUE,dirname(__FILE__))));
+  }
+
+  function check()
+  {
+    return(array());
+  }
+
+  function save_object()
+  {
+  }
+
+  function get_sieve_script_part()
+  {
+    return("{");
+  } 
+}
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Comment.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Comment.inc
new file mode 100644 (file)
index 0000000..deaa4f3
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+
+/* Sieve comment tag */
+class sieve_comment 
+{
+  var $data = "";
+  var $object_id= -1;
+  var $small  = TRUE;
+
+  function get_sieve_script_part()
+  {
+    $str = "\n/*".$this->data."*/";
+    return($str);
+  } 
+    
+  function sieve_comment($data,$object_id)
+  {
+    $this->object_id = $object_id;
+
+    if($data === NULL){
+      $data = array('ELEMENTS' => array(array('class' => "quoted-string" ,"text" => "/*"._("Your comment here")."*/")));
+    }
+
+    foreach($data['ELEMENTS'] as $node){
+
+      $text = $node['text'];
+  
+      /* Convert \t to spaces  */ 
+      $text = preg_replace("#\t#","    ",$text);
+      
+      /* Remove comment indicator '#' but keep spaces */
+      $text = preg_replace("/^([ ]*)\#/","\\1",$text);
+     
+      /* Remove comment indicator '/ *' */ 
+      $text = preg_replace("#\/\*#","",$text);
+      
+      /* Remove comment indicator '* /' */ 
+      $text = preg_replace("#\*\/#","",$text);
+
+      $this->data .= $text."\n";
+    }
+    $this->data = rtrim($this->data)."\n";
+  }
+
+  function check()
+  {
+    return(array())  ;
+  }
+
+  function save_object()
+  {
+    if(isset($_POST['comment_'.$this->object_id])){
+      $cm = stripslashes( $_POST['comment_'.$this->object_id]);
+      $cm = preg_replace("/\*\//","* /",$cm);
+      $this->data = $cm;
+    }
+  
+    if(isset($_POST['toggle_small_'.$this->object_id])){
+      $this->small = !$this->small;
+    }
+  }
+
+  function execute()
+  {
+    $smarty = get_smarty();
+    $smarty->assign("ID", $this->object_id);
+    $smarty->assign("Small", $this->small);
+    $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__)));
+    $Comment = $this->data;
+
+    if($this->small){
+      $Comment = nl2br(preg_replace("/ /","&nbsp;",$Comment));
+    }
+    /* Create html object */ 
+    $smarty->assign("Comment",$Comment);
+    $smarty->assign("ID",$this->object_id);
+    $object = $smarty->fetch(get_template_path("templates/element_comment.tpl",TRUE,dirname(__FILE__)));    
+    $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container);
+    return($str);
+  }
+}
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Discard.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Discard.inc
new file mode 100644 (file)
index 0000000..1ee28ad
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+class sieve_discard 
+{
+  var $data = array();
+  var $object_id = -1;
+
+  function sieve_discard($data,$object_id)
+  {
+    $this->object_id = $object_id;
+  }
+
+  function get_sieve_script_part()
+  {
+    return("discard;");
+  } 
+  function check()
+  {
+    return(array())  ;
+  }
+
+    
+  function save_object()
+  {
+  
+  }
+
+  function execute()
+  {
+    $smarty = get_smarty();
+    $smarty->assign("ID", $this->object_id);
+    $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__)));
+    $object = $smarty->fetch(get_template_path("templates/element_discard.tpl",TRUE,dirname(__FILE__)));
+    $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container);
+    return($str);
+  }
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Else_Elsif.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Else_Elsif.inc
new file mode 100644 (file)
index 0000000..c02e123
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+
+/* Sieve else tag */
+class sieve_elsif extends sieve_if
+{
+  var $TYPE = "elsif";
+}
+
+class sieve_else
+{
+  var $object_id = -1;
+
+  function check()
+  {
+    return(array());
+  }
+
+  function sieve_else($data,$object_id)
+  {
+    $this->object_id = $object_id;
+  }
+
+  function save_object()
+  {
+  }
+
+  function execute()
+  {
+    $smarty = get_smarty();
+    $smarty->assign("ID", $this->object_id);
+    $object_container = $smarty->fetch(get_template_path("templates/object_container_clear.tpl",TRUE,dirname(__FILE__)));
+    $object= $smarty->fetch(get_template_path("templates/element_else.tpl",TRUE,dirname(__FILE__)));
+    $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container);
+    return($str);
+  }
+
+  function get_sieve_script_part()
+  {
+    return("else");
+  }
+}
+
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Fileinto.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Fileinto.inc
new file mode 100644 (file)
index 0000000..dc3923f
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+
+class sieve_fileinto 
+{
+  var $data     = "";
+  var $object_id= -1;
+  var $options  = array();
+  var $parent   = NULL;
+  var $user_mode= FALSE;
+
+  function save_object()
+  {
+    $mbs = $this->get_mail_boxes();
+    
+    if(isset($_POST['fileinto_'.$this->object_id])){
+      $mb = stripslashes($_POST['fileinto_'.$this->object_id]);
+
+      /* Depending on the user mode we only accept 
+       *  existing mailboxes 
+       */
+      if($this->user_mode){
+        $this->data = $mb;
+      }else{
+        if(in_array_ics($mb,$mbs)){
+          $this->data = $mb; 
+        }
+      }
+
+      /* Check Mode */
+      if(isset($_POST['user_mode_'.$this->object_id])){
+        $this->user_mode = !$this->user_mode;
+      }
+    }
+  }
+
+  function sieve_fileinto($data,$object_id,$parent)
+  {
+    $this->object_id = $object_id;
+    $this->parent = $parent;
+    $this->parent->add_require("fileinto");
+
+    $mbs = $this->get_mail_boxes();
+      
+    /* Set the default mailbox */
+    if($data === NULL){
+      $data = array('ELEMENTS' => array(array('class' => "quoted-string" ,"text" => $mbs[key($mbs)])));
+    }
+
+    /* Load element contents, should normaly be only one string 
+     *  but if we found more than one, just append the following strings.
+     */
+    for($i = 0 ; $i < count($data['ELEMENTS']) ; $i++){
+      $tmp = sieve_get_strings($data['ELEMENTS'],$i);
+      $i  = $i + $tmp['OFFSET'];
+      foreach($tmp['STRINGS'] as $str){
+        $this->data .= $str;
+      }
+    }
+
+    /* Set user mode to active, so we are able to insert 
+     *  the destination mail folder manually 
+     */
+    if(!in_array_ics($this->data,$mbs)){
+      $this->user_mode = TRUE;
+    }
+  }
+
+  function get_sieve_script_part()
+  {
+    $tmp = "";
+    $tmp.= "\"".$this->data."\", ";
+    $tmp = preg_replace("/,$/","",trim($tmp));
+    $tmp = preg_replace ("/\"\"/","\"",$tmp);
+    return("fileinto ".$tmp.";");
+  } 
+    
+  function execute()
+  {
+    $smarty = get_smarty();
+    $smarty->assign("Selected",htmlentities($this->data));
+    $smarty->assign("Boxes", $this->get_mail_boxes());
+    $smarty->assign("User_Mode", $this->user_mode);
+    $smarty->assign("ID", $this->object_id);
+    $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__)));
+    $object= $smarty->fetch(get_template_path("templates/element_fileinto.tpl",TRUE,dirname(__FILE__)));
+    $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container);
+
+    return($str);
+  }
+
+  function check()
+  {
+    return(array());
+  }
+
+  function get_mail_boxes()
+  {
+    $list  = $this->parent->parent->parent->parent->mailboxList;
+    return($list);
+  }
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_If.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_If.inc
new file mode 100644 (file)
index 0000000..cb33ae5
--- /dev/null
@@ -0,0 +1,1469 @@
+<?php
+
+
+class sieve_if 
+{
+  var $_parsed         = array();
+  var $TYPE    = "if";
+  var $object_id     = -1;
+
+  var $address_parts    = array();
+  var $comparators      = array();
+  var $match_types      = array();
+  var $operators        = array();
+  var $parent           = NULL;
+  
+  /* Initialize class 
+   *  $elements   contains all tokens that belongs to this if/else tag
+   *  $object_id  cotains an unique tag id, to be able to create uniqe html post names
+   */
+  function sieve_if($elements,$object_id,$parent)
+  {
+    $this->parent = $parent;
+    $this->object_id       = $object_id;
+  
+    /* Possible address parts we can select */
+    $this->address_parts = array( 
+        ":all"       => _("Complete address")."&nbsp;("._("Default").")",
+        ":domain"    => _("Domain part") ,
+        ":localpart" => _("Local part"));
+
+    /* comparator type */
+    $this->comparators   = array( 
+        "i;ascii-casemap" => _("Case insensitive")."&nbsp;("._("Default").")",
+        "i;octet"         => _("Case sensitive"),
+        "i;ascii-numeric" => _("Numeric"));
+
+    /* Match types */
+    $this->match_types  = array(  
+        ":is"         => _("is"),
+        ":regex"      => _("regex"),
+        ":contains"   => _("contains"),
+        ":matches"    => _("matches"),
+        ":count"      => _("count"),
+        ":value"      => _("value is"));
+
+    /* Operators */
+    $this->operators = array(     
+        "lt"  => _("less than"),
+        "le"  => _("less or equal"),
+        "eq"  => _("equals"),
+        "ge"  => _("greater or equal"),
+        "gt"  => _("greater than"),
+        "ne"  => _("not equal"));
+
+    /* Skip parsing if this element is new */
+    if($elements !== NULL){
+
+      /* Remove comments from tests */  
+      $tmp = array();
+      foreach($elements['ELEMENTS'] as $ele){
+        if($ele['class'] != "comment"){
+          $tmp[] = $ele;
+        }
+      }
+      $elements['ELEMENTS'] = $tmp;
+
+      if($elements!==NULL){
+        $this->elements = $elements;
+        $this->_parsed  = $this->_parse($elements['ELEMENTS'],1);
+      }
+    }
+  }
+
+
+  /* Returns the sieve script for this 
+   *  if/else tag.
+   */
+  function get_sieve_script_part()
+  {
+    $tmp = $this->TYPE." ".$this->get_sieve_script_part_recursive($parsed = NULL,$id = 1,$obj_id=1);
+    return($tmp);
+  } 
+
+
+  /* Return error msgs */
+  function check()
+  {
+    $check = $this->check_recursive();
+    return($check);
+  }
+
+  /* Recursivly fetch all error msgs */
+  function check_recursive($parsed = NULL,$id = 1,$obj_id=1)
+  {
+    $ret = array();
+    if($parsed === NULL){
+      $parsed = $this->_parsed;
+    }
+
+    if($parsed === NULL) {
+        return(array(_("Can't save empty tests.")));
+    }
+
+    /* Walk through all elements */
+    foreach($parsed as $key => $data){
+
+      /* Create elements */
+      switch($key)
+      {
+        /*******************
+         * Allof / Anyof
+         *******************/
+        case "anyof" :
+        case "allof" :
+        { 
+          foreach($data as $key2 => $dat){
+            if(($key2 === "Inverse") && ($key2 == "Inverse")){
+              continue;
+            }
+            $msgs = $this->check_recursive($dat, ($id +1),$key2);
+
+            foreach($msgs as $msg){
+              $ret[] = $msg;
+            }
+          }
+          break;
+        }
+
+        /*******************
+         * True / False
+         *******************/
+
+        case "true" :
+        case "false" : 
+        {
+          /* Can't fail anyway */
+          break;
+        }
+    
+        /*******************
+         * Default
+         *******************/
+
+        default: 
+        {
+          if(isset($data['LastError']) && !empty($data['LastError'])){
+            $ret[] = $data['LastError'];
+          }
+        }
+      }
+    }
+    return($ret);
+  }
+
+  /* Recursivly create a sieve script out of the given 
+   *  tags and tokens provided by $parsed.
+   *  $id       specifies the depth of the current element.
+   *  $obj_id   is the current tag-id handled by this function
+   */
+  function get_sieve_script_part_recursive($parsed = NULL,$id = 1,$obj_id=1)
+  {
+    $script ="";
+    if($parsed === NULL){
+      $parsed = $this->_parsed;
+    }
+
+
+    if(!is_array($parsed)){
+      return;
+    }
+
+    /* Walk through all elements */
+    foreach($parsed as $key => $data){
+
+      /* Create Inverse Tag */
+      if(is_array($data) && isset($data['Inverse']) && $data['Inverse']){
+        $Inverse = TRUE;
+      }else{
+        $Inverse = FALSE;
+      }
+
+      /* Create elements */
+      switch($key)
+      {
+
+        /*******************
+         * True / False
+         *******************/
+
+        case "true" :
+        case "false" :
+        {
+          /* Invert this test if required */
+          if($Inverse){
+            $script .= "not ";
+          }
+          $script .= $key;
+          break;
+        }
+
+
+        /*******************
+         * Address
+         *******************/
+
+        case "address" :   
+        {
+          /* [not] address 
+                        [address-part: tag] 
+                        [comparator: tag] 
+                        [match-type: tag] 
+                        <header-list: string-list> 
+                        <key-list: string-list> 
+          */
+
+          /* Invert this test if required */
+          if($Inverse){
+            $script .= "not ";
+          }
+  
+          $script .="address ";
+          /* Add address part tag */ 
+          if(!empty($data['Address_Part']) && $data['Address_Part'] != ":all"){
+            $script .= $data['Address_Part']." ";
+          }
+
+          /* Add comparator */
+          if(!empty($data['Comparator']) && $data['Comparator'] != ""){
+            $script .= preg_replace('/\"\"/',"\"", ":comparator \"".$data['Comparator']."\" ");
+          }
+    
+          /* Add match type */
+          $script .= $data['Match_type']." ";
+
+          /* Add special match type for count and value */
+          if(in_array($data['Match_type'], array(":value",":count")) && !empty($data['Match_type_value'])) {
+            $script .= sieve_create_strings($data['Match_type_value'])." ";
+          }
+
+          $script .= sieve_create_strings($data['Key_List']);
+          $script .= " ";
+          $script .= sieve_create_strings($data['Value_List']);
+          break;
+        }
+
+
+        /*******************
+         * Header
+         *******************/
+
+        case "header" :   
+        {
+          /* [not] header   
+                [comparator: tag] 
+                [match-type: tag] 
+                <header-names: string-list> 
+                <key-list: string-list>
+          */
+
+          /* Invert ? */
+          if($Inverse){
+            $script .= "not ";
+          }
+  
+          $script .="header ";
+          /* Add address part tag */ 
+          if(!empty($data['Address_Part']) && $data['Address_Part'] != ":all"){
+            $script .= $data['Address_Part']." ";
+          }
+
+          /* Add comparator */
+          if(!empty($data['Comparator']) && $data['Comparator'] != ""){
+            $script .= preg_replace('/\"\"/',"\"", ":comparator \"".$data['Comparator']."\" ");
+          }
+    
+          /* Add match type */
+          $script .= $data['Match_type']." ";
+
+          /* Add special match type for count and value */
+          if(in_array($data['Match_type'], array(":value",":count")) && !empty($data['Match_type_value'])) {
+            $script .= sieve_create_strings($data['Match_type_value'])." ";
+          }
+
+          $script .= sieve_create_strings($data['Key_List']);
+          $script .= " ";
+          $script .= sieve_create_strings($data['Value_List']);
+          break;
+        }
+
+
+        /*******************
+         * Envelope
+         *******************/
+
+        case "envelope" :   
+        {
+          /* [not]  envelope 
+                    [address-part: tag] 
+                    [comparator: tag] 
+                    [match-type: tag] 
+                    <envelope-part: string-list> 
+                    <key-list: string-list> 
+          */
+
+          /* Invert */
+          if($Inverse){
+            $script .= "not ";
+          }
+  
+          $script .="envelope ";
+          /* Add address part tag */ 
+          if(!empty($data['Address_Part']) && $data['Address_Part'] != ":all"){
+            $script .= $data['Address_Part']." ";
+          }
+
+          /* Add comparator */
+          if(!empty($data['Comparator']) && $data['Comparator'] != ""){
+            $script .= preg_replace('/\"\"/',"\"", ":comparator \"".$data['Comparator']."\" ");
+          }
+    
+          /* Add match type */
+          $script .= $data['Match_type']." ";
+
+          /* Add special match type for count and value */
+          if(in_array($data['Match_type'], array(":value",":count")) && !empty($data['Match_type_value'])) {
+            $script .= sieve_create_strings($data['Match_type_value'])." ";
+          }
+
+          $script .= sieve_create_strings($data['Key_List']);
+          $script .= " ";
+          $script .= sieve_create_strings($data['Value_List']);
+          break;
+        }
+
+
+        /*******************
+         * Exists
+         *******************/
+        case "exists" : 
+        {
+          /* [not] exists 
+              <header-names: string-list> 
+          */
+
+          /* Invert ? */
+          if($Inverse){
+            $script .= "not ";
+          }
+
+          $script .= "exists ".sieve_create_strings($data['Values']);
+          break;
+        }
+
+
+        /*******************
+         * Size
+         *******************/
+        case "size" : 
+        {
+          /* [not] size 
+                <":over" / ":under"> 
+                <limit: number> 
+          */
+
+          /* Invert ? */
+          if($Inverse){
+            $script .= "not ";
+          }
+          /* Add size test */ 
+          $script .="size ";
+          $script .=$data['Match_type']." ";
+          foreach($data['Value_List'] as $val){
+            $script .= $val." ";
+          }
+          break;
+        }
+
+
+        /*******************
+         * Allof
+         *******************/
+        case "anyof" :
+        case "allof" :
+        {
+          /* allof <tests: test-list>
+             anyof <tests: test-list> */
+
+          /* Add spaces, to indent the code.*/ 
+          $block = "\n";
+          for($i = 0 ; $i < $id ; $i ++){
+            $block .= SIEVE_INDENT_TAB;
+          }          
+
+          /* Add allof/anyof tag */
+          if($Inverse){
+            $script .= "not ";
+          }
+          $script.= $key." ( ";
+
+          /* Add each test parameter */
+          foreach($data as $key2 => $dat){
+            if(($key2 === "Inverse") && ($key2 == "Inverse")){
+              continue;
+            }
+            $script.= $block.$this->get_sieve_script_part_recursive($dat, ($id +1),$key2).", ";
+          }
+    
+          /* Remove last _,_ and close the tag */
+          $script = preg_replace("/,$/","",trim($script));
+          $script.= $block.")";
+          break ;
+        }
+
+        default :
+        {
+          $script .= "THERE IS SOME IMPLEMENTATION MISSING FOR SIEVE SCRIPT CREATION :".$key;
+        }
+      }
+    }
+    return($script);
+  }
+
+  
+  function add_test($data,$type)
+  {
+    switch($type)
+    {
+      case "header" : 
+      case "address" : 
+      case "envelope" : 
+      {
+        /* Add to Tree */
+        $values = array(        "Inverse"         => FALSE,
+                                "Comparator"      => "",
+                                "Expert"          => FALSE,
+                                "LastError"       => "",
+                                "Match_type"      => ":contains",
+                                "Match_type_value"=> "",
+                                "Key_List"        => array(_("emtpy")),
+                                "Value_List"      => array(_("empty"))) ;
+        if($type == "address"){
+          $values["Address_Part"]    = ":all";
+        }
+        $data[$type]=$values;
+
+        $this->parent->add_require("relational");
+        if($type == "envelope"){
+          $this->parent->add_require("envelope");
+        }
+    
+
+        break;
+      }
+      case "allof" :
+      case "anyof" :
+      {
+        $data[$type] = array("Inverse" => FALSE);
+        break;
+      }
+      case "size" :
+      {
+        $tmp= array( 
+            "Inverse"    => FALSE,
+            "Match_type" => ":over",
+            "Value_List" => array("1M"));
+
+        $tmp['LastError'] = "";
+        $data[$type] = $tmp;
+        break;
+      }
+      case "true":
+      {
+        $data['true'] = "true";
+        $data['true']['LastError'] = "";
+        break;
+      }
+      case "false":
+      {
+        $data['false'] = "false";
+        $data['false']['LastError'] = "";
+        break;
+      }
+      case "exists" :
+      {
+        $data['exists'] = array('Inverse' => FALSE,
+                                'Values'  => array(_("Nothing specified right now")),
+                                'LastError' => "");
+        break;
+      }
+      default : echo "Still buggy ";exit;
+    }
+
+    return($data);
+  }
+
+
+  /* Ensure that all changes made on the ui 
+   *  will be saved. 
+   */
+  function save_object()
+  {
+  
+    if(isset($_POST['add_type']) && isset($_POST["test_type_to_add_".$this->object_id])){
+      $this->_parsed = $this->add_test($this->_parsed,$_POST["test_type_to_add_".$this->object_id]);
+    }
+
+    $tmp = $this->save_object_recursive($parsed = NULL,$id = 1,$obj_id=1);
+    $this->_parsed = $tmp;
+  }
+
+
+  /* Recursivly save all ui changes for the 
+   *  tags and tokens provided by $parsed.
+   *  $id       specifies the depth of the current element.
+   *  $obj_id   is the current tag-id handled by this function
+   */
+  function save_object_recursive($parsed = NULL,$id = 1,$obj_id=1)
+  {
+    /* Variable initialization */ 
+    $ret ="";
+    if($parsed === NULL){
+      $parsed = $this->_parsed;
+    }
+
+    if(!is_array($parsed)) {
+      return;
+    }
+
+    /* Walk through all elements */
+    foreach($parsed as $key => $data){
+
+      /* Id used to have unique html names */
+      $element_id = $this->object_id."_".$id."_".$obj_id;
+      
+      foreach($_POST as $name => $value){
+        if(preg_match("/Remove_Test_Object_".$element_id."_(x|y)/",$name)) {
+          return(false); 
+        }
+      }
+
+      
+      if(isset($_POST['add_type']) && isset($_POST["test_type_to_add_".$element_id])){
+        $parsed[$key][] = $this->add_test(array(),$_POST["test_type_to_add_".$element_id]);
+      }
+
+      /* Create elements */
+      switch($key)
+      {
+        /*******************
+         * Address 
+         *******************/
+
+        case "envelope" :
+        case "header" : 
+        case "address" : 
+        {
+          /* [not] address 
+                        [address-part: tag] 
+                        [comparator: tag] 
+                        [match-type: tag] 
+                        <header-list: string-list> 
+                        <key-list: string-list> 
+          */
+
+          /* Possible address parts we can select */
+          $address_parts = $this->address_parts;
+          $comparators   = $this->comparators;
+          $match_types   = $this->match_types; 
+          $operators     = $this->operators;
+
+          $parsed[$key]['LastError'] = "";
+
+          /* Toggle Inverse ? */
+          if(isset($_POST['toggle_inverse_'.$element_id])){
+            $parsed[$key]['Inverse'] = !$parsed[$key]['Inverse'];
+          }
+
+          /* Check if we want to toggle the expert mode */
+          if(isset($_POST['Toggle_Expert_'.$element_id])){
+            $parsed[$key]['Expert'] = !$parsed[$key]['Expert'];
+          }
+
+          /* Get address part */
+          if(isset($_POST['address_part_'.$element_id])){
+            $ap = $_POST['address_part_'.$element_id];
+
+            if(!isset($address_parts[$ap])){
+              $parsed[$key]['LastError'] = _("Invalid type of address part.") ;
+            }
+            $parsed[$key]['Address_Part'] = $ap;
+          }
+
+          /* Check if match type has changed */
+          if(isset($_POST['matchtype_'.$element_id])){
+            $mt = $_POST['matchtype_'.$element_id];
+
+            if(!isset($match_types[$mt])){
+              $parsed[$key]['LastError'] = _("Invalid match type given.");
+            }
+            if($mt == ":regex"){
+              $this->parent->add_require("regex");
+            }
+            if($mt == ":count"){
+              $this->parent->add_require("comparator-i;ascii-numeric");
+            }
+            $parsed[$key]['Match_type'] = $mt;
+          }
+
+          /* Get the comparator tag, if posted */
+          if(isset($_POST['comparator_'.$element_id])){
+            $cp = $_POST['comparator_'.$element_id];
+
+            if(!isset($comparators[$cp])){
+              $parsed[$key]['LastError'] = _("Invalid operator given.");
+            }
+            $parsed[$key]['Comparator'] = $cp;
+
+            if($cp == "i;ascii-numeric"){
+              $this->parent->add_require("comparator-i;ascii-numeric");
+            }
+          }
+
+          /* In case of :count and :value match types 
+           *  we have a special match operator we should save.
+           */
+          if(in_array($parsed[$key]['Match_type'],array(":value",":count"))){
+            if(isset($_POST['operator_'.$element_id])){
+              $op = $_POST['operator_'.$element_id];
+
+              if(!isset($operators[$op])){
+                $parsed[$key]['LastError'] = _("Please specify a valid operator.");
+              }
+              $parsed[$key]['Match_type_value'] = $op;
+            }
+          }
+
+          /* Get the address fields we should check, they are seperated by , */
+          if(isset($_POST['keys_'.$element_id])){
+            $vls = stripslashes($_POST['keys_'.$element_id]);
+            $tmp = array();
+
+            $tmp2 = split(",",$vls);
+            foreach($tmp2 as $val){
+              $tmp[] = trim($val);
+  
+              if(preg_match("/\"/",$val)){
+                $parsed[$key]['LastError'] = _("Invalid character found in address attribute. Quotes are not allowed here.");
+              }
+            }
+            $parsed[$key]['Key_List'] = $tmp;
+          }
+
+          /* Get the values should check for, they are seperated by , */
+          if(isset($_POST['values_'.$element_id])){
+            $vls = stripslashes($_POST['values_'.$element_id]);
+            $tmp = array();
+
+            $tmp2 = split(",",$vls);
+            foreach($tmp2 as $val){
+              $tmp[] = trim($val);
+              if(preg_match("/\"/",$val)){
+                $parsed[$key]['LastError'] = _("Invalid character found in value attribute. Quotes are not allowed here.");
+              }
+            }
+            $parsed[$key]['Value_List'] = $tmp;
+          }
+          break;
+        }
+        /*******************
+         * TRUE FALSE 
+         *******************/
+
+        case "true" :
+        case "false" : 
+        {
+          $name = 'boolean_'.$element_id;
+          if(isset($_POST[$name])){
+            $key2 = $_POST[$name];
+            
+            if($key != $key2) {
+              $parsed = array($key2 => $key2); 
+            }
+          }
+          break;
+        }
+
+        /*******************
+         * Exists 
+         *******************/
+
+        case "exists" :
+        {
+          /* Toggle Inverse ? */
+          if(isset($_POST['toggle_inverse_'.$element_id])){
+            $parsed[$key]['Inverse'] = !$parsed[$key]['Inverse'];
+          }
+
+          /* get list of match values */
+          if(isset($_POST['Values_'.$element_id])){
+            $vls = stripslashes($_POST['Values_'.$element_id]);
+            $tmp = array();          
+  
+            $tmp2 = split(",",$vls);
+            foreach($tmp2 as $val){
+              $tmp[] = "\"".trim(preg_replace("/\"/","",$val))."\"";
+            }
+            $parsed['exists']['Values'] = $tmp;
+          }
+          break;
+        }
+
+        /*******************
+         * Size 
+         *******************/
+
+        case "size" :
+        {
+          $Match_types = array( ":over" => _("greater than") ,
+                                ":under" => _("lower than"));
+
+          $Units       = array( "M" => _("Megabyte"),
+                                "K" => _("Kilobyte"),
+                                ""  => _("Bytes"));
+
+          /* Toggle Inverse ? */
+          if(isset($_POST['toggle_inverse_'.$element_id])){
+            $parsed[$key]['Inverse'] = !$parsed[$key]['Inverse'];
+          }
+
+          /* Reset error */
+          $parsed[$key]['LastError'] ="";
+
+          /* Get match type */
+          if(isset($_POST['Match_type_'.$element_id])){
+            $mt = $_POST['Match_type_'.$element_id];
+            if(!isset($Match_types[$mt])){
+              $parsed[$key]['LastError'] = _("Please select a valid match type in the list box below.");
+            }
+            $parsed[$key]['Match_type'] = $mt;
+          }
+
+          /* Get old values */
+          $value = preg_replace("/[^0-9]*$/","",$parsed[$key]['Value_List'][0]);
+          $unit  = preg_replace("/^[0-9]*/","",$parsed[$key]['Value_List'][0]);
+
+          /* Get value */
+          if(isset($_POST['Value_'.$element_id])){
+            $vl = $_POST['Value_'.$element_id];
+         
+            if(!(is_numeric($vl) && preg_match("/^[0-9]*$/",$vl))){
+              $parsed[$key]['LastError'] = _("Only numeric values are allowed here.");
+            }
+            $value = preg_replace("/[^0-9]/","",$vl);
+          }        
+
+          /* Get unit */
+          if(isset($_POST['Value_Unit_'.$element_id])){
+            $ut = $_POST['Value_Unit_'.$element_id];
+       
+            if(!isset($Units[$ut])){
+              $parsed[$key]['LastError'] = _("No valid unit selected");
+            }
+            $unit = $ut;
+          }       
+          $parsed[$key]['Value_List'] = array(); 
+          $parsed[$key]['Value_List'][0] = $value.$unit;
+          break;
+        }
+
+        /*******************
+         * Allof 
+         *******************/
+     
+        case "allof" : 
+        {
+          if(isset($_POST['toggle_inverse_'.$element_id])){
+            $parsed[$key]['Inverse'] = !$parsed[$key]['Inverse'];
+          }
+          foreach($data as $key2 => $dat){
+            if(($key2 === "Inverse") && ($key2 == "Inverse")){
+              continue;
+            }
+            $tmp_data = $this->save_object_recursive($dat, ($id +1),$key2."-".$obj_id);
+            if($tmp_data != false){
+              $parsed[$key][$key2] = $tmp_data;
+            }else{
+              unset( $parsed[$key][$key2]);
+            }
+          }
+          break ;
+        } 
+
+        /*******************
+         * Anyof 
+         *******************/
+     
+        case "anyof" : 
+        {
+          if(isset($_POST['toggle_inverse_'.$element_id])){
+            $parsed[$key]['Inverse'] = !$parsed[$key]['Inverse'];
+          }
+          foreach($data as $key2 => $dat){
+            if(($key2 === "Inverse") && ($key2 == "Inverse")){
+              continue;
+            }
+            $tmp_data = $this->save_object_recursive($dat, ($id +1),$key2."-".$obj_id);
+            if($tmp_data != false){
+              $parsed[$key][$key2] = $tmp_data;
+            }else{
+              unset( $parsed[$key][$key2]);
+            }
+          }
+          break ;
+        } 
+      }
+    } 
+    return($parsed);
+  }  
+
+
+  /* Return html element for IF */ 
+  function execute()
+  {
+    /* Create title */
+    $name  = "<img alt='' src='images/small_filter.png' class='center'>";
+    $name .= "<b>"._("Condition")."</b>";
+    if($this->TYPE == "if"){
+      $name .= "&nbsp;-&nbsp;"._("If");
+    }elseif($this->TYPE == "elsif"){
+      $name .= "&nbsp;-&nbsp;"._("Else If");
+    }else{
+      $name .= "&nbsp;-&nbsp;"._("Else");
+    }
+
+    $smarty = get_smarty();
+    $smarty->assign("ID", $this->object_id);
+
+    /* Get navigation element container */
+    $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__)));
+
+    $smarty->assign("Name", $name);
+    $smarty->assign("Contents", $this->get_as_html());
+
+    if($this->TYPE == "if"){
+      $object = $smarty->fetch(get_template_path("templates/element_if.tpl",TRUE,dirname(__FILE__)));
+    }else{
+      $object = $smarty->fetch(get_template_path("templates/element_elsif.tpl",TRUE,dirname(__FILE__)));
+    }
+    $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container);
+    return($str);
+  }
+
+  
+  /* Returns all elements as html */
+  function get_as_html($parsed = NULL,$id = 1,$obj_id=1)
+  {
+    $ret ="";
+    if($parsed === NULL){
+      $parsed = $this->_parsed;
+    }
+
+    if((!is_array($parsed)) || !count($parsed)) {
+      $smarty = get_smarty();
+      $smarty->assign("ID",$this->object_id);
+      $smarty->assign("DisplayAdd",TRUE);
+      $smarty->assign("DisplayDel",FALSE);
+      $str = $smarty->fetch(get_template_path("templates/object_test_container.tpl",TRUE,dirname(__FILE__)));
+      $ret .= preg_replace("/%%OBJECT_CONTENT%%/",_("Empty"),$str);
+      return($ret);
+    }
+
+    /* Walk through all elements */
+    foreach($parsed as $key => $data){
+
+      /* Create Inverse Tag */
+      if(is_array($data) && isset($data['Inverse']) && $data['Inverse']){
+        $Inverse = TRUE;
+      }else{
+        $Inverse = FALSE;
+      }
+
+      /* Id used to have unique html names */
+      $element_id = $this->object_id."_".$id."_".$obj_id;
+
+      /* Create elements */
+      switch($key)
+      {
+  
+        /*******************
+         * TRUE FALSE 
+         *******************/
+
+        case "true" :
+        case "false" : 
+        { 
+          /* Inverse element if required */
+          if($Inverse){        
+            if($key == "true"){
+              $key = "false";
+            }else{
+              $key = "true";
+            }           
+          }
+
+          /* Get template */
+          $smarty = get_smarty();
+          $smarty->assign("values"    , array("false" => _("False"), "true" => _("True")));
+          $smarty->assign("selected"  , $key); 
+          $smarty->assign("ID"  , $element_id); 
+          $ret .= $smarty->fetch(get_template_path("templates/element_boolean.tpl",TRUE,dirname(__FILE__)));
+          break;
+        }
+
+
+        /*******************
+         * Header 
+         *******************/
+
+        case "header": 
+        {
+          $address_parts = $this->address_parts;
+          $comparators   = $this->comparators;
+          $match_types   = $this->match_types; 
+          $operators     = $this->operators;
+
+          $smarty = get_smarty();
+          $smarty->assign("comparators",$comparators);
+          $smarty->assign("match_types",$match_types);
+          $smarty->assign("operators",$operators);
+          $smarty->assign("LastError",$data['LastError']);
+          $smarty->assign("match_type", $data['Match_type']);
+          $smarty->assign("operator"  , preg_replace("/\"/","",$data['Match_type_value']));
+          $smarty->assign("comparator", preg_replace("/\"/","",$data['Comparator']));
+
+          $keys = "";
+          foreach($data['Key_List'] as $key){
+            $keys .= $key.", ";
+          }
+          $keys = preg_replace("/,$/","",trim($keys));
+   
+          $values = "";
+          foreach($data['Value_List'] as $key){
+            $values .= $key.", ";
+          }
+          $values = preg_replace("/,$/","",trim($values));
+
+          $smarty->assign("keys",$keys);
+          $smarty->assign("Inverse",$Inverse);
+          $smarty->assign("values",$values);
+          $smarty->assign("Expert", $data['Expert']);
+          $smarty->assign("ID"  , $element_id); 
+          $ret .= $smarty->fetch(get_template_path("templates/element_header.tpl",TRUE,dirname(__FILE__)));
+          break;
+        }
+
+
+        /*******************
+         * Envelope 
+         *******************/
+
+        case "envelope":
+        {
+          $address_parts = $this->address_parts;
+          $comparators   = $this->comparators;
+          $match_types   = $this->match_types; 
+          $operators     = $this->operators;
+
+          $smarty = get_smarty();
+          $smarty->assign("Inverse",$Inverse);
+          $smarty->assign("comparators",$comparators);
+          $smarty->assign("Expert", $data['Expert']);
+          $smarty->assign("match_types",$match_types);
+          $smarty->assign("operators",$operators);
+          $smarty->assign("LastError",$data['LastError']);
+          $smarty->assign("match_type", $data['Match_type']);
+          $smarty->assign("operator"  , preg_replace("/\"/","",$data['Match_type_value']));
+          $smarty->assign("comparator", preg_replace("/\"/","",$data['Comparator']));
+
+          $keys = "";
+          foreach($data['Key_List'] as $key){
+            $keys .= $key.", ";
+          }
+          $keys = preg_replace("/,$/","",trim($keys));
+
+          $values = "";
+          foreach($data['Value_List'] as $key){
+            $values .= $key.", ";
+          }
+          $values = preg_replace("/,$/","",trim($values));
+          $smarty->assign("keys",$keys);
+          $smarty->assign("values",$values);
+
+          $smarty->assign("ID"  , $element_id); 
+          $ret .= $smarty->fetch(get_template_path("templates/element_envelope.tpl",TRUE,dirname(__FILE__)));
+          break;
+        }
+
+
+        /*******************
+         * Address 
+         *******************/
+
+        case "address" : 
+        {
+          $address_parts = $this->address_parts;
+          $comparators   = $this->comparators;
+          $match_types   = $this->match_types; 
+          $operators     = $this->operators;
+
+          $smarty = get_smarty();
+          $smarty->assign("Inverse",$Inverse);
+          $smarty->assign("address_parts",$address_parts);
+          $smarty->assign("comparators",$comparators);
+          $smarty->assign("match_types",$match_types);
+          $smarty->assign("LastError",$data['LastError']);
+          $smarty->assign("operators",$operators);
+          $smarty->assign("match_type", $data['Match_type']);
+          $smarty->assign("operator"  , preg_replace("/\"/","",$data['Match_type_value']));
+          $smarty->assign("comparator", preg_replace("/\"/","",$data['Comparator']));
+          $smarty->assign("address_part", $data['Address_Part']);
+          $smarty->assign("Expert", $data['Expert']);
+        
+          $keys = "";
+          foreach($data['Key_List'] as $key){
+            $keys .= $key.", ";
+          }
+          $keys = preg_replace("/,$/","",trim($keys));
+   
+          $values = "";
+          foreach($data['Value_List'] as $key){
+            $values .= $key.", ";
+          }
+          $values = preg_replace("/,$/","",trim($values));
+
+          $smarty->assign("keys",$keys);
+          $smarty->assign("values", $values);
+          $smarty->assign("ID"  , $element_id); 
+          $str = $smarty->fetch(get_template_path("templates/element_address.tpl",TRUE,dirname(__FILE__)));
+          $ret .= $str;
+          break;
+        }
+      
+
+        /*******************
+         * Size 
+         *******************/
+        
+        case "size" : 
+        {
+          $Match_types = array( ":over" => _("greater than") , 
+                                ":under" => _("lower than"));
+
+          $Units       = array( "M" => _("Megabyte"),
+                                "K" => _("Kilobyte"),
+                                ""  => _("Bytes"));
+
+          $Match_type   = $data['Match_type'];
+          $Value        = preg_replace("/[^0-9]/","",$data['Value_List'][0]);
+          $Value_Unit   = preg_replace("/[0-9]/","",$data['Value_List'][0]);
+       
+          $LastError = "";
+          if(isset($data['LastError'])){
+            $LastError = $data['LastError'];
+          }
+          $smarty = get_smarty();
+          $smarty->assign("Inverse",$Inverse);
+          $smarty->assign("LastError",$LastError);
+          $smarty->assign("Match_types",$Match_types);
+          $smarty->assign("Units",$Units);
+          $smarty->assign("Match_type",$Match_type);
+          $smarty->assign("Value",$Value);
+          $smarty->assign("Value_Unit",$Value_Unit);
+          $smarty->assign("ID"  , $element_id); 
+          $ret .= $smarty->fetch(get_template_path("templates/element_size.tpl",TRUE,dirname(__FILE__)));
+          break;
+        }
+        
+        /*******************
+         * Exists 
+         *******************/
+        
+        case "exists" : 
+        {
+          $LastError = "";
+          if(isset($data['LastError'])){
+            $LastError = $data['LastError'];
+          }
+          $Values = "";
+          foreach($data['Values'] as $val){
+            $Values .= $val.", ";
+          }
+          $Values = preg_replace("/,$/","",trim($Values));
+
+          $smarty = get_smarty();
+          $smarty->assign("LastError",$LastError);
+          $smarty->assign("Values",$Values);
+          $smarty->assign("Inverse",$Inverse);
+          $smarty->assign("ID"  , $element_id); 
+          $ret .= $smarty->fetch(get_template_path("templates/element_exists.tpl",TRUE,dirname(__FILE__)));
+          break;
+        }
+  
+
+        /*******************
+         * All of   
+         *******************/
+
+        case "allof" : 
+        {
+          $Contents = ""; 
+          foreach($data as $key => $dat){
+            if(($key === "Inverse") && ($key == "Inverse")){
+              continue;
+            }
+            $Contents .=        $this->get_as_html($dat, ($id +1),$key."-".$obj_id);
+          }
+
+          $smarty = get_smarty();
+          $smarty->assign("ID"  , $element_id); 
+          $smarty->assign("DisplayAdd",TRUE);
+          $smarty->assign("DisplayDel",FALSE);
+          $cont_tmp = $smarty->fetch(get_template_path("templates/object_test_container.tpl",TRUE,dirname(__FILE__)));
+          $cont_tmp = preg_replace("/%%OBJECT_CONTENT%%/","<b>"._("Click here to add a new test")."</b>",$cont_tmp);
+
+          $smarty->assign("Inverse",$Inverse);
+          $smarty->assign("Contents",$cont_tmp.$Contents);
+          $smarty->assign("ID"  , $element_id); 
+          $allof_tmp = $smarty->fetch(get_template_path("templates/element_allof.tpl",TRUE,dirname(__FILE__)));
+
+          $ret = $allof_tmp;
+          break ;
+        } 
+
+
+        /*******************
+         * Any of   
+         *******************/
+
+        case "anyof" : 
+        {
+          $Contents = ""; 
+          foreach($data as $key => $dat){
+            if(($key === "Inverse") && ($key == "Inverse")){
+              continue;
+            }
+            $Contents .=        $this->get_as_html($dat, ($id +1),$key."-".$obj_id);
+          }
+          $smarty = get_smarty();
+          $smarty->assign("ID"  , $element_id); 
+          $smarty->assign("DisplayAdd",TRUE);
+          $smarty->assign("DisplayDel",FALSE);
+          $cont_tmp = $smarty->fetch(get_template_path("templates/object_test_container.tpl",TRUE,dirname(__FILE__)));
+          $cont_tmp = preg_replace("/%%OBJECT_CONTENT%%/",_("Click here to add a new test"),$cont_tmp);
+
+          $smarty->assign("Inverse",$Inverse);
+          $smarty->assign("Contents",$cont_tmp.$Contents);
+          $allof_tmp = $smarty->fetch(get_template_path("templates/element_anyof.tpl",TRUE,dirname(__FILE__)));
+
+          $ret = $allof_tmp;
+
+          break ;
+        } 
+        default : 
+        {
+          trigger_error(_("Unhandled switch type"));
+        }
+      }
+    }
+    
+    if(!isset($smarty)){
+      $smarty =get_smarty();
+    }
+
+    $smarty->assign("ID",$element_id);
+    $smarty->assign("DisplayAdd",FALSE);
+    $smarty->assign("DisplayDel",TRUE);
+    $str = $smarty->fetch(get_template_path("templates/object_test_container.tpl",TRUE,dirname(__FILE__)));
+    $ret = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($ret,"\\"),$str);
+    return($ret);
+  }
+
+
+  /* Parse given token identified by $data[$id] 
+   *  and return the parsed tokens. 
+   */
+  function _parse($data,$id = 0)
+  {
+    $av_match_type = array();
+    foreach($this->match_types as $name => $description){
+      $av_match_type[] = $name;
+    }
+    $av_match_type[] = ":over";
+    $av_match_type[] = ":under";
+
+
+
+    $av_methods= array("address","allof","anyof","exists","false","header","not","size","true","envelope");
+    $type = $data[$id]['text'];
+    $tmp = array();
+
+    /* Is there an identifier named 'not' to inverse this filter ? */
+    $Inverse = FALSE;
+    if($data[$id]['class'] == "identifier" && $data[$id]['text'] == "not"){
+      $Inverse = TRUE;
+      $id ++;
+      $type = $data[$id]['text'];
+    }
+
+    switch($type)
+    {
+
+      /****************
+       * Parse - Envelope / Header / Address
+       ****************/ 
+
+      case "envelope" : 
+      case "header":
+      case "address" : 
+      {
+        /* Address matches are struckture as follows :
+           [not] 
+           address 
+                  [address-part: tag]           all|localpart|domain|user|detail
+                  [comparator: tag]             i;octet i;ascii-casemap i;ascii-numeric
+                  [match-type: tag]             is|contains|matches|count|value 
+                  <header-list: string-list> 
+                  <key-list: string-list>   
+          */ 
+   
+        
+        $part     = "(:all|:localpart|:domain)";
+        $operator = "(:regex|:contains|:is|:matches|:count|:value)";
+        $value_op = "(lt|le|eq|ge|gt|ne)";
+
+        $Address_Part     = "";
+        $Comparator       = "";        
+        $Match_type       = "";    
+        $Match_type_value = "";
+  
+        $Key_List         = array();
+        $Value_List       = array();
+  
+        for($i = 0 ; $i < count($data) ; $i ++){
+         
+          /* Get next node */ 
+          $node = $data[$i];
+  
+          /* Check address part definition */
+          if($node['class'] == "tag" && preg_match("/".$part."/i",$node['text'])){
+            $Address_Part = $node['text'];
+          }
+
+          /* Check for match type  */
+          elseif($node['class'] == "tag" && preg_match("/".$operator."/i",$node['text'])){
+            $Match_type = $node['text'];
+
+            /* Get value operator */
+            if(in_array($Match_type,array(":value",":count"))){
+              $i ++;        
+              $node = $data[$i];
+
+              if($node['class'] == "quoted-string" && preg_match("/".$value_op."/",$node['text'])){
+                $Match_type_value = $node['text'];
+              }
+            }
+          } 
+
+          /* Check for a comparator */
+          elseif($node['class'] == "tag" && preg_match("/comparator/",$node['text'])){
+            $i ++;
+            $node = $data[$i];
+            $Comparator = $node['text'];
+          }
+  
+          /* Check for Key_List */  
+          elseif(count(sieve_get_strings($data,$i))){
+            $tmp2 = sieve_get_strings($data,$i);
+            $i =  $tmp2['OFFSET'];
+
+            if(!count($Key_List)){
+              $Key_List = $tmp2['STRINGS'];
+            }else{
+              $Value_List = $tmp2['STRINGS']; 
+            }
+          } 
+      
+        }
+         
+        /* Add to Tree */ 
+        $values = array( "Inverse"         => $Inverse,
+                                "Comparator"      => $Comparator,
+                                "Expert"          => FALSE,
+                                "Match_type"      => $Match_type,
+                                "Match_type_value"=> $Match_type_value,
+                                "Key_List"        => $Key_List,
+                                "Value_List"      => $Value_List) ;
+        if($type == "address"){
+          $values["Address_Part"]    = $Address_Part;
+        }
+        $tmp[$type] = $values;
+        $tmp[$type]['LastError'] = "";
+        break;
+      }
+
+
+      /****************
+       * Parse - Size
+       ****************/ 
+
+      case "size":
+      {
+    
+        $ops = "(:over|:under)";
+
+        $Match_type = "";
+
+        for($i = $id ; $i < count($data); $i++){
+
+          /* Get current node */
+          $node = $data[$i];
+
+          /* Get tag (under / over) */
+          if($node['class'] == "tag" && preg_match("/".$ops."/",$node['text'])){
+            $Match_type = $node['text'];
+          }
+          
+          /* Get Value_List, the value that we want to match for */
+          elseif(count(sieve_get_strings($data,$i))){
+            $tmp2 = sieve_get_strings($data,$i);
+            $i =  $tmp2['OFFSET'];
+          
+            $Value_List = $tmp2['STRINGS'];
+          } 
+        }        
+    
+        $tmp[$type]= array( "Inverse"    => $Inverse,
+                            "Match_type" => $Match_type,
+                            "Value_List" => $Value_List);
+        $tmp[$type]['LastError'] = "";
+        break;
+      }
+
+
+      /****************
+       * Parse - True / False
+       ****************/ 
+
+      case "true": 
+      {
+        $tmp['true'] = "true";
+        $tmp['true']['LastError'] = "";
+        break;
+      }
+      case "false":
+      {
+        $tmp['false'] = "false";
+        $tmp['false']['LastError'] = "";
+        break;
+      }
+
+
+      /****************
+       * Parse - Exists
+       ****************/ 
+
+      case "exists":
+      {
+        
+        /* Skip first values, [if,not,exists] */
+        $node = $data[$id];
+        while(in_array($node['text'],array("if","not","exists"))){
+          $id ++;
+          $node = $data[$id];
+        }
+
+        /* Get values */
+        $tmp2 = sieve_get_strings($data,$id);
+  
+        
+        $tmp['exists'] = array('Inverse' => $Inverse,
+                               'Values'  => $tmp2['STRINGS']);
+        $tmp[$type]['LastError'] = "";
+        break;
+      }
+
+
+      /****************
+       * Parse - Allof
+       ****************/ 
+
+      case "allof" :
+      {
+        /* Get parameter and recursivly call this method 
+         *  for each parameter 
+         */
+        $id ++;
+        $tmp2 = $this->get_parameter($data,$id);
+        
+        foreach($tmp2 as $parameter){
+          $tmp['allof'][] = $this->_parse($parameter);
+        }
+        $tmp['allof']['Inverse'] = $Inverse;
+        break;
+      }
+
+
+      /****************
+       * Parse - Anyof
+       ****************/ 
+
+      case "anyof" :
+      {
+        /* Get parameter and recursivly call this method 
+         *  for each parameter 
+         */
+        $id ++;
+        $tmp2 = $this->get_parameter($data,$id);
+
+        foreach($tmp2 as $parameter){
+          $tmp['anyof'][] = $this->_parse($parameter);
+        }
+        $tmp['anyof']['Inverse'] = $Inverse;
+        break;
+      }
+      default : $tmp[$id] = $type; 
+    }
+    
+    return($tmp); 
+  }
+
+
+  function get_parameter($data,$id)
+  {
+    $par = array();
+    $open_brakets = 0;
+    $next = NULL;
+    $num = 0;
+    for($i = $id ; $i < count($data) ; $i++ ){
+      if(in_array($data[$i]['class'],array("left-parant","left-bracket"))){
+        $open_brakets ++;
+      }
+      if($data[$i]['class'] == "comma" && $open_brakets == 1){
+        $num ++;
+      }
+      if(!in_array($data[$i]['class'],array("comma","left-parant","right-parant")) || $open_brakets >1 ){
+        $par[$num][] = $data[$i];
+      }
+      if(in_array($data[$i]['class'],array("right-parant","right-bracket"))){
+        $open_brakets --;
+      }
+    }
+    return($par);
+  }
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Keep.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Keep.inc
new file mode 100644 (file)
index 0000000..3e1d58e
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+/* This class handles the keep statement */
+class sieve_keep 
+{
+  var $object_id = -1;
+
+  function sieve_keep($data,$object_id)
+  {
+    $this->object_id = $object_id;
+  }
+
+  function save_object()
+  {
+  }
+
+  function check()
+  {
+    return(array());
+  }
+
+  function execute()
+  {
+    $smarty = get_smarty();
+    $smarty->assign("ID", $this->object_id);
+    $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__)));
+    $object = $smarty->fetch(get_template_path("templates/element_keep.tpl",TRUE,dirname(__FILE__)));
+    $str = preg_replace("/%%OBJECT_CONTENT%%/", addcslashes($object,"\\"),$object_container);
+    return($str);
+  }
+  function get_sieve_script_part()
+  {
+    return("keep;");
+  } 
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Redirect.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Redirect.inc
new file mode 100644 (file)
index 0000000..bbb2d4b
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+class sieve_redirect 
+{
+  var $data = "";
+  var $object_id = -1;
+  var $LastError   ="";
+  
+  function save_object()
+  {
+    if(isset($_POST['redirect_to_'.$this->object_id])){
+      $rt = stripslashes($_POST['redirect_to_'.$this->object_id]);
+
+      $rt = trim($rt);
+      $this->data = $rt;
+    }
+  }
+
+
+  function check()
+  {
+    $msgs = array();
+    
+    if(!tests::is_email($this->data)){
+      $msgs[] =_("Please specify a valid email address.");
+    }
+    
+    return($msgs);
+  }
+
+  function sieve_redirect($data,$object_id)
+  {
+    $this->object_id = $object_id;
+
+    if($data === NULL){
+      $data = array('ELEMENTS' => array(array('class' => "quoted-string" ,"text" => _("Place a mail address here"))));
+    }
+
+    for($i = 0 ; $i < count($data['ELEMENTS']) ; $i++){
+      $tmp = sieve_get_strings($data['ELEMENTS'],$i);
+      $i  = $i + $tmp['OFFSET'];
+      foreach($tmp['STRINGS'] as $str){
+        $this->data .= $str;
+      }
+    }
+  }
+
+
+  function get_sieve_script_part()
+  {
+    return("redirect ".sieve_create_strings($this->data).";");
+  } 
+   
+  function execute()
+  {
+    $values = htmlentities($this->data);
+    $smarty = get_smarty();
+    $smarty->assign("ID", $this->object_id);
+    $smarty->assign("Destinations" , $values);
+    $smarty->assign("LastError" , $this->check());
+    $smarty->assign("LastErrorCnt" , count($this->check()));
+    $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__)));
+    $object= $smarty->fetch(get_template_path("templates/element_redirect.tpl",TRUE,dirname(__FILE__)));
+    $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container);
+    return($str);
+  }
+}
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Reject.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Reject.inc
new file mode 100644 (file)
index 0000000..3f07260
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+
+class sieve_reject 
+{
+  var $data = "";
+  var $object_id = -1;
+  var $parent = NULL;
+
+  function save_object()
+  {
+    if(isset($_POST['reject_message_'.$this->object_id])){
+      $msg = stripslashes($_POST['reject_message_'.$this->object_id]);
+      $this->data = $msg;
+    }
+  }
+
+  function check()
+  {
+    $msgs = array();
+    if(preg_match("/\"/",$this->data)){
+      $msgs [] = _("Invalid character found, quotes are not allowed in a reject message.");
+    }
+    return($msgs);
+  }
+
+  function sieve_reject($data,$object_id,$parent)
+  {
+    $this->object_id = $object_id;
+    $this->parent = $parent;
+    $this->parent->add_require("reject");
+
+    /* If the given data is emtpy 
+     *  (This is the case when we add new elements in the ui) 
+     * Set a default text. 
+     */
+    if($data === NULL){
+      $this->data = _("Your reject text here");
+    }else{
+
+      for($i = 0 ; $i < count($data['ELEMENTS']) ; $i++){
+        $tmp = sieve_get_strings($data['ELEMENTS'],$i);
+        $i  = $i + $tmp['OFFSET'];
+        foreach($tmp['STRINGS'] as $str){
+          $this->data .= $str;
+        }
+      }
+    }
+  }
+
+  function get_sieve_script_part()
+  {
+    return("reject ".sieve_create_strings($this->data).";");
+  } 
+
+  function execute()
+  {
+    /* check if this will be a 
+     *   - single string ""
+     *   - or a multi line text: ... ; 
+     */
+    $Multiline = preg_match("/\n/",$this->data);
+
+    $smarty = get_smarty();
+    $smarty->assign("ID", $this->object_id);
+    $smarty->assign("Message",$this->data);
+    $smarty->assign("Multiline",$Multiline);
+    $smarty->assign("LastError" , $this->check());
+    $smarty->assign("LastErrorCnt" , count($this->check()));
+    $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__)));
+    $object= $smarty->fetch(get_template_path("templates/element_reject.tpl",TRUE,dirname(__FILE__)));
+    $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container);
+    return($str);
+  }
+}
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Require.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Require.inc
new file mode 100644 (file)
index 0000000..a9b6890
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+
+class sieve_require 
+{
+  var $data = array();
+  var $object_id = -1;
+  var $parent = NULL;  
+  var $skip_save_object =FALSE;
+
+  function sieve_require($data,$object_id,$parent)
+  {
+    $this->parent = $parent;
+    $this->object_id = $object_id;
+    if($data !== NULL){
+
+      for($i = 0 ; $i < count($data['ELEMENTS']) ; $i++){
+        $tmp = sieve_get_strings($data['ELEMENTS'],$i);
+        $i  = $i + $tmp['OFFSET'];
+        foreach($tmp['STRINGS'] as $str){
+          $this->data[]= $str;
+        }
+      }
+    }
+  }
+
+
+  /* Add a new require statement and ensure 
+   *  that it is not specified twice 
+   */
+  function Add_Require($str)
+  {
+    $current = array();
+    foreach($this->data as $dat){
+      $current[] = $dat;
+    }
+    if(!in_array($str,$current)){
+      $this->data[] = $str;
+    }
+    $this->data = array_unique($this->data);
+    $this->skip_save_object = TRUE;
+  }
+
+  function save_object()
+  {
+    if($this->skip_save_object){
+      $this->skip_save_object = FALSE;
+      return;
+    }
+
+    /* Get the values should check for, they are seperated by , */
+    if(isset($_POST['require_'.$this->object_id])){
+      $vls = stripslashes($_POST['require_'.$this->object_id]);
+      $tmp = array();
+
+      $tmp2 = split(",",$vls);
+      foreach($tmp2 as $val){
+        
+        $val = trim($val);
+    
+        if(empty($val)) continue;        
+  
+        $tmp[] = $val;
+      }
+      $this->data = $tmp;
+    }
+  }
+
+  function check()
+  {
+    $msgs = array();
+  
+    if(!count($this->data)){
+      $msgs[] = _("Please specify at least one valid requirement.");
+    }
+    return($msgs);
+  }
+
+  function get_sieve_script_part()
+  {
+    if(count($this->data)){
+    $tmp = sieve_create_strings($this->data);
+    return("require ".$tmp.";\n");
+    }else{
+      return("");
+    }
+  } 
+    
+  function execute()
+  {
+    $Require = "";
+    foreach($this->data as $key){
+      $Require .= $key.", ";
+    }
+    $Require = preg_replace("/,$/","",trim($Require));
+
+    $smarty = get_smarty();
+    $smarty->assign("Require",$Require);
+    $tmp = $this->check();
+    $smarty->assign("LastError",$tmp);
+    $smarty->assign("LastErrorCnt",count($tmp));
+    $smarty->assign("ID", $this->object_id);
+    $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__)));
+    $object= $smarty->fetch(get_template_path("templates/element_require.tpl",TRUE,dirname(__FILE__)));
+    $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container);
+    return($str);
+  }
+}
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Stop.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Stop.inc
new file mode 100644 (file)
index 0000000..9acc72b
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+
+/* This class handles the stop statement */
+class sieve_stop 
+{
+  var $object_id = -1;
+
+  function sieve_stop($data,$object_id)
+  {
+    $this->object_id = $object_id;
+  }
+
+  function save_object()
+  {
+  }
+
+  function check()
+  {
+    return(array());
+  }
+
+  function execute()
+  {
+    $smarty = get_smarty();
+    $smarty->assign("ID", $this->object_id);
+    $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__)));
+    $object= $smarty->fetch(get_template_path("templates/element_stop.tpl",TRUE,dirname(__FILE__)));
+    $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container);
+    return($str);
+  }
+
+  function get_sieve_script_part()
+  {
+    return("stop; \n");
+  } 
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Vacation.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Vacation.inc
new file mode 100644 (file)
index 0000000..1af166e
--- /dev/null
@@ -0,0 +1,179 @@
+<?php
+
+class sieve_vacation 
+{
+  var $days     = FALSE;
+  var $subject  = FALSE;
+  var $from     = "";
+  var $mime     = "";
+  var $handle   = "";
+  var $reason   = "\"I am not available, currently.\"";
+  var $addresses= array();
+  var $object_id= -1;
+  var $Expert   = FALSE;
+  var $parent   = NULL;
+
+  function sieve_vacation($data,$object_id,$parent)
+  {
+    $this->parent = $parent;
+    $this->object_id = $object_id;
+    $this->parent->add_require("vacation");
+
+    /* 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");
+
+    /* skip if empty */
+    if(($data === NULL) || !is_array($data)) return;
+
+    /* Walk through elements */
+    $p= count($data['ELEMENTS']);
+    for ($i= 0; $i < $p; $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[] =  preg_replace("/\"/i","",$data['ELEMENTS'][$i]['text']);
+        }
+      }
+
+      /* Add the vacation message */
+      if(in_array($node['class'],array("quoted-string","multi-line"))){
+
+        $tmp = sieve_get_strings($data['ELEMENTS'],$i);
+        $strs= $tmp['STRINGS'];
+        $data = ""; 
+        foreach($strs as $str){
+          $data .= $str;
+        }
+        $this->reason = $data;
+      }
+    }
+  }
+
+  function get_sieve_script_part()
+  {
+    $str = "vacation ";
+    if($this->days){
+      $str.= ":days ".$this->days;
+    }
+
+    if(count($this->addresses)){
+      $str .= ":addresses ".sieve_create_strings($this->addresses);
+      if($this->subject){
+        $str.= ":subject ".sieve_create_strings($this->subject);
+      }
+    }
+    if($this->mime){
+      $str.= ":mime ".sieve_create_strings($this->mime);
+    }
+  
+    /* Append reason and ensure that this will be 
+     *  handled as multiline text element 
+     *  by adding a "\n" new line 
+     */
+    $str .= "\n ".sieve_create_strings($this->reason."\n");
+    return($str." ; \n");
+  }
+
+  function save_object()
+  {
+    /* Get release date */
+    if(isset($_POST['vacation_release_'.$this->object_id])){
+      $this->days = stripslashes($_POST['vacation_release_'.$this->object_id]);
+    }
+
+    /* Check if we want to toggle the expert mode */
+    if(isset($_POST['Toggle_Expert_'.$this->object_id])){
+      $this->Expert = !$this->Expert;
+    }
+
+    /* Get release date */
+    if(isset($_POST['vacation_receiver_'.$this->object_id])){
+      $vr = stripslashes ($_POST['vacation_receiver_'.$this->object_id]);
+      $tmp = array();
+      $tmp2 = split(",",$vr);
+      foreach($tmp2 as $val){
+        $ad = trim($val);
+        if(!empty($ad)){
+          $tmp[] = $ad;
+        }
+      }
+      $this->addresses = $tmp;
+    }
+
+    /* Get reason */
+    if(isset($_POST['vacation_reason_'.$this->object_id])){
+      $vr = stripslashes ($_POST['vacation_reason_'.$this->object_id]);
+      $this->reason = trim($vr);
+    }
+  }
+
+  function check()
+  {
+    $msgs = array();
+    $err = FALSE;
+    foreach($this->addresses as $addr){
+      if(!tests::is_email($addr)){
+        $err = true;
+      }
+    }
+    if($err){
+      $msgs[] = _("Alternative sender address must be a valid email addresses.");
+    }
+    return($msgs);
+  }
+
+  function execute()
+  {
+    $Addresses = "";
+    foreach($this->addresses as $key){
+      $Addresses .= $key.", ";
+    }
+    $Addresses = preg_replace("/,$/","",trim($Addresses));
+
+    $smarty = get_smarty();
+    $smarty->assign("LastError",$this->check());
+    $smarty->assign("LastErrorCnt",count($this->check()));
+    $smarty->assign("Reason",$this->reason);
+    $smarty->assign("Addresses",$Addresses);
+    $smarty->assign("Subject",$this->subject);
+    $smarty->assign("Days",$this->days);
+    $smarty->assign("ID",$this->object_id);
+    $smarty->assign("Expert",$this->Expert);
+
+    $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__)));
+    $object= $smarty->fetch(get_template_path("templates/element_vacation.tpl",TRUE,dirname(__FILE__)));
+    $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container);
+    return($str);
+  }
+}
+
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveManagement.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveManagement.inc
new file mode 100644 (file)
index 0000000..417853e
--- /dev/null
@@ -0,0 +1,1057 @@
+<?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
+ */
+
+
+/* The sieve management class displays a list of sieve 
+ *  scripts for the given mail account. 
+ * The account is identified by the parents uid attribute. 
+ *
+ *  $config       The config object
+ *  $dn           The object edited 
+ *  $parent       The parent object that provides the uid attribute 
+ */
+class sieveManagement extends plugin
+{
+  var $parent = NULL;
+  var $scripts= array();  
+  var $uattrib = "uid";
+  var $current_script  = -1;
+  var $current_handler = NULL;
+  var $script_to_delete =-1;
+  var $sieve_handle = NULL; 
+  var $Script_Error = "";
+  var $Sieve_Error = "";
+  var $create_script = FALSE;
+
+  /* To add new elements we need to know 
+   *  Where to add the element              -> add_new_id
+   *  Whould we add above or below this id  -> add_above_below
+   *  What kind of element should we add    -> add_element_type
+   */
+  var $add_new_element    = FALSE;
+  var $add_new_id         = -1;
+  var $add_above_below    = "below";
+  var $add_element_type   = "sieve_comment";
+
+  /* If this variable is TRUE, this indicates that we have the 
+   *  import dialog opened. 
+   */
+  var $Import_Script = FALSE;
+
+  /* Initialize the class and load all sieve scripts 
+   *  try to parse them and display errors 
+   */ 
+  function sieveManagement(&$config,$dn,&$parent,$uattrib)
+  {
+    /* Check given parameter */
+    if(!isset($parent->$uattrib)){
+      trigger_error("Sieve Management implementation error. Parameter 4 (".$uattrib.") must be part of the given parent element (".get_class($parent).").");
+    }
+
+    $this->uattrib = $uattrib;
+    $this->parent = &$parent;
+    plugin::plugin($config,$dn);
+
+    /* Get sieve, if this fail abort class initialization */
+    if(!$this->sieve_handle = $this->get_sieve()){
+      return;
+    }
+
+
+    /* Get all sieve scripts names */
+    if($this->sieve_handle->sieve_listscripts()){
+      if (is_array($this->sieve_handle->response)){
+        foreach($this->sieve_handle->response as $key => $name){
+
+          $data = array();
+          $data['NAME'] = $name;
+
+          if($key == "ACTIVE" && $key === "ACTIVE"){
+            $data['ACTIVE'] = TRUE;
+          }else{
+            $data['ACTIVE'] = FALSE;
+          }
+          $this->scripts[] = $data;          
+        }
+      } 
+    }
+
+    /* Get script contents */
+    foreach($this->scripts as $key => $script){
+      $p = new My_Parser($this);
+      $this->sieve_handle->sieve_getscript($script['NAME']);
+
+      $script = "";
+      foreach($this->sieve_handle->response as $line){
+        $script.=$line;
+      }
+
+      $this->scripts[$key]['IS_NEW'] = FALSE;;
+      $this->scripts[$key]['SCRIPT'] = $script;
+      $this->scripts[$key]['ORIG_SCRIPT'] = $script;
+      $this->scripts[$key]['MSG']   = "";
+      $ret = $p->parse($script);
+      if(!$ret){
+        $this->scripts[$key]['STATUS']   = FALSE;
+        $this->scripts[$key]['MODE']    = "Source";
+        $this->scripts[$key]['MSG'] = _("Parse failed")."<font color='red'>".$p->status_text."</font>";
+      }else{
+        $this->scripts[$key]['STATUS']   = TRUE;
+        $this->scripts[$key]['MODE']    = "Structured";
+        $this->scripts[$key]['MSG'] = _("Parse successful");
+      }
+      $this->scripts[$key]['PARSER'] = $p;
+      $this->scripts[$key]['EDITED'] = FALSE;
+    }
+    $this->sieve_handle = $this->sieve_handle;
+  }
+
+
+  /* Return a sieve class handle,
+   *  false if login fails
+   */
+  function get_sieve()
+  {
+    
+    /* Connect to sieve class and try to get all available sieve scripts */
+    if(isset($this->config->data['SERVERS']['IMAP'][$this->parent->gosaMailServer])){
+      $cfg=  $this->config->data['SERVERS']['IMAP'][$this->parent->gosaMailServer];
+      $this->Sieve_Error = "";
+
+      $uattrib = $this->uattrib;
+
+      /* Log into the mail server */
+      $this->sieve_handle= new sieve(
+          $cfg["sieve_server"], 
+          $cfg["sieve_port"], 
+          $this->parent->$uattrib, 
+          $cfg["password"], 
+          $cfg["admin"]);
+
+      /* Try to login */
+      if (!@$this->sieve_handle->sieve_login()){
+        $this->Sieve_Error = $this->sieve_handle->error_raw;
+        return(FALSE);
+      }
+      return($this->sieve_handle);
+    }else{
+      $this->Sieve_Error = sprintf(_("The specified mail server '%s' does not exist within the GOsa configuration."),
+        $this->parent->gosaMailServer);
+      return(FALSE);
+    }
+  }
+
+
+  /* Handle sieve list 
+   */
+  function execute()
+  {
+    /***************
+     * Create a new Script 
+     ***************/
+
+    /* Force opening the add script dialog */
+    if(isset($_POST['create_new_script'])){
+      $this->create_script = TRUE;
+    }
+
+    /* Close add script dialog, without adding a new one */
+    if(isset($_POST['create_script_cancel'])){
+      $this->create_script = FALSE;
+    }
+
+    /* Display create script dialog 
+     *  handle posts, display warnings if specified 
+     *  name is not useable. 
+     * Create a new script with given name
+     */
+    if($this->create_script){
+    
+      /* Set initial name or used posted name if available */
+      $name = "";
+      if(isset($_POST['NewScriptName'])){
+        $name = trim($_POST['NewScriptName']);
+      }
+      /* Check given name */ 
+      $err = false;
+
+      /* Is given name in lower case characters ? */
+      if(isset($_POST['create_script_save'])){
+        if(!strlen($name)){
+          $err =true;
+          msg_dialog::display(_("Error"), _("No script name specified!"), ERROR_DIALOG);
+        }
+        /* Is given name in lower case characters ? */
+        if($name != strtolower($name)){
+          $err =true;
+          msg_dialog::display(_("Error"), _("Please use only lowercase script names!"), ERROR_DIALOG);
+        }
+
+        /* Only chars are allowed here */
+        if(preg_match("/[^a-z]/i",$name)){
+          $err =true;
+          msg_dialog::display(_("Error"), _("Please use only alphabetical characters in script names!"), ERROR_DIALOG);
+        }
+
+        $tmp = $this->get_used_script_names();
+        if(in_array_ics($name,$tmp)){
+          $err =true;
+          msg_dialog::display(_("Error"), _("Script name already in use!"), ERROR_DIALOG);
+        }
+      }
+
+      /* Create script if everything is ok */
+      if($this->create_script && isset($_POST['create_script_save']) && !$err){
+
+        /* Close dialog */
+        $this->create_script = FALSE;
+
+        /* Script contents to use */
+        $script = "/*New script */".
+                  "stop;";
+
+        /* Create a new parser and initialize default values */
+        $p = new My_Parser($this);
+        $ret = $p->parse($script);
+        $sc['SCRIPT'] = $script;
+        $sc['ORIG_SCRIPT'] = $script;
+        $sc['IS_NEW'] = TRUE;
+        $sc['MSG']   = "";
+        if(!$ret){
+          $sc['STATUS']   = FALSE;
+          $sc['MODE']    = "Source";
+          $sc['MSG'] = _("Parse failed")."<font color='red'>".$p->status_text."</font>";
+        }else{
+          $sc['STATUS']   = TRUE;
+          $sc['MODE']    = "Structured";
+          $sc['MSG'] = _("Parse successful");
+        }
+        $sc['PARSER'] = $p;
+        $sc['EDITED'] = TRUE;
+        $sc['ACTIVE'] = FALSE;
+        $sc['NAME']   = $name;
+      
+        /* Add script */
+        $this->scripts[$name] = $sc;
+      }else{
+      
+        /* Display dialog to enter new script name */
+        $smarty = get_smarty();
+        $smarty->assign("NewScriptName",$name);
+        return($smarty->fetch(get_template_path("templates/create_script.tpl",TRUE,dirname(__FILE__))));
+      }
+    }
+
+
+    /*************
+     * Handle several posts 
+     *************/
+
+    $once = TRUE;
+    foreach($_POST as $name => $value){
+
+      /* Edit script requested */
+      if(preg_match("/^editscript_/",$name) && $once && !$this->current_handler){
+        $script = preg_replace("/^editscript_/","",$name);
+        $script = preg_replace("/_(x|y)/","",$script);
+        $once = FALSE;
+
+        $this->current_script = $script;
+        $this->current_handler = $this->scripts[$script]['PARSER'];
+        $this->scripts[$script]['SCRIPT_BACKUP'] = $this->scripts[$script]['SCRIPT'];
+      }
+
+      /* remove script requested */
+      if($this->parent->acl_is_writeable("sieveManagement") && preg_match("/^delscript_/",$name) && $once && !$this->current_handler){
+        $script = preg_replace("/^delscript_/","",$name);
+        $script = preg_replace("/_(x|y)/","",$script);
+        $once = FALSE;
+        $this->script_to_delete = $script;  
+      }
+
+      /* Activate script */
+      if($this->parent->acl_is_writeable("sieveManagement") && preg_match("/^active_script_/",$name) && $once && !$this->current_handler){
+        $script = preg_replace("/^active_script_/","",$name);
+        $script = preg_replace("/_(x|y)/","",$script);
+        $once = FALSE;
+
+        /* We can only activate existing scripts */
+        if(!$this->scripts[$script]['IS_NEW']){
+
+          /* Get sieve */
+          if(!$this->sieve_handle = $this->get_sieve()){
+            msg_dialog::display(_("SIEVE error"), sprintf(_("Cannot log into SIEVE server: %s"), '<br><br><i>'.to_string($this->Sieve_Error).'</i>'), ERROR_DIALOG);
+          }
+
+          /* Try to activate the given script and update 
+           *  class script array. 
+           */
+          if(!$this->sieve_handle->sieve_setactivescript($this->scripts[$script]['NAME'])){
+            msg_dialog::display(_("SIEVE error"), sprintf(_("Cannot retrieve SIEVE script: %s"), '<br><br><i>'.to_string($this->sieve_handler->error_raw).'</i>'), ERROR_DIALOG);
+          }else{
+            foreach($this->scripts as $key => $data){
+              if($key == $script){
+                $this->scripts[$key]['ACTIVE'] = TRUE;
+              }else{
+                $this->scripts[$key]['ACTIVE'] = FALSE;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    
+    /*************
+     * Remove script handling 
+     *************/
+
+    /* Remove aborted */
+    if(isset($_POST['delete_cancel'])){
+      $this->script_to_delete = -1;
+    }
+
+    /* Remove confirmed */
+    if($this->parent->acl_is_writeable("sieveManagement") && isset($_POST['delete_script_confirm'])){
+
+      $script = $this->scripts[$this->script_to_delete];
+
+      /* Just remove from array if it is a new script */
+      if($script['IS_NEW']){
+        unset($this->scripts[$this->script_to_delete]);
+      }else{
+
+        /* Get sieve */
+        if(!$this->sieve_handle = $this->get_sieve()){
+          msg_dialog::display(_("SIEVE error"), sprintf(_("Cannot log into SIEVE server: %s"), '<br><br><i>'.to_string($this->Sieve_Error).'</i>'), ERROR_DIALOG);
+        }
+
+        if(!$this->sieve_handle->sieve_deletescript($this->scripts[$this->script_to_delete]['NAME'])){
+          msg_dialog::display(_("SIEVE error"), sprintf(_("Cannot remove SIEVE script: %s"), '<br><br><i>'.to_string($this->sieve_handler->error_raw).'</i>'), ERROR_DIALOG);
+        }else{
+          unset($this->scripts[$this->script_to_delete]);
+        }
+      }
+      $this->script_to_delete = -1;
+    }
+
+    /* Display confirm dialog */
+    if($this->script_to_delete != -1){
+      $smarty = get_smarty();
+      $smarty->assign("Warning",
+          sprintf(_("You are going to remove the sieve script '%s' from your mail server."),
+            $this->scripts[$this->script_to_delete]['NAME']));
+      return($smarty->fetch(get_template_path("templates/remove_script.tpl",TRUE,dirname(__FILE__))));
+    }
+
+
+    /**************
+     * Save script changes 
+     **************/
+
+    /* Abort saving */
+    if(isset($_POST['cancel_sieve_changes'])){
+      $tmp = $this->scripts[$this->current_script]['SCRIPT_BACKUP'];
+      $this->scripts[$this->current_script]['SCRIPT'] = $tmp;
+      $this->scripts[$this->current_script]['PARSER']->parse($tmp);
+      $this->current_handler = NULL;
+    }
+
+    /* Save currently edited sieve script. */
+    if($this->parent->acl_is_writeable("sieveManagement") && 
+       isset($_POST['save_sieve_changes']) && 
+       is_object($this->current_handler)){
+      $chk = $this->current_handler->check();
+      if(!count($chk)){
+
+        $sc = $this->scripts[$this->current_script]['SCRIPT'];
+        $p = new My_Parser($this);
+        if($p -> parse($sc)){
+
+          if($this->scripts[$this->current_script]['MODE'] == "Source-Only"){
+            $this->scripts[$this->current_script]['MODE'] = "Source";
+          }
+  
+          $this->scripts[$this->current_script]['PARSER'] = $p;
+          $this->scripts[$this->current_script]['EDITED'] = TRUE;
+          $this->scripts[$this->current_script]['STATUS'] = TRUE;
+          $this->scripts[$this->current_script]['MSG'] = _("Edited");
+          $this->current_handler = NULL;
+        }else{
+          msg_dialog::display(_("SIEVE error"), $p->status_text, ERROR_DIALOG);
+        }
+      }else{
+        foreach($chk as $msgs){
+          msg_dialog::display(_("SIEVE error"), $msgs, ERROR_DIALOG);
+        }
+      }
+    }
+
+
+    /*************
+     * Display edit dialog 
+     *************/
+
+    /* Display edit dialog, depending on Mode display different uis
+     */
+    if($this->current_handler){
+
+        if(isset($_POST['Import_Script'])){
+          $this->Import_Script = TRUE;
+        }
+
+        if(isset($_POST['Import_Script_Cancel'])){
+          $this->Import_Script = FALSE;
+        }
+
+        if(isset($_POST['Import_Script_Save']) && isset($_FILES['Script_To_Import'])){
+
+          $file     = $_FILES['Script_To_Import'];
+
+          if($file['size'] == 0){
+            msg_dialog::display(_("Error"), _("Uploaded script is empty!"), ERROR_DIALOG);
+          }elseif(!file_exists($file['tmp_name'])){
+            msg_dialog::display(_("Internal error"), sprintf(_("Cannot access temporary file '%s'!"), $file['tmp_name']), ERROR_DIALOG);
+          }elseif(!is_readable ($file['tmp_name'])){
+            msg_dialog::display(_("SIEVE error"), sprintf(_("Cannot open temporary file '%s'!"), $file['tmp_name']), ERROR_DIALOG);
+          }else{
+            
+            
+            $contents = file_get_contents($file['tmp_name']);
+           
+            $this->scripts[$this->current_script]['SCRIPT'] = $contents;
+            if(!$this->current_handler->parse($contents)){
+              $this->scripts[$this->current_script]['MODE'] = "Source";
+            }else{
+              $this->scripts[$this->current_script]['MODE'] = "Structured";
+            }
+            $this->Script_Error = "";
+            $this->Import_Script = FALSE;
+          }
+        }
+
+        if($this->Import_Script){
+          $smarty = get_smarty();
+          $str = $smarty->fetch(get_template_path("templates/import_script.tpl",TRUE,dirname(__FILE__)));
+          return($str);
+        }
+  
+
+        /* Create dump of current sieve script */
+        if(isset($_POST['Save_Copy'])){
+
+            /* force download dialog */
+            header("Content-type: application/tiff\n");
+            if (preg_match('/MSIE 5.5/', $HTTP_USER_AGENT) ||
+                    preg_match('/MSIE 6.0/', $HTTP_USER_AGENT)) {
+                header('Content-Disposition: filename="dump.script"');
+            } else {
+                header('Content-Disposition: attachment; filename="dump.script"');
+            }
+            header("Content-transfer-encoding: binary\n");
+            header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
+            header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
+            header("Cache-Control: no-cache");
+            header("Pragma: no-cache");
+            header("Cache-Control: post-check=0, pre-check=0");
+            echo $this->scripts[$this->current_script]['SCRIPT'];
+            exit();
+        }
+
+
+      /****
+       * Add new element to ui
+       ****/
+
+      /* Abort add dialog */ 
+      if(isset($_POST['select_new_element_type_cancel'])){
+        $this->add_new_element = FALSE;
+      }
+
+      /* Add a new element */
+      if($this->add_new_element){
+
+        $element_types= array(
+            "sieve_keep"      => _("Keep"),
+            "sieve_comment"   => _("Comment"),
+            "sieve_fileinto"  => _("File into"),
+            "sieve_keep"      => _("Keep"),
+            "sieve_discard"   => _("Discard"),
+            "sieve_redirect"  => _("Redirect"),
+            "sieve_reject"    => _("Reject"),
+            "sieve_require"   => _("Require"),
+            "sieve_stop"      => _("Stop"),
+            "sieve_vacation"  => _("Vacation message"),
+            "sieve_if"        => _("If"));
+
+
+        /* Element selected */
+        if(isset($_POST['element_type']) && isset($element_types[$_POST['element_type']]) 
+           || isset($_POST['element_type']) &&in_array($_POST['element_type'],array("sieve_else","sieve_elsif"))){
+          $this->add_element_type = $_POST['element_type'];
+        }
+
+        /* Create new element and add it to
+         *  the selected position 
+         */
+        if(isset($_POST['select_new_element_type'])){
+          if($this->add_new_element_to_current_script($this->add_element_type,$this->add_new_id,$this->add_above_below)){
+            $this->add_new_element = FALSE;
+          }else{
+            msg_dialog::display(_("SIEVE error"), _("Cannot add new element!") , ERROR_DIALOG);
+          }
+        }
+      }
+
+      /* Only display select dialog if it is necessary */
+      if($this->add_new_element){
+        $smarty = get_smarty();
+    
+        $add_else_elsif = FALSE;
+
+        /* Check if we should add else/elsif to the select box 
+         *  or not. We can't add else twice!.
+         */
+        if($this->add_above_below == "below"){
+
+          /* Get posistion of the current element 
+           */
+          foreach($this->current_handler->tree_->pap as $key => $obj){
+        
+            if($obj->object_id == $this->add_new_id && in_array(get_class($obj),array("sieve_if","sieve_elsif"))){
+  
+              /* Get block start/end */
+              $end_id = $this->current_handler->tree_->get_block_end($key);
+              $else_found = FALSE;
+              $elsif_found = FALSE;
+          
+              /* Check if there is already an else in this block 
+               */
+              for($i =  $key ; $i < $end_id ; $i ++){
+                if(get_class($this->current_handler->tree_->pap[$i]) == "sieve_else"){
+                  $else_found = TRUE;
+                }
+                if(get_class($this->current_handler->tree_->pap[$i]) == "sieve_elsif"){
+                  $elsif_found = TRUE;
+                }
+              }
+  
+              /* Only allow adding 'else' if there is currently 
+               *  no 'else' statement. And don't allow adding 
+               *  'else' before 'elseif'
+               */ 
+              if(!$else_found && (!(get_class($obj) == "sieve_if" && $elsif_found))){
+                $element_types['sieve_else'] = _("Else");
+              }
+              $element_types['sieve_elsif'] = _("Else If");
+            }
+          }
+        }
+
+        $smarty->assign("element_types",$element_types );
+        $smarty->assign("element_type",$this->add_element_type);
+        $str = $smarty->fetch(get_template_path("templates/add_element.tpl",TRUE,dirname(__FILE__)));
+        return($str);
+      }
+
+
+
+      /****************
+       * Handle test posts 
+       ****************/
+
+      /* handle some special posts from test elements 
+       */
+      foreach($_POST as $name => $value){
+        if(preg_match("/^Add_Test_Object_/",$name)) {
+          $name = preg_replace("/^Add_Test_Object_/","",$name);
+          $name = preg_replace("/_(x|y)$/","",$name);
+
+          $test_types_to_add = array(
+              "address" =>_("Address"),
+              "header"  =>_("Header"),
+              "envelope"=>_("Envelope"),
+              "size"    =>_("Size"),
+              "exists"  =>_("Exists"),
+              "allof"   =>_("All of"),
+              "anyof"   =>_("Any of"),
+              "true"    =>_("True"),
+              "false"   =>_("False"));
+
+          $smarty = get_smarty();
+          $smarty->assign("ID",$name);
+          $smarty->assign("test_types_to_add",$test_types_to_add);
+          $ret = $smarty->fetch(get_template_path("templates/select_test_type.tpl",TRUE,dirname(__FILE__)));
+          return($ret);
+        }
+      }
+
+      $current = $this->scripts[$this->current_script];
+
+      /* Create html results */
+      $smarty = get_smarty();
+      $smarty->assign("Mode",$current['MODE']);
+      if($current['MODE'] == "Structured"){
+        $smarty->assign("Contents",$this->current_handler->tree_->execute());
+      }else{
+        $smarty->assign("Contents",$current['SCRIPT']);
+      }
+      $smarty->assign("Script_Error",$this->Script_Error);
+      $ret = $smarty->fetch(get_template_path("templates/edit_frame_base.tpl",TRUE,dirname(__FILE__)));
+      return($ret);
+    }
+
+
+    /* Create list of available sieve scripts 
+     */
+    $List = new divSelectBox("sieveManagement");
+    foreach($this->scripts as $key => $script){
+  
+      $edited =  $script['EDITED'];
+      $active =  $script['ACTIVE'];
+      
+      $field1 = array("string" => "&nbsp;",
+                      "attach" => "style='width:20px;'");  
+      if($active){
+        $field1 = array("string" => "<img src='images/true.png' alt='"._("Active")."' 
+                                      title='"._("This script is marked as active")."'>",
+                        "attach" => "style='width:20px;'");  
+      }
+      $field2 = array("string" => $script['NAME']);  
+      $field3 = array("string" => $script['MSG']);
+      $field4 = array("string" => _("Script length").":&nbsp;".strlen($script['SCRIPT']));
+
+      if($this->parent->acl_is_writeable("sieveManagement")){
+        $del = "<input type='image' name='delscript_".$key."' src='images/edittrash.png'
+                  title='"._("Remove script")."'>";
+      }else{
+        $del = "<img src='images/empty.png' alt=' '>";
+      }
+
+      if($active || $script['IS_NEW'] || !$this->parent->acl_is_writeable("sieveManagement")){
+        $activate = "<img src='images/empty.png' alt=' '>";
+      }else{
+        $activate = "<input type='image' name='active_script_".$key."' src='images/true.png'
+                       title='"._("Activate script")."'>";
+      }
+
+      $field6 = array("string" => $activate."<input type='image' name='editscript_".$key."' src='images/edit.png'
+                        title='"._("Edit script")."'>".$del,
+                      "attach" => "style='border-right:0px; width:70px;'");
+      $List->AddEntry(array($field1,$field2,$field3,$field4,$field6)); 
+    }
+
+    $List->SetHeight(400);
+    /* If the uattrib is empty   (Attribute to use for authentification with sieve)
+     *  Display a message that the connection can't be established.
+     */
+    $uattrib = $this->uattrib;
+    $smarty = get_smarty();
+
+    if(!$this->get_sieve()){
+      $smarty->assign("Sieve_Error",sprintf(
+        _("Can't log into SIEVE server. Server says '%s'."),
+          to_string($this->Sieve_Error)));
+    }else{
+      $smarty->assign("Sieve_Error","");
+    }
+
+    $smarty->assign("uattrib_empty",empty($this->parent->$uattrib));
+    $smarty->assign("List",$List->DrawList());
+    return($smarty->fetch(get_template_path("templates/management.tpl",TRUE,dirname(__FILE__))));
+  }
+
+
+  /* Add a new element to the currently opened script editor.
+   * The insert position is specified by 
+   */
+  function add_new_element_to_current_script($type,$id,$position)
+  {
+    /* Test given data */
+    if(!in_array_ics($position,array("above","below"))){
+      trigger_error("Can't add new element with \$position=".$position.". Only 'above','below' are allowed here.");
+      return(FALSE);
+    }
+    if(!is_numeric($id)){
+      trigger_error("Can't add new element, given id is not numeric.");
+      return(FALSE);
+    }
+    $tmp = get_declared_classes();  
+    if(!in_array($type,$tmp)){
+      if(!empty($type)){
+        trigger_error("Can't add new element, given \$class=".$class." does not exists.");
+      }
+      return(FALSE);
+    }
+    if(!is_object($this->current_handler) || get_class($this->current_handler) != "My_Parser"){
+      trigger_error("Can't add new element, there is no valid script editor opened.");
+      return(FALSE);
+    }
+
+    /* These element types are allowed to be added here */
+    $element_types= array(
+        "sieve_keep"      => _("Keep"),
+        "sieve_comment"   => _("Comment"),
+        "sieve_fileinto"  => _("File into"),
+        "sieve_keep"      => _("Keep"),
+        "sieve_discard"   => _("Discard"),
+        "sieve_redirect"  => _("Redirect"),
+        "sieve_reject"    => _("Reject"),
+        "sieve_require"   => _("Require"),
+        "sieve_stop"      => _("Stop"),
+        "sieve_vacation"  => _("Vacation message"),
+        "sieve_if"        => _("If"));
+
+    /* Check if we should add else/elsif to the select box
+     *  or not. We can't add else twice!.
+     */
+
+    /* Get posistion of the current element
+     */
+    foreach($this->current_handler->tree_->pap as $key => $obj){
+
+      if($obj->object_id == $id && in_array(get_class($obj),array("sieve_if","sieve_elsif"))){
+
+        /* Get block start/end */
+        $end_id = $this->current_handler->tree_->get_block_end($key);
+        $else_found = FALSE;
+        $elsif_found = FALSE;
+
+        /* Check if there is already an else in this block
+         */
+        for($i =  $key ; $i < $end_id ; $i ++){
+          if(get_class($this->current_handler->tree_->pap[$i]) == "sieve_else"){
+            $else_found = TRUE;
+          }
+          if(get_class($this->current_handler->tree_->pap[$i]) == "sieve_elsif"){
+            $elsif_found = TRUE;
+          }
+        }
+
+        if($this->add_above_below == "below"){
+
+          /* Only allow adding 'else' if there is currently
+           *  no 'else' statement. And don't allow adding
+           *  'else' before 'elseif'
+           */
+          if(!$else_found && (!(get_class($obj) == "sieve_if" && $elsif_found))){
+            $element_types['sieve_else'] = _("Else");
+          }
+          $element_types['sieve_elsif'] = _("Else If");
+        }else{
+         
+          /* Allow adding elsif above elsif */ 
+          if(in_array(get_class($obj),array("sieve_elsif"))){
+            $element_types['sieve_elsif'] = _("Else If");
+          }
+        }
+      }
+    }
+
+    if(!isset($element_types[$type])){
+      msg_dialog::display(_("SIEVE error"), _("Cannot insert element at the requested position!") , ERROR_DIALOG);
+      return;
+    }
+
+
+    /* Create elements we should add 
+     * -Some element require also surrounding block elements
+     */
+    $parent = $this->current_handler->tree_;
+    if($this->add_element_type == "sieve_if"){
+      $ele[] = new $this->add_element_type(NULL, preg_replace("/[^0-9]/","",microtime()),$parent);
+      $ele[] = new sieve_block_start(NULL,preg_replace("/[^0-9]/","",microtime()),$parent);
+      $ele[] = new sieve_block_end(NULL,preg_replace("/[^0-9]/","",microtime()),$parent);
+    }elseif($this->add_element_type == "sieve_else"){
+      $ele[] = new sieve_block_end(NULL,preg_replace("/[^0-9]/","",microtime()),$parent);
+      $ele[] = new $this->add_element_type(NULL, preg_replace("/[^0-9]/","",microtime()),$parent);
+      $ele[] = new sieve_block_start(NULL,preg_replace("/[^0-9]/","",microtime()),$parent);
+    }elseif($this->add_element_type == "sieve_elsif"){
+      $ele[] = new sieve_block_end(NULL,preg_replace("/[^0-9]/","",microtime()),$parent);
+      $ele[] = new $this->add_element_type(NULL, preg_replace("/[^0-9]/","",microtime()),$parent);
+      $ele[] = new sieve_block_start(NULL,preg_replace("/[^0-9]/","",microtime()),$parent);
+    }elseif($this->add_element_type == "sieve_vacation"){
+
+      /* Automatically add addresses to sieve alternate addresses */
+      $data = NULL;
+      $tmp = new $this->add_element_type($data, preg_replace("/[^0-9]/","",microtime()),$parent);
+      if(isset($this->parent->gosaMailAlternateAddress)){
+        $tmp->addresses = $this->parent->gosaMailAlternateAddress;
+      }
+      $ele[] = $tmp ;
+    }else{
+      $ele[] = new $this->add_element_type(NULL, preg_replace("/[^0-9]/","",microtime()),$parent);
+    }
+
+    /* Get index of the element identified by object_id == $id; 
+     */
+    $index = -1;
+    $data = $this->current_handler->tree_->pap;
+    foreach($data as $key => $obj){
+      if($obj->object_id == $id && $index==-1){
+        $index = $key;
+      }
+    }
+
+    /* Tell to user that we couldn't find the given object 
+     *  so we can't add an element. 
+     */
+    if($index == -1 ){
+      trigger_error("Can't add new element, specified \$id=".$id." could not be found in object tree.");
+      return(FALSE);
+    }
+
+    /* We have found the specified object_id 
+     *  and want to detect the next free position 
+     *  to insert the new element.
+     */
+    if($position == "above"){
+      $direction ="up";
+      $next_free = $this->current_handler->tree_->_get_next_free_move_slot($index,$direction,TRUE);
+    }else{
+      $direction = "down";
+      $next_free = $this->current_handler->tree_->_get_next_free_move_slot($index,$direction,TRUE);
+    }
+    /* This is extremly necessary, cause some objects 
+     *  updates the tree objects ... Somehow i should change this ... 
+     */
+    $data = $this->current_handler->tree_->pap;
+    $start = $end = array();
+
+    if($position == "above"){
+      $start = array_slice($data,0,$next_free);
+      $end   = array_slice($data,$next_free);
+    }else{
+      $start = array_slice($data,0,$next_free+1);
+      $end   = array_slice($data,$next_free+1);
+    }
+
+    $new = array();
+    foreach($start as $obj){
+      $new[] = $obj;
+    }
+    foreach($ele as $el){
+      $new[] = $el;
+    }
+    foreach($end as $obj){
+      $new[] = $obj;
+    }
+    $data= $new;
+    $this->current_handler->tree_->pap = $data;
+    return(TRUE);
+  }
+
+
+
+  function save_object()
+  {
+    if($this->current_handler){
+
+      if(isset($_GET['Add_Object_Top_ID'])){
+        $this->add_new_element    = TRUE;
+        $this->add_new_id         = $_GET['Add_Object_Top_ID'];
+        $this->add_above_below    = "above";
+      }  
+
+      if(isset($_GET['Add_Object_Bottom_ID'])){
+        $this->add_new_element    = TRUE;
+        $this->add_new_id         = $_GET['Add_Object_Bottom_ID'];
+        $this->add_above_below    = "below";
+      }  
+
+      if(isset($_GET['Remove_Object_ID'])){
+        $found_id = -1;
+        foreach($this->current_handler->tree_->pap as $key => $element){
+          if($element->object_id == $_GET['Remove_Object_ID']){
+            $found_id = $key;
+          }
+        }
+        if($found_id != -1 ){
+          $this->current_handler->tree_->remove_object($found_id);  
+        }
+      }  
+      if(isset($_GET['Move_Up_Object_ID'])){
+        $found_id = -1;
+        foreach($this->current_handler->tree_->pap as $key => $element){
+          if($element->object_id == $_GET['Move_Up_Object_ID']){
+            $found_id = $key;
+          }
+        }
+        if($found_id != -1 ){
+          $this->current_handler->tree_->move_up_down($found_id,"up");
+        }
+      }  
+      if(isset($_GET['Move_Down_Object_ID'])){
+        $found_id = -1;
+        foreach($this->current_handler->tree_->pap as $key => $element){
+          if($element->object_id == $_GET['Move_Down_Object_ID']){
+            $found_id = $key;
+          }
+        }
+        if($found_id != -1 ){
+          $this->current_handler->tree_->move_up_down($found_id,"down");
+        }
+      }  
+  
+
+      /* Check if there is an add object requested 
+       */
+      $data = $this->current_handler->tree_->pap;
+      $once = TRUE;
+      foreach($_POST as $name => $value){
+        foreach($data as $key => $obj){
+          if(isset($obj->object_id) && preg_match("/^Add_Object_Top_".$obj->object_id."_/",$name) && $once){
+            $once = FALSE;
+            $this->add_element_type   =  $_POST['element_type_'.$obj->object_id];
+            $this->add_new_element    = FALSE;
+            $this->add_new_id         = $obj->object_id;
+            $this->add_above_below    = "above";
+            $this->add_new_element_to_current_script($this->add_element_type,$this->add_new_id,$this->add_above_below);
+          }
+          if(isset($obj->object_id) && preg_match("/^Add_Object_Bottom_".$obj->object_id."_/",$name) && $once){
+            $once = FALSE;
+            $this->add_element_type   =  $_POST['element_type_'.$obj->object_id];
+            $this->add_new_element    = FALSE;
+            $this->add_new_id         = $obj->object_id;
+            $this->add_above_below    = "below";
+            $this->add_new_element_to_current_script($this->add_element_type,$this->add_new_id,$this->add_above_below);
+          }
+        
+          if(isset($obj->object_id) && preg_match("/^Remove_Object_".$obj->object_id."_/",$name) && $once){
+            $once = FALSE;
+            $this->current_handler->tree_->remove_object($key);
+          }
+          if(isset($obj->object_id) && preg_match("/^Move_Up_Object_".$obj->object_id."_/",$name) && $once){
+            $this->current_handler->tree_->move_up_down($key,"up");
+            $once = FALSE;
+          }
+          if(isset($obj->object_id) && preg_match("/^Move_Down_Object_".$obj->object_id."_/",$name) && $once){
+            $this->current_handler->tree_->move_up_down($key,"down");
+            $once = FALSE;
+          }
+        }
+      }
+
+      /* Skip Mode changes and Parse tests 
+       *  if we are currently in a subdialog 
+       */
+
+      $this->current_handler->save_object();
+      $Mode = $this->scripts[$this->current_script]['MODE'];
+      $skip_mode_change = false;
+      if(in_array($Mode,array("Source-Only","Source"))){
+        if(isset($_POST['script_contents'])){
+          $sc = stripslashes($_POST['script_contents']);
+          $this->scripts[$this->current_script]['SCRIPT'] = $sc;
+          $p = new My_Parser($this);
+          if($p -> parse($sc)){
+            $this->Script_Error = "";
+          } else {
+            $this->Script_Error = $p->status_text;
+            $skip_mode_change = TRUE;
+          }
+        }
+      }
+      if(in_array($Mode,array("Structured"))){
+        $sc = $this->current_handler->get_sieve_script();
+        $this->scripts[$this->current_script]['SCRIPT'] = $sc;
+        $p = new My_Parser($this);
+        if($p -> parse($sc)){
+          $this->Script_Error = "";
+        } else {
+          $this->Script_Error = $p->status_text;
+          $skip_mode_change = TRUE;
+        }
+      }
+      if(!$skip_mode_change){
+        if($this->scripts[$this->current_script]['MODE'] != "Source-Only"){
+          $old_mode = $this->scripts[$this->current_script]['MODE'];
+          if(isset($_POST['View_Source'])){
+            $this->scripts[$this->current_script]['MODE'] = "Source";
+          }
+          if(isset($_POST['View_Structured'])){
+            $this->scripts[$this->current_script]['MODE'] = "Structured";
+          }
+          $new_mode = $this->scripts[$this->current_script]['MODE'];
+
+          if($old_mode != $new_mode){
+
+            $sc = $this->scripts[$this->current_script]['SCRIPT'];
+            $p = new My_Parser($this);
+
+            if($p -> parse($sc)){
+              $this->current_handler->parse($sc);
+              $this->Script_Error = "";
+            } else {
+              $this->Script_Error = $p->status_text;
+            }
+          } 
+        }
+      }
+    }
+  }
+
+  
+  function get_used_script_names()
+  {
+    $ret = array();
+    foreach($this->scripts as $script){
+      $ret[] = $script['NAME'];
+    }
+    return($ret);
+  }
+
+
+
+  function save()
+  {
+    /* Get sieve */
+    if(!$this->sieve_handle = $this->get_sieve()){
+      msg_dialog::display(_("SIEVE error"), sprintf(_("Cannot log into SIEVE server: %s"), '<br><br><i>'.to_string($this->Sieve_Error).'</i>'), ERROR_DIALOG);
+      return;
+    }
+
+    $everything_went_fine = TRUE;
+
+    foreach($this->scripts as $key => $script){
+      if($script['EDITED']){
+        $data = $this->scripts[$key]['SCRIPT'];
+        if(!$this->sieve_handle->sieve_sendscript($script['NAME'], addcslashes ($data,"\\"))){
+          new log("modify","users/mailAccount".get_class($this),$script['NAME'],"Failed to save sieve script named '".$script['NAME']."': ".to_string($this->sieve_handle->error_raw));
+
+          $everything_went_fine = FALSE;
+          msg_dialog::display(_("SIEVE error"), sprintf(_("Cannot store SIEVE script: %s"), '<br><br><i>'.to_string($this->sieve_handle->error_raw).'</i>'), ERROR_DIALOG);
+          $this->scripts[$key]['MSG'] = "<font color='red'>".
+                                           _("Failed to save sieve script").": ".
+                                           to_string($this->sieve_handle->error_raw).
+                                           "</font>";
+        }
+      }
+    }
+    return($everything_went_fine);
+  }
+}
+// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/class_tree.inc b/gosa-plugins/mail/personal/mail/sieve/class_tree.inc
new file mode 100644 (file)
index 0000000..d4bdfc7
--- /dev/null
@@ -0,0 +1,153 @@
+<?php
+
+class Tree
+{
+       var $childs_;
+       var $parents_;
+       var $nodes_;
+       var $maxId_;
+       var $dumpFn_;
+       var $dump_;
+
+       function Tree(&$root)
+       {
+               $this->_construct($root);
+       }
+
+       function _construct(&$root)
+       {
+               $this->childs_ = array();
+               $this->parents_ = array();
+               $this->nodes_ = array();
+               $this->maxId_ = 0;
+
+               $this->parents_[0] = null;
+               $this->nodes_[0] = $root;
+       }
+
+       function addChild(&$child)
+       {
+               return $this->addChildTo($this->maxId_, $child);
+       }
+
+       function addChildTo($parent_id, &$child)
+       {
+               if (!is_int($parent_id) ||
+                   !isset($this->nodes_[$parent_id]))
+               {
+                       return null;
+               }
+
+               if (!isset($this->childs_[$parent_id]))
+               {
+                       $this->childs_[$parent_id] = array();
+               }
+
+               $child_id = ++$this->maxId_;
+               $this->nodes_[$child_id] = $child;
+               $this->parents_[$child_id] = $parent_id;
+               array_push($this->childs_[$parent_id], $child_id);
+
+               return $child_id;
+       }
+
+       function getRoot()
+       {
+               if (!isset($this->nodes_[0]))
+               {
+                       return null;
+               }
+
+               return 0;
+       }
+
+       function getParent($node_id)
+       {
+               if (!is_int($node_id) ||
+                   !isset($this->nodes_[$node_id]))
+               {
+                       return null;
+               }
+
+               return $this->parents_[$node_id];
+       }
+
+       function getChilds($node_id)
+       {
+               if (!is_int($node_id) ||
+                   !isset($this->nodes_[$node_id]))
+               {
+                       return null;
+               }
+
+               if (!isset($this->childs_[$node_id]))
+               {
+                       return array();
+               }
+
+               return $this->childs_[$node_id];
+       }
+
+       function getNode($node_id)
+       {
+               if (!is_int($node_id) ||
+                   !isset($this->nodes_[$node_id]))
+               {
+                       return null;
+               }
+
+               return $this->nodes_[$node_id];
+       }
+
+       function setDumpFunc($callback)
+       {
+               if ($callback === NULL || is_callable($callback))
+               {
+                       $this->dumpFn_ = $callback;
+               }
+       }
+
+       function dump()
+       {
+               $this->dump_ = "tree\n";
+               $this->doDump_(0, '', true);
+               return $this->dump_;
+       }
+
+       function doDump_($node_id, $prefix, $last)
+       {
+               if ($last)
+               {
+                       $infix = '`--- ';
+                       $child_prefix = $prefix . '   ';
+               }
+               else
+               {
+                       $infix = '|--- ';
+                       $child_prefix = $prefix . '|  ';
+               }
+
+               $node = $this->nodes_[$node_id];
+               if ($this->dumpFn_ !== NULL)
+               {
+                       $this->dump_ .= $prefix . $infix . call_user_func($this->dumpFn_, $node) . "\n";
+               }
+               else
+               {
+                       $this->dump_ .= "$prefix$infix$node\n";
+               }
+
+               if (isset($this->childs_[$node_id]))
+               {
+                       $childs = $this->childs_[$node_id];
+                       $last_child = count($childs);
+
+                       for ($i=1; $i <= $last_child; ++$i)
+                       {
+                               $this->doDump_($childs[$i-1], $child_prefix, ($i == $last_child ? true : false));
+                       }
+               }
+       }
+}
+
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/libsieve.inc b/gosa-plugins/mail/personal/mail/sieve/libsieve.inc
new file mode 100644 (file)
index 0000000..3b94e49
--- /dev/null
@@ -0,0 +1,8 @@
+<?php
+require_once 'class_parser.inc';
+require_once 'class_scanner.inc';
+require_once 'class_semantics.inc';
+require_once 'class_tree.inc';
+require_once 'class_sieve.inc';
+require_once 'class_sieveElement_If.inc';
+?>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/add_element.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/add_element.tpl
new file mode 100644 (file)
index 0000000..d98c529
--- /dev/null
@@ -0,0 +1,14 @@
+<h2>{t}Add a new element{/t}</h2>
+{t}Please select the type of element you want to add{/t}
+<br>
+<select name='element_type'>
+       {html_options options=$element_types selected=$element_type }
+</select>
+
+<p class='seperator'>&nbsp;</p>
+<br>
+<div class='seperator' style='text-align:right; width:100%;'>
+    <input type='submit' name='select_new_element_type' value='{t}Continue{/t}'>
+    &nbsp;
+    <input type='submit' name='select_new_element_type_cancel' value='{t}Abort{/t}'>
+</div>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/block_indent_start.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/block_indent_start.tpl
new file mode 100644 (file)
index 0000000..482f637
--- /dev/null
@@ -0,0 +1,12 @@
+
+<table class='object_container_container'> 
+       <tr>
+               <td class='object_container_cell_top_left'>
+                       &nbsp;  
+               </td>
+               <td style='width:3px;'>
+               </td>
+               <td>
+                       
+                       <div class=''style='height:12px;'>&nbsp;</div>
+                       <div class='container_'>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/block_indent_stop.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/block_indent_stop.tpl
new file mode 100644 (file)
index 0000000..857aa68
--- /dev/null
@@ -0,0 +1,5 @@
+                       </div>
+                       <div style='height:12px;'>&nbsp;</div>
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/create_script.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/create_script.tpl
new file mode 100644 (file)
index 0000000..fa44081
--- /dev/null
@@ -0,0 +1,21 @@
+<h2>Create a new sieve script</h2>
+{t}Please enter the name for the new script below. Script names must consist of lower case characters only.{/t}
+
+<br>
+<br>
+<p class="seperator">&nbsp;</p>
+<br>
+<b>{t}Script name{/t}</b> <input type='text' name='NewScriptName' value='{$NewScriptName}'>
+<br>
+<br>
+
+<div class='seperator' style='border-top:1px solid #999; text-align:right; width:100%; padding-top:10px;'>
+   <input type='submit' name='create_script_save' value='{t}Apply{/t}' id='create_script_save'>
+   &nbsp;
+   <input type='submit' name='create_script_cancel' value='{t}Cancel{/t}'>
+</div>
+<script language="JavaScript" type="text/javascript">
+       <!--
+       focus_field('NewScriptName');
+       -->
+</script>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/edit_frame_base.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/edit_frame_base.tpl
new file mode 100644 (file)
index 0000000..83d62a0
--- /dev/null
@@ -0,0 +1,42 @@
+
+<table class='editing_surface'>
+       <tr>
+               <td class='editing_surface_menu'>
+                       
+                       <input type='submit' name='Save_Copy' value="{t}Export{/t}">
+                       <input type='submit' name='Import_Script' value="{t}Import{/t}">
+
+                       {if $Mode != "Source-Only"}                     
+                               
+                               {if $Mode == "Source"}
+                               <input type='submit' name='View_Structured' value="{t}View structured{/t}">
+                               {else}
+                               <input type='submit' name='View_Source' value="{t}View source{/t}">
+                               {/if}
+                       {/if}
+               </td>
+       </tr>
+       <tr>
+               <td class='editing_surface_content'>
+
+                       {if $Script_Error != ""}
+                                               <div  class='sieve_error_msgs'>
+                                                       {$Script_Error}
+                                               </div>
+                       {/if}
+
+
+                       {if $Mode == "Structured"}
+                               {$Contents}
+                       {else}
+                               <textarea class='editing_source' name='script_contents'>{$Contents}</textarea>
+                       {/if}
+
+               </td>
+       </tr>
+</table>
+<div class='seperator' style='text-align:right; width:100%;'>
+       <input type='submit' name='save_sieve_changes' value='{t}Save{/t}'>
+        &nbsp;
+    <input type='submit' name='cancel_sieve_changes' value='{t}Cancel{/t}'>
+</div>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_address.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_address.tpl
new file mode 100644 (file)
index 0000000..ea6580f
--- /dev/null
@@ -0,0 +1,142 @@
+{if $Expert}
+       {if $LastError != ""}
+               <table class='sieve_test_case'>
+               <tr>
+                               <td colspan=2>
+                           <font color='red'><b>{$LastError}</b></font>
+                               </td>
+                       </tr>
+               </table>
+        {/if}
+
+<table class='sieve_test_case'>
+       <tr>
+               <td >
+                       <b>{t}Address{/t}</b>
+               </td>
+        <td style='text-align:right; vertical-align:top;'>
+                       <input type='submit' name='Toggle_Expert_{$ID}' value='{t}Normal view{/t}'>
+               </td>
+       </tr>
+</table>
+<table>
+       <tr>
+               <td >
+                       {t}Match type{/t}
+               </td>
+               <td>
+                       <select name='matchtype_{$ID}' title='{t}Boolean value{/t}' onChange='document.mainform.submit();'> 
+                               {html_options options=$match_types selected=$match_type}
+                       </select>
+
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       {t}Invert test{/t}?
+               </td>
+               <td>
+                       {if $Inverse}
+                               <input type='submit' name='toggle_inverse_{$ID}' value='{t}Yes{/t}'>
+                       {else}
+                               <input type='submit' name='toggle_inverse_{$ID}' value='{t}No{/t}'>
+                       {/if}
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       {t}Part of address that should be used{/t}
+               </td>
+               <td>
+                       <select name='address_part_{$ID}' title='{t}Boolean value{/t}'> 
+                               {html_options options=$address_parts selected=$address_part}
+                       </select>
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       {t}Comparator{/t}
+               </td>
+               <td>
+                       <select name='comparator_{$ID}' title='{t}Boolean value{/t}'> 
+                               {html_options options=$comparators selected=$comparator}
+                       </select>
+               </td>
+       </tr>
+               {if $match_type == ":count" || $match_type == ":value"}
+       <tr>
+               <td>
+                       {t}Operator{/t}
+               </td>
+               <td>
+                       <select name='operator_{$ID}' title='{t}Boolean value{/t}' onChange='document.mainform.submit();'>
+                               {html_options options=$operators selected=$operator}
+                       </select>
+               </td>
+       </tr>
+               {/if}
+       <tr>
+               <td colspan=2>&nbsp;</td>
+       </tr>
+</table>
+<table style='width:100%;'>
+    <tr>
+        <td style='width:50%;'>
+            {t}Address fields to include{/t}<br>
+            <textarea style='width:100%;height:70px;' name='keys_{$ID}'>{$keys}</textarea>
+        </td>
+        <td style='width:50%;'>
+            {t}Values to match for{/t}<br>
+            <textarea style='width:100%;height:70px;' name='values_{$ID}'>{$values}</textarea>
+        </td>
+    </tr>
+</table>
+       {else}
+
+       {if $LastError != ""}
+               <table class='sieve_test_case'>
+               <tr>
+                               <td colspan=2>
+                           <font color='red'><b>{$LastError}</b></font>
+                               </td>
+                       </tr>
+               </table>
+        {/if}
+
+<table class='sieve_test_case'>
+       <tr>
+               {if $match_type == ":count" || $match_type == ":value"}
+               <td style='vertical-align:top; width:350px;'>
+               {else}
+               <td style='vertical-align:top; width:200px;'>
+               {/if}
+                       <b>{t}Address{/t}</b>
+               
+                       {if $Inverse}
+                               <input type='submit' name='toggle_inverse_{$ID}' value='{t}Not{/t}'>
+                       {else}
+                               <input type='submit' name='toggle_inverse_{$ID}' value='{t}-{/t}'>
+                       {/if}
+                       &nbsp;
+                       <select onChange='document.mainform.submit();' name='matchtype_{$ID}' title='{t}Boolean value{/t}'> 
+                               {html_options options=$match_types selected=$match_type}
+                       </select>
+
+                       {if $match_type == ":count" || $match_type == ":value"}
+                       <select name='operator_{$ID}' title='{t}Boolean value{/t}' onChange='document.mainform.submit();'>
+                               {html_options options=$operators selected=$operator}
+                       </select>
+                       {/if}
+               </td>
+               <td>
+                       <textarea style='width:100%;height:40px;' name='keys_{$ID}'>{$keys}</textarea>
+               </td>
+               <td>
+                       <textarea style='width:100%;height:40px;' name='values_{$ID}'>{$values}</textarea>
+               </td>
+               <td style='text-align:right; vertical-align:top; width:120px;'>
+                       <input type='submit' name='Toggle_Expert_{$ID}' value='{t}Expert view{/t}'>
+               </td>
+       </tr>
+</table>
+       {/if}
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_allof.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_allof.tpl
new file mode 100644 (file)
index 0000000..024c011
--- /dev/null
@@ -0,0 +1,16 @@
+<table class='sieve_allof_container'>
+       <tr>
+       <td class='sieve_allof_left'>
+            {if $Inverse}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}Not{/t}' title='{t}Inverse match{/t}'>
+            {else}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}-{/t}' title='{t}Inverse match{/t}'>
+            {/if}
+                       <br>
+                       <b>{t}All of{/t}</b>
+               </td>
+        <td class='sieve_allof_right'>
+                       {$Contents}
+        </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_anyof.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_anyof.tpl
new file mode 100644 (file)
index 0000000..f6e1b22
--- /dev/null
@@ -0,0 +1,16 @@
+<table class='sieve_anyof_container'>
+       <tr>
+       <td class='sieve_anyof_left'>
+            {if $Inverse}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}Not{/t}' title='{t}Inverse match{/t}'>
+            {else}
+                <input type='submit' name='toggle_inverse_{$ID}' value='-' title='{t}Inverse match{/t}'>
+            {/if}
+                       <br>
+                       <b>{t}Any of{/t}</b>
+               </td>
+        <td class='sieve_anyof_right'>
+                       {$Contents}
+        </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_block_end.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_block_end.tpl
new file mode 100644 (file)
index 0000000..41c3a2c
--- /dev/null
@@ -0,0 +1,5 @@
+<!--
+           </td>
+    </tr>
+</table>
+-->
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_block_start.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_block_start.tpl
new file mode 100644 (file)
index 0000000..5261624
--- /dev/null
@@ -0,0 +1,12 @@
+<!--
+<table cellspacing=0 style='width:100%;border: solid 1px #BBB;346575;'>
+       <tr>
+       <td style='width:20px; text-align:center;vertical-align:top; color: #FFFFFF; background-color:#BBBBBB;' >
+        </td>
+       <td style='width:30px; text-align:center;vertical-align:top; color: #FFFFFF; background-color:#346575;'>
+                       <b>+</b>
+        </td>
+        <td style=' background-color:#BBBBBB;
+                    border: solid 0px #DDDDDD;
+                  '>
+-->
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_boolean.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_boolean.tpl
new file mode 100644 (file)
index 0000000..44f5f7b
--- /dev/null
@@ -0,0 +1,12 @@
+<table class='sieve_test_case'>
+       <tr>
+               <td>
+                       <b>{t}Bool{/t}</b>
+                       <select name='boolean_{$ID}' title='{t}Boolean value{/t}'> 
+                               {html_options options=$values selected=$selected}
+                       </select>
+                       <input type='submit' value='{t}update{/t}'>
+                       <br>
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_comment.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_comment.tpl
new file mode 100644 (file)
index 0000000..56edf94
--- /dev/null
@@ -0,0 +1,23 @@
+<table class='sieve_comment_container'> 
+       <tr>
+               <td>
+                       <b>{t}Comment{/t}</b>
+               </td>
+               <td style='text-align: right;'>
+                       {if $Small}
+                               <input type='submit' name='toggle_small_{$ID}' value='{t}Edit{/t}'>     
+                       {else}
+                               <input type='submit' name='toggle_small_{$ID}' value='{t}Cancel{/t}'>   
+                       {/if}
+               </td>
+       </tr>
+       <tr>
+               <td style='padding-left:20px;' colspan=2>
+               {if $Small}
+                       {$Comment}
+               {else}
+                       <textarea  name='comment_{$ID}' class='sieve_comment_area'>{$Comment}</textarea>
+               {/if}
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_discard.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_discard.tpl
new file mode 100644 (file)
index 0000000..e26f77a
--- /dev/null
@@ -0,0 +1,12 @@
+<table class='sieve_discard_container'>
+       <tr>
+               <td>
+                       <b>{t}Discard{/t}</b>
+               </td>
+       </tr>
+       <tr>
+               <td class='sieve_discard_input'>
+                       {t}Discard message{/t}
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_else.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_else.tpl
new file mode 100644 (file)
index 0000000..739fd05
--- /dev/null
@@ -0,0 +1,7 @@
+<table class='sieve_default_table'>
+       <tr>
+               <td>
+                       <b>{t}Else{/t}</b>
+       </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_elsif.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_elsif.tpl
new file mode 100644 (file)
index 0000000..4da7c47
--- /dev/null
@@ -0,0 +1,8 @@
+<table class='sieve_default_table'>
+       <tr>
+               <td>
+                       <b>{t}Else If{/t}</b>
+                       {$Contents}
+       </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_envelope.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_envelope.tpl
new file mode 100644 (file)
index 0000000..f0bcb67
--- /dev/null
@@ -0,0 +1,134 @@
+
+    {if $Expert}
+        {if $LastError != ""}
+               <table class='sieve_test_case'>
+            <tr>
+                <td colspan=2>
+                    <font color='red'><b>{$LastError}</b></font>
+                </td>
+            </tr>
+               </table>
+        {/if}
+
+<table class='sieve_test_case'>
+    <tr>
+               <td style='width:50%;'>
+                       <b>{t}Envelope{/t}</b>
+               </td>
+        <td style='text-align:right; vertical-align:top;'>
+            <input type='submit' name='Toggle_Expert_{$ID}' value='{t}Normal view{/t}'>
+        </td>
+    </tr>
+</table>
+<table>
+    <tr>
+        <td style='width:50%;'>
+            {t}Match type{/t}
+        </td>
+        <td>
+            <select name='matchtype_{$ID}' title='{t}Boolean value{/t}' onChange='document.mainform.submit();'>
+                {html_options options=$match_types selected=$match_type}
+            </select>
+
+        </td>
+    </tr>
+           <tr>
+        <td>
+            {t}Invert test{/t}?
+        </td>
+        <td>
+            {if $Inverse}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}Yes{/t}' title='{t}Inverse match{/t}'>
+            {else}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}No{/t}' title='{t}Inverse match{/t}'>
+            {/if}
+        </td>
+    </tr>
+    <tr>
+        <td>
+            {t}Comparator{/t}
+        </td>
+        <td>
+            <select name='comparator_{$ID}' title='{t}Boolean value{/t}'>
+                {html_options options=$comparators selected=$comparator}
+            </select>
+        </td>
+    </tr>
+        {if $match_type == ":count" || $match_type == ":value"}
+    <tr>
+        <td>
+            {t}Operator{/t}
+        </td>
+        <td>
+            <select name='operator_{$ID}' title='{t}Boolean value{/t}' onChange='document.mainform.submit();'>
+                {html_options options=$operators selected=$operator}
+            </select>
+        </td>
+    </tr>
+        {/if}
+  <tr>
+        <td colspan=2>&nbsp;</td>
+    </tr>
+</table>
+<table style='width:100%;'> 
+    <tr>
+        <td >
+            {t}Address fields to include{/t}<br>
+            <textarea style='width:100%;height:70px;' name='keys_{$ID}'>{$keys}</textarea>
+        </td>
+        <td >
+            {t}Values to match for{/t}<br>
+            <textarea style='width:100%;height:70px;' name='values_{$ID}'>{$values}</textarea>
+        </td>
+    </tr>
+</table>
+
+       {else}
+       {if $LastError != ""}
+               <table class='sieve_test_case'>
+               <tr>
+                               <td colspan=4>
+                           <font color='red'><b>{$LastError}</b></font>
+                               </td>
+                       </tr>
+               </table>
+        {/if}
+<table class='sieve_test_case'>
+       <tr>
+               {if $match_type == ":count" || $match_type == ":value"}
+               <td style='vertical-align:top; width:350px;'>
+               {else}
+               <td style='vertical-align:top; width:200px;'>
+               {/if}
+
+                       
+                       <b>{t}Envelope{/t}</b>
+               
+                       {if $Inverse}
+                               <input type='submit' name='toggle_inverse_{$ID}' value='{t}Not{/t}'>
+                       {else}
+                               <input type='submit' name='toggle_inverse_{$ID}' value='{t}-{/t}'>
+                       {/if}
+                       &nbsp;
+                       <select onChange='document.mainform.submit();' name='matchtype_{$ID}' title='{t}Boolean value{/t}'> 
+                               {html_options options=$match_types selected=$match_type}
+                       </select>
+
+                       {if $match_type == ":count" || $match_type == ":value"}
+                       <select name='operator_{$ID}' title='{t}Boolean value{/t}' onChange='document.mainform.submit();'>
+                               {html_options options=$operators selected=$operator}
+                       </select>
+                       {/if}
+               </td>
+               <td>
+                       <textarea style='width:100%;height:40px;' name='keys_{$ID}'>{$keys}</textarea>
+               </td>
+               <td>
+                       <textarea style='width:100%;height:40px;' name='values_{$ID}'>{$values}</textarea>
+               </td>
+               <td style='text-align:right; vertical-align:top; width:120px;'>
+                       <input type='submit' name='Toggle_Expert_{$ID}' value='{t}Expert view{/t}'>
+               </td>
+       </tr>
+</table>
+       {/if}
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_exists.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_exists.tpl
new file mode 100644 (file)
index 0000000..29882d3
--- /dev/null
@@ -0,0 +1,20 @@
+<table class='sieve_test_case'>
+    <tr>
+        <td style='vertical-align:top; width:200px;'>
+            {if $LastError != ""}
+                <font color='red'>{$LastError}</font>
+                <br>
+            {/if}
+            <b>{t}Exists{/t}</b>
+            {if $Inverse}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}Not{/t}' title='{t}Inverse match{/t}'>
+            {else}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}-{/t}' title='{t}Inverse match{/t}'>
+            {/if}
+
+               </td>
+               <td>
+            <textarea style='width:99%;height:20px;' name='Values_{$ID}'>{$Values}</textarea>
+               </td>
+    </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_fileinto.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_fileinto.tpl
new file mode 100644 (file)
index 0000000..c6ae998
--- /dev/null
@@ -0,0 +1,30 @@
+<table class='sieve_fileinto_container'>
+       <tr>
+               <td colspan=2>
+                       <b>{t}Move mail into folder{/t}</b>
+               </td>
+               <td style='text-align:right;'>
+                       {if $User_Mode}
+                               <input type='submit' name='user_mode_{$ID}' value='{t}Select from list{/t}'>
+                       {else}
+                               <input type='submit' name='user_mode_{$ID}' value='{t}Manual selection{/t}'>
+                       {/if}
+               </td>
+       </tr>
+       <tr>
+               <td style='width:20px;'>
+               </td>
+               <td>
+                       {t}Folder{/t}
+                       {if $User_Mode}
+                               <input class='sieve_fileinto_input' type='text' value="{$Selected}" name='fileinto_{$ID}'>
+                       {else}
+                               <select name='fileinto_{$ID}' class='sieve_fileinto_input'>
+                                       {html_options values=$Boxes output=$Boxes selected=$Selected}
+                               </select>
+                       {/if}
+               </td>
+               <td >
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_header.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_header.tpl
new file mode 100644 (file)
index 0000000..8dcd309
--- /dev/null
@@ -0,0 +1,136 @@
+       {if $Expert}
+       {if $LastError != ""}
+               <table class='sieve_test_case'>
+               <tr>
+                               <td colspan=4>
+                           <font color='red'><b>{$LastError}</b></font>
+                               </td>
+                       </tr>
+               </table>
+        {/if}
+
+
+<table class='sieve_test_case'>
+       <tr>
+               <td>
+                       <b>{t}Header{/t}</b>
+               </td>
+        <td style='text-align:right; vertical-align:top;'>
+            <input type='submit' name='Toggle_Expert_{$ID}' value='{t}Normal view{/t}'>
+        </td>
+    </tr>
+</table>
+<table>
+    <tr>
+               <td>
+            {t}Match type{/t}
+        </td>
+        <td>
+            <select name='matchtype_{$ID}' title='{t}Boolean value{/t}' onChange='document.mainform.submit();'>
+                {html_options options=$match_types selected=$match_type}
+            </select>
+
+        </td>
+    </tr>
+    <tr>
+        <td>
+            {t}Invert test{/t}?
+        </td>
+        <td>
+            {if $Inverse}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}Yes{/t}'>
+            {else}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}No{/t}'>
+            {/if}
+        </td>
+    </tr>
+    <tr>
+        <td>
+            {t}Comparator{/t}
+        </td>
+        <td>
+            <select name='comparator_{$ID}' title='{t}Boolean value{/t}'>
+                {html_options options=$comparators selected=$comparator}
+            </select>
+        </td>
+    </tr>
+        {if $match_type == ":count" || $match_type == ":value"}
+    <tr>
+        <td>
+            {t}operator{/t}
+        </td>
+        <td>
+            <select name='operator_{$ID}' title='{t}Boolean value{/t}' onChange='document.mainform.submit();'>
+                {html_options options=$operators selected=$operator}
+            </select>
+        </td>
+    </tr>
+        {/if}
+
+        <tr>
+        <td colspan=2>&nbsp;</td>
+    </tr>
+   </table>
+   <table class='sieve_test_case'>
+    <tr>
+        <td >
+            {t}Address fields to include{/t}<br>
+            <textarea style='width:100%;height:70px;' name='keys_{$ID}'>{$keys}</textarea>
+        </td>
+        <td >
+            {t}Values to match for{/t}<br>
+            <textarea style='width:100%;height:70px;' name='values_{$ID}'>{$values}</textarea>
+        </td>
+    </tr>
+       </table>
+
+       {else}
+       {if $LastError != ""}
+               <table class='sieve_test_case'>
+               <tr>
+                               <td colspan=4>
+                           <font color='red'><b>{$LastError}</b></font>
+                               </td>
+                       </tr>
+               </table>
+        {/if}
+
+               
+<table class='sieve_test_case'>
+    <tr>
+               {if $match_type == ":count" || $match_type == ":value"}
+               <td style='vertical-align:top; width:350px;'>
+               {else}
+               <td style='vertical-align:top; width:200px;'>
+               {/if}
+            <b>{t}Header{/t}</b>
+
+            {if $Inverse}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}Not{/t}'>
+            {else}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}-{/t}'>
+            {/if}
+            &nbsp;
+            <select onChange='document.mainform.submit();' name='matchtype_{$ID}' title='{t}Boolean value{/t}'>
+                {html_options options=$match_types selected=$match_type}
+            </select>
+
+            {if $match_type == ":count" || $match_type == ":value"}
+            <select name='operator_{$ID}' title='{t}Boolean value{/t}' onChange='document.mainform.submit();'>
+                {html_options options=$operators selected=$operator}
+            </select>
+            {/if}
+        </td>
+        <td>
+            <textarea style='width:100%;height:40px;' name='keys_{$ID}'>{$keys}</textarea>
+        </td>
+        <td>
+            <textarea style='width:100%;height:40px;' name='values_{$ID}'>{$values}</textarea>
+        </td>
+        <td style='text-align:right; vertical-align:top; width:120px;'>
+            <input type='submit' name='Toggle_Expert_{$ID}' value='{t}Expert view{/t}'>
+        </td>
+    </tr>
+
+</table>
+       {/if}
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_if.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_if.tpl
new file mode 100644 (file)
index 0000000..98f9b4a
--- /dev/null
@@ -0,0 +1,8 @@
+<table class='sieve_default_table'>
+       <tr>
+       <td>
+                       <b>{t}Condition{/t}</b>
+                       {$Contents}
+       </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_keep.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_keep.tpl
new file mode 100644 (file)
index 0000000..f3c5d86
--- /dev/null
@@ -0,0 +1,12 @@
+<table class='sieve_keep_container'>
+       <tr>
+               <td>
+                       <b>{t}Keep{/t}</b>
+               </td>
+       </tr>
+       <tr>
+               <td class='sieve_keep_input'>
+                       {t}Keep message{/t}
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_redirect.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_redirect.tpl
new file mode 100644 (file)
index 0000000..778ff1a
--- /dev/null
@@ -0,0 +1,22 @@
+<table class='sieve_redirect_container'>
+       {foreach from=$LastError item=val key=key}
+        <tr>
+            <td colspan=4>
+                <div class='sieve_error_msgs'>{$LastError[$key]}</div>
+
+            </td>
+        </tr>
+
+    {/foreach}
+       <tr>
+               <td>
+                       <b>{t}Redirect{/t}</b>
+               </td>
+       </tr>
+       <tr>
+               <td class='sieve_redirect_input'>
+                       {t}Redirect mail to following recipients{/t}<br>
+                       <textarea name='redirect_to_{$ID}' class='sieve_redirect_input'>{$Destinations}</textarea>
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_reject.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_reject.tpl
new file mode 100644 (file)
index 0000000..3b4d84d
--- /dev/null
@@ -0,0 +1,28 @@
+<table class='sieve_reject_container'>
+
+{foreach from=$LastError item=val key=key}
+        <tr>
+            <td colspan=4>
+                <div class='sieve_error_msgs'>{$LastError[$key]}</div>
+
+            </td>
+        </tr>
+
+    {/foreach}
+       <tr>
+               <td>
+                       <b>{t}Reject mail{/t}</b>
+                       &nbsp;
+                       {if $Multiline}
+<!--                           {t}This is a multiline text element{/t}-->
+                       {else}
+<!--                           {t}This is stored as single string{/t}-->
+                       {/if}
+               </td>
+       </tr>
+       <tr>
+               <td class='sieve_reject_input'>
+                       <textarea name='reject_message_{$ID}' class='sieve_reject_input'>{$Message}</textarea>
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_require.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_require.tpl
new file mode 100644 (file)
index 0000000..3a3f261
--- /dev/null
@@ -0,0 +1,21 @@
+<table class='sieve_require_container'>
+       {foreach from=$LastError item=val key=key}
+               <tr>
+                       <td colspan=4>
+                               <div class='sieve_error_msgs'>{$LastError[$key]}</div>
+                       </td>
+               </tr>
+
+       {/foreach}
+       <tr>
+               <td style=''>
+                       <b>{t}Require{/t}</b>
+               </td>
+       </tr>
+       <tr>
+               <td style='padding-left:20px;;'>
+                       <input type='text'  name='require_{$ID}' class='sieve_require_input' value='{$Require}'>
+               </td>
+       </tr>
+</table>
+
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_size.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_size.tpl
new file mode 100644 (file)
index 0000000..a8e2346
--- /dev/null
@@ -0,0 +1,25 @@
+<table class='sieve_test_case'>
+       <tr>
+               <td>
+                       <b>{t}Size{/t}</b>
+                       {if $LastError != ""}
+                               <font color='red'>{$LastError}</font>
+                               <br>
+                       {/if}                   
+
+               {if $Inverse}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}Not{/t}' title='{t}Inverse match{/t}'>
+            {else}
+                <input type='submit' name='toggle_inverse_{$ID}' value='{t}-{/t}' title='{t}Inverse match{/t}'>
+            {/if}
+
+                       <select name='Match_type_{$ID}' title='{t}Select match type{/t}'>
+                               {html_options options=$Match_types selected=$Match_type}
+                       </select>
+                       <input type='text' name='Value_{$ID}' value='{$Value}'>
+                       <select name='Value_Unit_{$ID}' title='{t}Select value unit{/t}'>
+                               {html_options options=$Units selected=$Value_Unit}
+                       </select>
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_stop.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_stop.tpl
new file mode 100644 (file)
index 0000000..975f10b
--- /dev/null
@@ -0,0 +1,12 @@
+<table class='sieve_stop_container'>
+       <tr>
+               <td>
+                       <b>{t}Stop{/t}</b><br>
+               </td>
+       </tr>
+       <tr>
+               <td class='sieve_stop_input'>
+                       {t}Stop execution here{/t}
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_vacation.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_vacation.tpl
new file mode 100644 (file)
index 0000000..1741487
--- /dev/null
@@ -0,0 +1,56 @@
+<table class='sieve_vacation_container'>
+
+       {foreach from=$LastError item=val key=key}
+               <tr>
+                       <td colspan=4>
+                               <div class='sieve_error_msgs'>{$LastError[$key]}</div>
+                       </td>
+               </tr>
+       {/foreach}
+       {if $Expert}
+       <tr>
+               <td style='width:20%'>  
+                       <b>{t}Vacation Message{/t}</b>
+               </td>   
+        <td style='text-align:right; vertical-align:top;'>
+            <input type='submit' name='Toggle_Expert_{$ID}' value='{t}Normal view{/t}'>
+        </td>
+       </tr>
+       <tr>
+               <td >
+                       {t}Release interval{/t}&nbsp;
+               </td>
+               <td>
+                       <input type='text' name='vacation_release_{$ID}' value='{$Days}'>
+                       &nbsp;{t}days{/t}
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       {t}Alternative sender addresses{/t}
+               </td>
+               <td>
+               <textarea name='vacation_receiver_{$ID}' style='width:100%;height:20px;'>{$Addresses}</textarea>
+               </td>
+       </tr>
+       <tr>
+               <td class='sieve_vacation_input' colspan=2>
+                   <textarea name='vacation_reason_{$ID}' class='sieve_vacation_input'>{$Reason}</textarea>
+               </td>
+       </tr>
+       {else}
+       <tr>
+               <td>    
+                       <b>{t}Vacation message{/t}</b>
+               </td>   
+               <td width='10%' style='vertical-align:top;'>
+            <input type='submit' name='Toggle_Expert_{$ID}' value='{t}Expert view{/t}'>
+               </td>
+       </tr>
+       <tr>
+               <td class='sieve_vacation_input' colspan=2>
+                   <textarea name='vacation_reason_{$ID}' class='sieve_vacation_input'>{$Reason}</textarea>
+               </td>
+       </tr>
+       {/if}
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/import_script.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/import_script.tpl
new file mode 100644 (file)
index 0000000..22df06c
--- /dev/null
@@ -0,0 +1,15 @@
+<h2>{t}Import sieve script{/t}</h2>
+{t}Please select the sieve script you want to import. Use the import button to import the script or the cancel button to abort.{/t}
+<br>
+<br>
+<b>{t}Script to import{/t}</b>&nbsp;<input type='file' name='Script_To_Import'>
+
+<br>
+<br>
+<p class='seperator'>&nbsp;</p>
+<br>
+<div class='seperator' style='text-align:right; width:100%;'>
+    <input type='submit' name='Import_Script_Save' value='{t}Import{/t}'>
+        &nbsp;
+    <input type='submit' name='Import_Script_Cancel' value='{t}Cancel{/t}'>
+</div>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/management.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/management.tpl
new file mode 100644 (file)
index 0000000..315e47e
--- /dev/null
@@ -0,0 +1,27 @@
+<h2>{t}List of sieve scripts{/t}</h2>
+<!--
+{if $uattrib_empty}
+               
+       <font color='red'><b>{t}Connection to the sieve server could not be established, the authentification attribute is empty.{/t}</b></font><br>
+       {t}Please verfiy that the attributes uid and mail are not empty and try again.{/t}
+       <br>
+       <br>
+
+{elseif $Sieve_Error != ""}
+
+       <font color='red'><b>{t}Connection to the sieve server could not be established.{/t}</b></font><br>
+       {$Sieve_Error}
+       <br>
+       {t}Possibly the sieve account has not been created yet.{/t}
+       <br>
+       <br>
+{/if}
+       {t}Be careful. All your changes will be saved directly to sieve, if you use the save button below.{/t}
+-->
+       {$List}
+       <input type='submit' name='create_new_script' value='{t}Create new script{/t}'>
+       <p style="text-align:right;border-top:1px solid #999; padding-top:10px;">
+               <input type=submit name="sieve_finish" style="width:80px" value="{t}Save{/t}">
+               &nbsp;
+               <input type=submit name="sieve_cancel" value="{t}Cancel{/t}">
+       </p>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/object_container.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/object_container.tpl
new file mode 100644 (file)
index 0000000..14925b1
--- /dev/null
@@ -0,0 +1,54 @@
+<table class='object_container_container'> 
+       <tr>
+               <td class='object_container_cell_top_left'>
+                       &nbsp;  
+               </td>
+               <td class='object_container_cell_top_right'>
+                       <input type='image' src='images/sieve_move_object_up.png' name='Move_Up_Object_{$ID}' 
+                               title='{t}Move object up one position{/t}' alt='{t}Up{/t}' class='center'>
+                       <a href='{$plug}&amp;Move_Up_Object_ID={$ID}'>{t}Move up{/t}</a>
+                       &nbsp;&nbsp;&nbsp;
+                       <input type='image' src='images/sieve_move_object_down.png' name='Move_Down_Object_{$ID}' 
+                               title='{t}Move object down one position{/t}' alt='{t}Down{/t}' class='center'>
+                       <a href='{$plug}&amp;Move_Down_Object_ID={$ID}'>{t}Move down{/t}</a>
+                       &nbsp;&nbsp;&nbsp;
+                       <input type='image' src='images/sieve_del_object.png' name='Remove_Object_{$ID}' 
+                               title='{t}Remove object{/t}' alt='R' class='center'>
+                       <a href='{$plug}&amp;Remove_Object_ID={$ID}'>{t}Remove element{/t}</a>
+                       &nbsp;&nbsp;&nbsp;
+       
+                       <select name='element_type_{$ID}'>
+                               <option value=''>&lt;{t}choose element{/t}&gt;</option>
+                               <option value='sieve_keep'>{t}Keep{/t}</option>
+                               <option value='sieve_comment'>{t}Comment{/t}</option>
+                               <option value='sieve_fileinto'>{t}Fileinto{/t}</option>
+                               <option value='sieve_keep'>{t}Keep{/t}</option>
+                               <option value='sieve_discard'>{t}Discard{/t}</option>
+                               <option value='sieve_redirect'>{t}Redirect{/t}</option>
+                               <option value='sieve_reject'>{t}Reject{/t}</option>
+                               <option value='sieve_require'>{t}Require{/t}</option>
+                               <option value='sieve_stop'>{t}Stop{/t}</option>
+                               <option value='sieve_vacation'>{t}Vacation message{/t}</option>
+                               <option value='sieve_if'>{t}If{/t}</option>
+                               <option value='sieve_else'>{t}Else{/t}</option>
+                               <option value='sieve_elsif'>{t}Else If{/t}</option>
+                       </select>
+
+                       <input type='image' src='images/sieve_add_new_top.png' name='Add_Object_Top_{$ID}'
+                               alt='{t}Add new{/t}' title='{t}Add a new object above this one.{/t}' class='center'>
+                       <input type='image' src='images/truly_not_available_image' name='Add_Object_Top_{$ID}'
+                               alt='{t}Add element above{/t}' title='{t}Add a new object above this one.{/t}' class='center'>
+                       <input type='image' src='images/sieve_add_new_bottom.png' name='Add_Object_Bottom_{$ID}'
+                               alt='{t}Add new{/t}' title='{t}Add a new object below this one.{/t}' class='center'>    
+                       <input type='image' src='images/truly_not_available_image' name='Add_Object_Bottom_{$ID}'
+                               alt='{t}Add element below{/t}' title='{t}Add a new object below this one.{/t}' class='center'>  
+               </td>
+       </tr>
+       <tr>
+               <td class='object_container_cell_bottom_left'>
+               </td>
+               <td>
+                       %%OBJECT_CONTENT%%
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/object_container_clear.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/object_container_clear.tpl
new file mode 100644 (file)
index 0000000..4f5579f
--- /dev/null
@@ -0,0 +1,28 @@
+<table class='object_container_container'> 
+       <tr>
+               <td class='object_container_cell_top_left'>
+                       &nbsp;  
+               </td>
+               <td class='object_container_cell_top_right'>
+                   <input type='image' src='images/sieve_move_object_up.png' name='Move_Up_Object_{$ID}'
+                title='{t}Move this object up one position{/t}' alt='{t}Up{/t}' class='center'>
+            <a href='{$plug}&amp;Move_Up_Object_ID={$ID}'>{t}Move up{/t}</a>
+
+            <input type='image' src='images/sieve_move_object_down.png' name='Move_Down_Object_{$ID}'
+                title='{t}Move this object down one position{/t}' alt='{t}Down{/t}' class='center'>
+            <a href='{$plug}&amp;Move_Down_Object_ID={$ID}'>{t}Move down{/t}</a>
+
+            <input type='image' src='images/sieve_del_object.png' name='Remove_Object_{$ID}'
+                title='{t}Remove this object{/t}' alt='R' class='center'>
+            <a href='{$plug}&amp;Remove_Object_ID={$ID}'>{t}Remove element{/t}</a>
+
+               </td>
+    </tr>
+    <tr>
+               <td class='object_container_cell_bottom_left'>
+        </td>
+        <td>
+            %%OBJECT_CONTENT%%
+        </td>
+    </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/object_test_container.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/object_test_container.tpl
new file mode 100644 (file)
index 0000000..e157717
--- /dev/null
@@ -0,0 +1,17 @@
+<table class='sieve_test_container'>
+       <tr>
+               <td style='width:20px; ; text-align:center; vertical-align:top;'>       
+                       {if $DisplayAdd}
+                               <input type='image' src='images/sieve_add_test.png' name='Add_Test_Object_{$ID}' 
+                                       title='{t}Add object{/t}' alt='R' class='center'>
+                       {/if}
+                       {if $DisplayDel}
+                               <input type='image' src='images/sieve_del_object.png' name='Remove_Test_Object_{$ID}' 
+                                       title='{t}Remove object{/t}' alt='R' class='center'>
+                       {/if}
+               </td>
+               <td>
+                       %%OBJECT_CONTENT%%
+               </td>
+       </tr>
+</table>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/remove_script.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/remove_script.tpl
new file mode 100644 (file)
index 0000000..5bb5b49
--- /dev/null
@@ -0,0 +1,17 @@
+<div style="font-size:18px;">
+<img alt="" src="images/button_cancel.png" align=top>&nbsp;{t}Warning{/t}
+</div>
+<p>
+ {$Warning}<br>
+ {t}Please double check if your really want to do this since there is no way for GOsa to get your data back.{/t}
+</p>
+
+<p>
+ {t}Best thing to do before performing this action would be to save the current script in a file. So - if you've done so - press 'Delete' to continue or 'Cancel' to abort.{/t}
+</p>
+
+<p class="plugbottom">
+  <input type=submit name="delete_script_confirm" value="{t}Delete{/t}">
+  &nbsp;
+  <input type=submit name="delete_cancel" value="{t}Cancel{/t}">
+</p>
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/select_test_type.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/select_test_type.tpl
new file mode 100644 (file)
index 0000000..dd7a8fb
--- /dev/null
@@ -0,0 +1,14 @@
+<h2>{t}Select the type of test you want to add{/t}</h2>
+
+<b>{t}Available test types{/t}</b>&nbsp;:&nbsp;
+<select name='test_type_to_add_{$ID}'>
+       {html_options options=$test_types_to_add}
+</select>
+
+<p class='seperator'>&nbsp;</p>
+<br>
+<div class='seperator' style='text-align:right; width:100%;'>
+       <input type='submit' name='add_type' value='{t}Continue{/t}'>
+       &nbsp;
+       <input type='submit' name='does_nothing' value='{t}Cancel{/t}'>
+</div>