summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e3e00d8)
raw | patch | inline | side by side (parent: e3e00d8)
author | cajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8> | |
Thu, 17 Jan 2008 08:43:34 +0000 (08:43 +0000) | ||
committer | cajus <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:
diff --git a/gosa-core/plugins/personal/connectivity/class_kolabAccount.inc b/gosa-core/plugins/personal/connectivity/class_kolabAccount.inc
+++ /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> </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")." : <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
+++ /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> </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">
- <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> </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">
- {/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}
- <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">
-
- </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
--- /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> </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")." : <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
--- /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> </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">
+ <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> </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">
+ {/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}
+ <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">
+
+ </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
--- /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
--- /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
+++ /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
+++ /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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("/ /"," ",$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
--- /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
--- /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
--- /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
--- /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")." ("._("Default").")",
+ ":domain" => _("Domain part") ,
+ ":localpart" => _("Local part"));
+
+ /* comparator type */
+ $this->comparators = array(
+ "i;ascii-casemap" => _("Case insensitive")." ("._("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 .= " - "._("If");
+ }elseif($this->TYPE == "elsif"){
+ $name .= " - "._("Else If");
+ }else{
+ $name .= " - "._("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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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" => " ",
+ "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").": ".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
--- /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
--- /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
--- /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'> </p>
+<br>
+<div class='seperator' style='text-align:right; width:100%;'>
+ <input type='submit' name='select_new_element_type' value='{t}Continue{/t}'>
+
+ <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
--- /dev/null
@@ -0,0 +1,12 @@
+
+<table class='object_container_container'>
+ <tr>
+ <td class='object_container_cell_top_left'>
+
+ </td>
+ <td style='width:3px;'>
+ </td>
+ <td>
+
+ <div class=''style='height:12px;'> </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
--- /dev/null
@@ -0,0 +1,5 @@
+ </div>
+ <div style='height:12px;'> </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
--- /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"> </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'>
+
+ <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
--- /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}'>
+
+ <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
--- /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> </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}
+
+ <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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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> </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}
+
+ <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
--- /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
--- /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
--- /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> </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}
+
+ <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
--- /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
--- /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
--- /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
--- /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>
+
+ {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
--- /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
--- /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
--- /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
--- /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}
+ </td>
+ <td>
+ <input type='text' name='vacation_release_{$ID}' value='{$Days}'>
+ {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
--- /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> <input type='file' name='Script_To_Import'>
+
+<br>
+<br>
+<p class='seperator'> </p>
+<br>
+<div class='seperator' style='text-align:right; width:100%;'>
+ <input type='submit' name='Import_Script_Save' value='{t}Import{/t}'>
+
+ <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
--- /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}">
+
+ <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
--- /dev/null
@@ -0,0 +1,54 @@
+<table class='object_container_container'>
+ <tr>
+ <td class='object_container_cell_top_left'>
+
+ </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}&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 object down one position{/t}' alt='{t}Down{/t}' class='center'>
+ <a href='{$plug}&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 object{/t}' alt='R' class='center'>
+ <a href='{$plug}&Remove_Object_ID={$ID}'>{t}Remove element{/t}</a>
+
+
+ <select name='element_type_{$ID}'>
+ <option value=''><{t}choose element{/t}></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
--- /dev/null
@@ -0,0 +1,28 @@
+<table class='object_container_container'>
+ <tr>
+ <td class='object_container_cell_top_left'>
+
+ </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}&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}&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}&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
--- /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
--- /dev/null
@@ -0,0 +1,17 @@
+<div style="font-size:18px;">
+<img alt="" src="images/button_cancel.png" align=top> {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}">
+
+ <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
--- /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> :
+<select name='test_type_to_add_{$ID}'>
+ {html_options options=$test_types_to_add}
+</select>
+
+<p class='seperator'> </p>
+<br>
+<div class='seperator' style='text-align:right; width:100%;'>
+ <input type='submit' name='add_type' value='{t}Continue{/t}'>
+
+ <input type='submit' name='does_nothing' value='{t}Cancel{/t}'>
+</div>