From: cajus Date: Thu, 17 Jan 2008 08:43:34 +0000 (+0000) Subject: Moved kolab X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=0d4ac59cc46ece3e0bfb4aa4bc35911f125d4b3f;p=gosa.git Moved kolab git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@8435 594d385d-05f5-0310-b6e9-bd551577e9d8 --- diff --git a/gosa-core/plugins/personal/connectivity/class_kolabAccount.inc b/gosa-core/plugins/personal/connectivity/class_kolabAccount.inc deleted file mode 100644 index a9149d4dc..000000000 --- a/gosa-core/plugins/personal/connectivity/class_kolabAccount.inc +++ /dev/null @@ -1,602 +0,0 @@ -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 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.= ""; - - 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.= ""; - } - $invitation.= ""; - - /* Add mode switch */ - $invitation.= ""; - } - if ($nr != 0) { - $button.= ""; - } - - $invitation.= "  - $button - \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")." : "._("Connectivity addon")."", - "plSelfModify" => TRUE, - "plDepends" => array("user"), - "plPriority" => 20, // Position in tabs - "plSection" => array("personal" => _("My account")), - "plCategory" => array("users"), - "plOptions" => array(), - - "plProvidedAcls" => array( - "kolabFreeBusyFuture" => _("Free busy future"), - "unrestrictedMailSize" => _("Mail size restriction"), - "calFBURL" => _("Free busy information"), - "kolabDelegate" => _("Delegations"), - "kolabInvitationPolicy" => _("Invitation policy")) - )); - } - - - /*! \brief Enable multiple edit support. \ - Also sets $this->mail_account to TRUE, which simulates \ - a valid mail extension. - */ - public function enable_multiple_support() - { - plugin::enable_multiple_support(); - $this->mail_Account = TRUE; - } - - - /*! \brief Save html POSTs in multiple edit. - */ - public function multiple_save_object() - { - if (isset($_POST['connectivityTab'])){ - plugin::multiple_save_object(); - if(isset($_POST['use_kolabState'])){ - $this->multi_boxes[] = "kolabState"; - } - $this->save_object(); - } - } - - - /*! \brief Returns all modified values. \ - All selected an modified values will be returned \ - in an array. - @return array Returns an array containing all attribute modifications - */ - public function get_multi_edit_values() - { - $ret = plugin::get_multi_edit_values(); - if(in_array("kolabState",$this->multi_boxes)){ - $ret['is_account'] = $this->is_account; - } - - print_a($ret); - - return($ret); - } - - /*! \brief Sets modified attributes in mutliple edit. \ - All collected values from "get_multi_edit_values()" \ - will be applied to this plugin. - @param array An array containing modified attributes returned by get_multi_edit_values(); - */ - public function set_multi_edit_values($values) - { - plugin::set_multi_edit_values($values); - if(isset($values['is_account'])){ - $this->is_account = $values['is_account']; - } - } - - - /*! \brief Initialize multiple edit ui for this plugin. \ - This function sets plugin defaults in multiple edit. - @param array Attributes used in all object - @param array All used attributes. - */ - public function init_multiple_support($attrs,$all) - { - plugin::init_multiple_support($attrs,$all); - if(isset($attrs['objectClass']) && in_array("kolabInetOrgPerson",$attrs['objectClass'])){ - $this->is_account = TRUE; - } - - /* Pull arrays */ - foreach(array("kolabDelegate", "kolabInvitationPolicy") as $attr){ - if (isset($this->multi_attrs["$attr"]["count"])){ - $tmp = array(); - for ($i= 0; $i<$this->multi_attrs["$attr"]["count"]; $i++){ - $tmp[]=$this->multi_attrs["$attr"][$i]; - } - $this->$attr = $tmp; - } - } - - /* If this one is empty, preset with ACT_MANUAL for anonymous users */ - if (count ($this->kolabInvitationPolicy) == 0){ - $this->kolabInvitationPolicy= array("ACT_MANUAL"); - } - } -} - -// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: -?> diff --git a/gosa-core/plugins/personal/connectivity/kolab.tpl b/gosa-core/plugins/personal/connectivity/kolab.tpl deleted file mode 100644 index c05bfb177..000000000 --- a/gosa-core/plugins/personal/connectivity/kolab.tpl +++ /dev/null @@ -1,134 +0,0 @@ - -{if !$mail_account} -

{t}Kolab account{/t}

- {t}The kolab account is currently disabled. It's features can be adjusted if you add a mail account.{/t} -{else} - -

-{if $multiple_support} - - - - -{else} - -{/if} - -{t}Kolab account{/t}

- - - - - - -
- -{if $multiple_support} - -
- -
- -   - - -{else} -
- {render acl=$kolabDelegateACL} - - {/render} -
- {render acl=$kolabDelegateACL} - - {/render} - {render acl=$kolabDelegateACL} -   - {/render} - {render acl=$kolabDelegateACL} - - {/render} -{/if} - -

{t}Mail size{/t}

-{render acl=$unrestrictedMailSizeACL checkbox=$multiple_support checked=$use_unrestrictedMailSize} -   - {t}No mail size restriction for this account{/t} -{/render} -
-   - - -

{t}Free Busy information{/t}

- - - - - - - - - -
-{render acl=$calFBURLACL checkbox=$multiple_support checked=$use_calFBURL} - -{/render} -
-{render acl=$kolabFreeBusyFutureACL checkbox=$multiple_support checked=$use_kolabFreeBusyFuture} - - {t}days{/t} -{/render} -
- - -

{t}Invitation policy{/t}

-{if $multiple_support} - -{/if} -{render acl=$kolabInvitationPolicyACL} - - {$invitation} -
-{/render} - - -
- -{/if} diff --git a/gosa-plugins/kolab/personal/connectivity/class_kolabAccount.inc b/gosa-plugins/kolab/personal/connectivity/class_kolabAccount.inc new file mode 100644 index 000000000..a9149d4dc --- /dev/null +++ b/gosa-plugins/kolab/personal/connectivity/class_kolabAccount.inc @@ -0,0 +1,602 @@ +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 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.= ""; + + 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.= ""; + } + $invitation.= ""; + + /* Add mode switch */ + $invitation.= ""; + } + if ($nr != 0) { + $button.= ""; + } + + $invitation.= "  + $button + \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")." : "._("Connectivity addon")."", + "plSelfModify" => TRUE, + "plDepends" => array("user"), + "plPriority" => 20, // Position in tabs + "plSection" => array("personal" => _("My account")), + "plCategory" => array("users"), + "plOptions" => array(), + + "plProvidedAcls" => array( + "kolabFreeBusyFuture" => _("Free busy future"), + "unrestrictedMailSize" => _("Mail size restriction"), + "calFBURL" => _("Free busy information"), + "kolabDelegate" => _("Delegations"), + "kolabInvitationPolicy" => _("Invitation policy")) + )); + } + + + /*! \brief Enable multiple edit support. \ + Also sets $this->mail_account to TRUE, which simulates \ + a valid mail extension. + */ + public function enable_multiple_support() + { + plugin::enable_multiple_support(); + $this->mail_Account = TRUE; + } + + + /*! \brief Save html POSTs in multiple edit. + */ + public function multiple_save_object() + { + if (isset($_POST['connectivityTab'])){ + plugin::multiple_save_object(); + if(isset($_POST['use_kolabState'])){ + $this->multi_boxes[] = "kolabState"; + } + $this->save_object(); + } + } + + + /*! \brief Returns all modified values. \ + All selected an modified values will be returned \ + in an array. + @return array Returns an array containing all attribute modifications + */ + public function get_multi_edit_values() + { + $ret = plugin::get_multi_edit_values(); + if(in_array("kolabState",$this->multi_boxes)){ + $ret['is_account'] = $this->is_account; + } + + print_a($ret); + + return($ret); + } + + /*! \brief Sets modified attributes in mutliple edit. \ + All collected values from "get_multi_edit_values()" \ + will be applied to this plugin. + @param array An array containing modified attributes returned by get_multi_edit_values(); + */ + public function set_multi_edit_values($values) + { + plugin::set_multi_edit_values($values); + if(isset($values['is_account'])){ + $this->is_account = $values['is_account']; + } + } + + + /*! \brief Initialize multiple edit ui for this plugin. \ + This function sets plugin defaults in multiple edit. + @param array Attributes used in all object + @param array All used attributes. + */ + public function init_multiple_support($attrs,$all) + { + plugin::init_multiple_support($attrs,$all); + if(isset($attrs['objectClass']) && in_array("kolabInetOrgPerson",$attrs['objectClass'])){ + $this->is_account = TRUE; + } + + /* Pull arrays */ + foreach(array("kolabDelegate", "kolabInvitationPolicy") as $attr){ + if (isset($this->multi_attrs["$attr"]["count"])){ + $tmp = array(); + for ($i= 0; $i<$this->multi_attrs["$attr"]["count"]; $i++){ + $tmp[]=$this->multi_attrs["$attr"][$i]; + } + $this->$attr = $tmp; + } + } + + /* If this one is empty, preset with ACT_MANUAL for anonymous users */ + if (count ($this->kolabInvitationPolicy) == 0){ + $this->kolabInvitationPolicy= array("ACT_MANUAL"); + } + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/kolab/personal/connectivity/kolab.tpl b/gosa-plugins/kolab/personal/connectivity/kolab.tpl new file mode 100644 index 000000000..c05bfb177 --- /dev/null +++ b/gosa-plugins/kolab/personal/connectivity/kolab.tpl @@ -0,0 +1,134 @@ + +{if !$mail_account} +

{t}Kolab account{/t}

+ {t}The kolab account is currently disabled. It's features can be adjusted if you add a mail account.{/t} +{else} + +

+{if $multiple_support} + + + + +{else} + +{/if} + +{t}Kolab account{/t}

+ + + + + + +
+ +{if $multiple_support} + +
+ +
+ +   + + +{else} +
+ {render acl=$kolabDelegateACL} + + {/render} +
+ {render acl=$kolabDelegateACL} + + {/render} + {render acl=$kolabDelegateACL} +   + {/render} + {render acl=$kolabDelegateACL} + + {/render} +{/if} + +

{t}Mail size{/t}

+{render acl=$unrestrictedMailSizeACL checkbox=$multiple_support checked=$use_unrestrictedMailSize} +   + {t}No mail size restriction for this account{/t} +{/render} +
+   + + +

{t}Free Busy information{/t}

+ + + + + + + + + +
+{render acl=$calFBURLACL checkbox=$multiple_support checked=$use_calFBURL} + +{/render} +
+{render acl=$kolabFreeBusyFutureACL checkbox=$multiple_support checked=$use_kolabFreeBusyFuture} + + {t}days{/t} +{/render} +
+ + +

{t}Invitation policy{/t}

+{if $multiple_support} + +{/if} +{render acl=$kolabInvitationPolicyACL} + + {$invitation} +
+{/render} + + +
+ +{/if} diff --git a/gosa-plugins/kolab/personal/mail/class_mail-methods-golab.inc b/gosa-plugins/kolab/personal/mail/class_mail-methods-golab.inc new file mode 100644 index 000000000..dc75674c2 --- /dev/null +++ b/gosa-plugins/kolab/personal/mail/class_mail-methods-golab.inc @@ -0,0 +1,261 @@ + "alias", + "gosaMailQuota" => "cyrus-userquota", + "gosaMailServer" => "kolabHomeServer"); + + function mailMethodGolab(&$config) + { + $this->config= $config->data['SERVERS']['IMAP']; + } + + function updateMailbox($folder) + { + } + + function setQuota($folder, $gosaMailQuota) + { + return (TRUE); + } + + /* Get quota and divide it by 1024, because in gosa we display in MB + but we get Kb */ + function getQuota($folder) + { + $result= array('quotaUsage' => '', 'gosaMailQuota' => ''); + + /* Only use lower case folder names, if folder name is like "@domain.com" */ + if(preg_match("/@/",$folder)){ + $folder = strtolower($folder); + } + + error_reporting(0); + + /* Load quota settings */ + $quota_value = @imap_get_quota($this->mbox, $folder); + if(is_array($quota_value)) { + if (isset($quota_value["STORAGE"]) && is_array($quota_value["STORAGE"])){ + /* use for PHP >= 4.3 */ + $result['quotaUsage']= (int) ($quota_value["STORAGE"]['usage'] / 1024); + $result['gosaMailQuota']= (int) ($quota_value["STORAGE"]['limit'] / 1024); + } else { + /* backward icompatible */ + $result['quotaUsage']= (int) ($quota_value['usage'] / 1024); + $result['gosaMailQuota']= (int) ($quota_value['limit'] / 1024); + } + }elseif(!$quota_value){ + return(false); + } + + error_reporting(E_ALL | E_STRICT); + + return ($result); + } + + + function fixAttributesOnLoad(&$mailObject) + { + /* Kolab shared folder names are like ' shared.uid@server.de ' + So overwrite uid to match these folder names. Else we can't read quota settings etc. + #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ + if(get_class($mailObject) == "mailgroup"){ + $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); + } + + /* Convert attributes and objectClasses */ + foreach ($this->attribute_map as $dest => $source){ + /* Hickert 11.11.05 : Alternate email addresses were saved, but not displayed again. + if (isset($mailObject->attrs[$source])){ + $mailObject->attrs[$dest]= $mailObject->attrs[$source]; + unset ($mailObject->attrs[$source]); + */ + + if (isset($mailObject->attrs[$source])){ + unset($mailObject->attrs[$source]['count']); + $mailObject->attrs[$dest]= $mailObject->attrs[$source]; + $mailObject->$dest= $mailObject->attrs[$source]; + + unset ($mailObject->$dest['count']); + unset ($mailObject->attrs[$source]); + } + } + + /* Adjust server name if needed */ + foreach ($mailObject->config->data['SERVERS']['IMAP'] as $srv => $dummy){ + if (preg_match("%".$mailObject->attrs['gosaMailServer'][0]."$%", $srv)){ + $mailObject->attrs['gosaMailServer']= array(0 => $srv, "count" => 1); + break; + } + } + } + + + function fixAttributesOnStore(&$mailObject) + { + global $config; + + /* If quota is empty, remove quota restrictions by setting quota to 0 */ + if(isset($mailObject->gosaMailQuota) && (empty($mailObject->gosaMailQuota))){ + $mailObject->attrs['gosaMailQuota'] = 0; + } + + /* Convert attributes and objectClasses */ + foreach ($this->attribute_map as $source => $dest){ + if (isset($mailObject->attrs[$source])){ + $mailObject->attrs[$dest]= $mailObject->attrs[$source]; + unset ($mailObject->attrs[$source]); + } + } + $objectclasses= array(); + foreach ($mailObject->attrs['objectClass'] as $oc){ + if ($oc != 'kolabInetOrgPerson' && $oc != 'kolabSharedFolder'){ + $objectclasses[]= $oc; + } + } + $mailObject->attrs['objectClass']= $objectclasses; + if (in_array("posixGroup", $mailObject->attrs['objectClass'])){ + + /* Add kolabSharedFoleder Class */ + $mailObject->attrs['objectClass'][]= 'kolabSharedFolder'; + + /* Work on acl attribute */ + $new_acl= array(); + foreach ($mailObject->attrs['acl'] as $uacl){ + + /* Get user=(mail) & acls */ + list($user, $acl) = split(" ", $uacl); + + /* Add al users which have seperated acls + %members% are all users in this group, + which have the standard group acl + */ + if ($user != "%members%"){ + $new_acl[$user]= $uacl; + } else { + + /* All groupmembers will be added */ + $ldap = $config->get_ldap_link(); + $ldap->cd($config->current['BASE']); + foreach ($mailObject->members as $member){ + + /* Get user mail address .... */ + $ldap->search("(&(objectClass=person)(|(uid=".$member.")(mail=".$member.")))",array("mail")); + $res = $ldap->fetch(); + + /* Default mail address is set to uid - + So if there is no mail address defined the uid is added + */ + $mail = $member; + + /* Use mail address if it is available */ + if(isset($res['mail'][0])){ + $mail = $res['mail'][0]; + } + + /* only append this mail/permission string to acl, + if there arn't already some (special) configs for this user */ + $found =false; + foreach($mailObject->imapacl as $mailA => $acl){ + if(strtolower(trim($mailA))==strtolower(trim($mail))){ + $found = true; + } + } + + /* Skipp user, with no email adress too */ + if($member == $mail){ + $found = true; + } + + /* Append new user acl */ + if(!$found){ + $new_acl[$member]= "$mail $acl"; + } + + /* Old line */ + // $new_acl[$member]= "$member $acl"; + } + } + } + + /* Save shared folder target */ + $mailObject->attrs['gosaSharedFolderTarget']= "kolab+".$mailObject->mail; + + /* Kolab shared folder names are like ' shared.uid@server.de ' + So overwrite uid to match these folder names. Else we can't read quota settings etc. + #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ + $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); + + /* Assign new acls */ + $mailObject->attrs['acl']= array(); + foreach ($new_acl as $key => $value){ + $mailObject->attrs['acl'][]= $value; + } + } else { + $mailObject->attrs['objectClass'][]= 'kolabInetOrgPerson'; + } + + /* Remove imap:// tagging */ + $mailObject->attrs['kolabHomeServer']= preg_replace('%imap://%', '', $mailObject->attrs['kolabHomeServer']); + $mailObject->attrs['gosaMailServer']= $mailObject->attrs['kolabHomeServer']; + $mailObject->attrs['kolabDeleteFlag']= array(); + } + + function fixAttributesOnRemove(&$mailObject) + { + /* Add attribute for object deletion and remove GOsa specific + values from entry. */ + foreach($this->attribute_map as $kolabAttr){ + $mailObject->attrs[$kolabAttr] = array(); + } + + /* Only add kolab delete Flag in case of an user.mailAccount */ + if(!in_array("posixGroup", $mailObject->attrs['objectClass'])){ + $mailObject->attrs['kolabDeleteFlag']= preg_replace('%imap://%', '', $mailObject->gosaMailServer); + }else{ + /* Kolab shared folder names are like ' shared.uid@server.de ' + So overwrite uid to match these folder names. Else we can't read quota settings etc. + #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ + $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); + + } + } + + + function deleteMailbox($folder) + { + /* Remove shared folders and skip removing users. + KolabD is not able to remove shared folders yet, so we do it instead */ + if(!(preg_match("/^user\//",$folder))){ + return mailMethodCyrus::deleteMailbox($folder); + } + return (TRUE); + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/kolab/personal/mail/class_mail-methods-kolab.inc b/gosa-plugins/kolab/personal/mail/class_mail-methods-kolab.inc new file mode 100644 index 000000000..c0606046b --- /dev/null +++ b/gosa-plugins/kolab/personal/mail/class_mail-methods-kolab.inc @@ -0,0 +1,267 @@ + "alias", + "gosaMailQuota" => "cyrus-userquota", + "gosaMailServer" => "kolabHomeServer"); + + function mailMethodKolab(&$config) + { + $this->config= $config->data['SERVERS']['IMAP']; + } + + function updateMailbox($folder) + { + } + + function setQuota($folder, $gosaMailQuota) + { + return (TRUE); + } + + /* Get quota and divide it by 1024, because in gosa we display in MB + but we get Kb */ + function getQuota($folder) + { + $result= array('quotaUsage' => '', 'gosaMailQuota' => ''); + + /* Only use lower case folder names, if folder name is like "@domain.com" */ + if(preg_match("/@/",$folder)){ + $folder = strtolower($folder); + } + + error_reporting(0); + + /* Load quota settings */ + $quota_value = @imap_get_quota($this->mbox, $folder); + if(is_array($quota_value)) { + if (isset($quota_value["STORAGE"]) && is_array($quota_value["STORAGE"])){ + /* use for PHP >= 4.3 */ + $result['quotaUsage']= (int) ($quota_value["STORAGE"]['usage'] / 1024); + $result['gosaMailQuota']= (int) ($quota_value["STORAGE"]['limit'] / 1024); + } else { + /* backward icompatible */ + $result['quotaUsage']= (int) ($quota_value['usage'] / 1024); + $result['gosaMailQuota']= (int) ($quota_value['limit'] / 1024); + } + }elseif(!$quota_value){ + return(false); + } + + error_reporting(E_ALL | E_STRICT); + + return ($result); + } + + + function fixAttributesOnLoad(&$mailObject) + { + /* Kolab shared folder names are like ' shared.uid@server.de ' + So overwrite uid to match these folder names. Else we can't read quota settings etc. + #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ + if(get_class($mailObject) == "mailgroup"){ + $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); + } + + /* Convert attributes and objectClasses */ + foreach ($this->attribute_map as $dest => $source){ + /* Hickert 11.11.05 : Alternate email addresses were saved, but not displayed again. + if (isset($mailObject->attrs[$source])){ + $mailObject->attrs[$dest]= $mailObject->attrs[$source]; + unset ($mailObject->attrs[$source]); + */ + + if (isset($mailObject->attrs[$source])){ + unset($mailObject->attrs[$source]['count']); + $mailObject->attrs[$dest]= $mailObject->attrs[$source]; + $mailObject->$dest= $mailObject->attrs[$source]; + + /* Ensure that cleanup will recognize the ampped attributes too */ + if(isset($mailObject->saved_attributes)){ + $mailObject->saved_attributes[$dest] = $mailObject->attrs[$source]; + $mailObject->saved_attributes[$source] = $mailObject->attrs[$source]; + } + + unset ($mailObject->$dest['count']); + unset ($mailObject->attrs[$source]); + } + } + + /* Adjust server name if needed */ + foreach ($mailObject->config->data['SERVERS']['IMAP'] as $srv => $dummy){ + if (preg_match("%".$mailObject->attrs['gosaMailServer'][0]."$%", $srv)){ + $mailObject->attrs['gosaMailServer']= array(0 => $srv, "count" => 1); + break; + } + } + } + + + function fixAttributesOnStore(&$mailObject) + { + global $config; + + /* If quota is empty, remove quota restrictions by setting quota to 0 */ + if(isset($mailObject->gosaMailQuota) && (empty($mailObject->gosaMailQuota))){ + $mailObject->attrs['gosaMailQuota'] = 0; + } + + /* Convert attributes and objectClasses */ + foreach ($this->attribute_map as $source => $dest){ + if (isset($mailObject->attrs[$source])){ + $mailObject->attrs[$dest]= $mailObject->attrs[$source]; + unset ($mailObject->attrs[$source]); + } + } + $objectclasses= array(); + foreach ($mailObject->attrs['objectClass'] as $oc){ + if ($oc != 'kolabInetOrgPerson' && $oc != 'kolabSharedFolder'){ + $objectclasses[]= $oc; + } + } + $mailObject->attrs['objectClass']= $objectclasses; + if (in_array("posixGroup", $mailObject->attrs['objectClass'])){ + + /* Add kolabSharedFoleder Class */ + $mailObject->attrs['objectClass'][]= 'kolabSharedFolder'; + + /* Work on acl attribute */ + $new_acl= array(); + foreach ($mailObject->attrs['acl'] as $uacl){ + + /* Get user=(mail) & acls */ + list($user, $acl) = split(" ", $uacl); + + /* Add al users which have seperated acls + %members% are all users in this group, + which have the standard group acl + */ + if ($user != "%members%"){ + $new_acl[$user]= $uacl; + } else { + + /* All groupmembers will be added */ + $ldap = $config->get_ldap_link(); + $ldap->cd($config->current['BASE']); + foreach ($mailObject->members as $member){ + + /* Get user mail address .... */ + $ldap->search("(&(objectClass=person)(|(uid=".$member.")(mail=".$member.")))",array("mail")); + $res = $ldap->fetch(); + + /* Default mail address is set to uid - + So if there is no mail address defined the uid is added + */ + $mail = $member; + + /* Use mail address if it is available */ + if(isset($res['mail'][0])){ + $mail = $res['mail'][0]; + } + + /* only append this mail/permission string to acl, + if there arn't already some (special) configs for this user */ + $found =false; + foreach($mailObject->imapacl as $mailA => $acl){ + if(strtolower(trim($mailA))==strtolower(trim($mail))){ + $found = true; + } + } + + /* Skipp user, with no email adress too */ + if($member == $mail){ + $found = true; + } + + /* Append new user acl */ + if(!$found){ + $new_acl[$member]= "$mail $acl"; + } + + /* Old line */ + // $new_acl[$member]= "$member $acl"; + } + } + } + + /* Save shared folder target */ + $mailObject->attrs['gosaSharedFolderTarget']= "kolab+shared.".$mailObject->mail; + + /* Kolab shared folder names are like ' shared.uid@server.de ' + So overwrite uid to match these folder names. Else we can't read quota settings etc. + #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ + $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); + + /* Assign new acls */ + $mailObject->attrs['acl']= array(); + foreach ($new_acl as $key => $value){ + $mailObject->attrs['acl'][]= $value; + } + } else { + $mailObject->attrs['objectClass'][]= 'kolabInetOrgPerson'; + } + + /* Remove imap:// tagging */ + $mailObject->attrs['kolabHomeServer']= preg_replace('%imap://%', '', $mailObject->attrs['kolabHomeServer']); + $mailObject->attrs['gosaMailServer']= $mailObject->attrs['kolabHomeServer']; + $mailObject->attrs['kolabDeleteFlag']= array(); + } + + function fixAttributesOnRemove(&$mailObject) + { + /* Add attribute for object deletion and remove GOsa specific + values from entry. */ + foreach($this->attribute_map as $kolabAttr){ + $mailObject->attrs[$kolabAttr] = array(); + } + + /* Only add kolab delete Flag in case of an user.mailAccount */ + if(!in_array("posixGroup", $mailObject->attrs['objectClass'])){ + $mailObject->attrs['kolabDeleteFlag']= preg_replace('%imap://%', '', $mailObject->gosaMailServer); + }else{ + /* Kolab shared folder names are like ' shared.uid@server.de ' + So overwrite uid to match these folder names. Else we can't read quota settings etc. + #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ + $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); + + } + } + + + function deleteMailbox($folder) + { + /* Remove shared folders and skip removing users. + KolabD is not able to remove shared folders yet, so we do it instead */ + if(preg_match("/^shared/",$folder)){ + return mailMethodCyrus::deleteMailbox($folder); + } + return (TRUE); + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/class_mail-methods-golab.inc b/gosa-plugins/mail/personal/mail/class_mail-methods-golab.inc deleted file mode 100644 index dc75674c2..000000000 --- a/gosa-plugins/mail/personal/mail/class_mail-methods-golab.inc +++ /dev/null @@ -1,261 +0,0 @@ - "alias", - "gosaMailQuota" => "cyrus-userquota", - "gosaMailServer" => "kolabHomeServer"); - - function mailMethodGolab(&$config) - { - $this->config= $config->data['SERVERS']['IMAP']; - } - - function updateMailbox($folder) - { - } - - function setQuota($folder, $gosaMailQuota) - { - return (TRUE); - } - - /* Get quota and divide it by 1024, because in gosa we display in MB - but we get Kb */ - function getQuota($folder) - { - $result= array('quotaUsage' => '', 'gosaMailQuota' => ''); - - /* Only use lower case folder names, if folder name is like "@domain.com" */ - if(preg_match("/@/",$folder)){ - $folder = strtolower($folder); - } - - error_reporting(0); - - /* Load quota settings */ - $quota_value = @imap_get_quota($this->mbox, $folder); - if(is_array($quota_value)) { - if (isset($quota_value["STORAGE"]) && is_array($quota_value["STORAGE"])){ - /* use for PHP >= 4.3 */ - $result['quotaUsage']= (int) ($quota_value["STORAGE"]['usage'] / 1024); - $result['gosaMailQuota']= (int) ($quota_value["STORAGE"]['limit'] / 1024); - } else { - /* backward icompatible */ - $result['quotaUsage']= (int) ($quota_value['usage'] / 1024); - $result['gosaMailQuota']= (int) ($quota_value['limit'] / 1024); - } - }elseif(!$quota_value){ - return(false); - } - - error_reporting(E_ALL | E_STRICT); - - return ($result); - } - - - function fixAttributesOnLoad(&$mailObject) - { - /* Kolab shared folder names are like ' shared.uid@server.de ' - So overwrite uid to match these folder names. Else we can't read quota settings etc. - #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ - if(get_class($mailObject) == "mailgroup"){ - $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); - } - - /* Convert attributes and objectClasses */ - foreach ($this->attribute_map as $dest => $source){ - /* Hickert 11.11.05 : Alternate email addresses were saved, but not displayed again. - if (isset($mailObject->attrs[$source])){ - $mailObject->attrs[$dest]= $mailObject->attrs[$source]; - unset ($mailObject->attrs[$source]); - */ - - if (isset($mailObject->attrs[$source])){ - unset($mailObject->attrs[$source]['count']); - $mailObject->attrs[$dest]= $mailObject->attrs[$source]; - $mailObject->$dest= $mailObject->attrs[$source]; - - unset ($mailObject->$dest['count']); - unset ($mailObject->attrs[$source]); - } - } - - /* Adjust server name if needed */ - foreach ($mailObject->config->data['SERVERS']['IMAP'] as $srv => $dummy){ - if (preg_match("%".$mailObject->attrs['gosaMailServer'][0]."$%", $srv)){ - $mailObject->attrs['gosaMailServer']= array(0 => $srv, "count" => 1); - break; - } - } - } - - - function fixAttributesOnStore(&$mailObject) - { - global $config; - - /* If quota is empty, remove quota restrictions by setting quota to 0 */ - if(isset($mailObject->gosaMailQuota) && (empty($mailObject->gosaMailQuota))){ - $mailObject->attrs['gosaMailQuota'] = 0; - } - - /* Convert attributes and objectClasses */ - foreach ($this->attribute_map as $source => $dest){ - if (isset($mailObject->attrs[$source])){ - $mailObject->attrs[$dest]= $mailObject->attrs[$source]; - unset ($mailObject->attrs[$source]); - } - } - $objectclasses= array(); - foreach ($mailObject->attrs['objectClass'] as $oc){ - if ($oc != 'kolabInetOrgPerson' && $oc != 'kolabSharedFolder'){ - $objectclasses[]= $oc; - } - } - $mailObject->attrs['objectClass']= $objectclasses; - if (in_array("posixGroup", $mailObject->attrs['objectClass'])){ - - /* Add kolabSharedFoleder Class */ - $mailObject->attrs['objectClass'][]= 'kolabSharedFolder'; - - /* Work on acl attribute */ - $new_acl= array(); - foreach ($mailObject->attrs['acl'] as $uacl){ - - /* Get user=(mail) & acls */ - list($user, $acl) = split(" ", $uacl); - - /* Add al users which have seperated acls - %members% are all users in this group, - which have the standard group acl - */ - if ($user != "%members%"){ - $new_acl[$user]= $uacl; - } else { - - /* All groupmembers will be added */ - $ldap = $config->get_ldap_link(); - $ldap->cd($config->current['BASE']); - foreach ($mailObject->members as $member){ - - /* Get user mail address .... */ - $ldap->search("(&(objectClass=person)(|(uid=".$member.")(mail=".$member.")))",array("mail")); - $res = $ldap->fetch(); - - /* Default mail address is set to uid - - So if there is no mail address defined the uid is added - */ - $mail = $member; - - /* Use mail address if it is available */ - if(isset($res['mail'][0])){ - $mail = $res['mail'][0]; - } - - /* only append this mail/permission string to acl, - if there arn't already some (special) configs for this user */ - $found =false; - foreach($mailObject->imapacl as $mailA => $acl){ - if(strtolower(trim($mailA))==strtolower(trim($mail))){ - $found = true; - } - } - - /* Skipp user, with no email adress too */ - if($member == $mail){ - $found = true; - } - - /* Append new user acl */ - if(!$found){ - $new_acl[$member]= "$mail $acl"; - } - - /* Old line */ - // $new_acl[$member]= "$member $acl"; - } - } - } - - /* Save shared folder target */ - $mailObject->attrs['gosaSharedFolderTarget']= "kolab+".$mailObject->mail; - - /* Kolab shared folder names are like ' shared.uid@server.de ' - So overwrite uid to match these folder names. Else we can't read quota settings etc. - #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ - $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); - - /* Assign new acls */ - $mailObject->attrs['acl']= array(); - foreach ($new_acl as $key => $value){ - $mailObject->attrs['acl'][]= $value; - } - } else { - $mailObject->attrs['objectClass'][]= 'kolabInetOrgPerson'; - } - - /* Remove imap:// tagging */ - $mailObject->attrs['kolabHomeServer']= preg_replace('%imap://%', '', $mailObject->attrs['kolabHomeServer']); - $mailObject->attrs['gosaMailServer']= $mailObject->attrs['kolabHomeServer']; - $mailObject->attrs['kolabDeleteFlag']= array(); - } - - function fixAttributesOnRemove(&$mailObject) - { - /* Add attribute for object deletion and remove GOsa specific - values from entry. */ - foreach($this->attribute_map as $kolabAttr){ - $mailObject->attrs[$kolabAttr] = array(); - } - - /* Only add kolab delete Flag in case of an user.mailAccount */ - if(!in_array("posixGroup", $mailObject->attrs['objectClass'])){ - $mailObject->attrs['kolabDeleteFlag']= preg_replace('%imap://%', '', $mailObject->gosaMailServer); - }else{ - /* Kolab shared folder names are like ' shared.uid@server.de ' - So overwrite uid to match these folder names. Else we can't read quota settings etc. - #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ - $mailObject->uid = $mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); - - } - } - - - function deleteMailbox($folder) - { - /* Remove shared folders and skip removing users. - KolabD is not able to remove shared folders yet, so we do it instead */ - if(!(preg_match("/^user\//",$folder))){ - return mailMethodCyrus::deleteMailbox($folder); - } - return (TRUE); - } -} - -// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: -?> diff --git a/gosa-plugins/mail/personal/mail/class_mail-methods-kolab.inc b/gosa-plugins/mail/personal/mail/class_mail-methods-kolab.inc deleted file mode 100644 index c0606046b..000000000 --- a/gosa-plugins/mail/personal/mail/class_mail-methods-kolab.inc +++ /dev/null @@ -1,267 +0,0 @@ - "alias", - "gosaMailQuota" => "cyrus-userquota", - "gosaMailServer" => "kolabHomeServer"); - - function mailMethodKolab(&$config) - { - $this->config= $config->data['SERVERS']['IMAP']; - } - - function updateMailbox($folder) - { - } - - function setQuota($folder, $gosaMailQuota) - { - return (TRUE); - } - - /* Get quota and divide it by 1024, because in gosa we display in MB - but we get Kb */ - function getQuota($folder) - { - $result= array('quotaUsage' => '', 'gosaMailQuota' => ''); - - /* Only use lower case folder names, if folder name is like "@domain.com" */ - if(preg_match("/@/",$folder)){ - $folder = strtolower($folder); - } - - error_reporting(0); - - /* Load quota settings */ - $quota_value = @imap_get_quota($this->mbox, $folder); - if(is_array($quota_value)) { - if (isset($quota_value["STORAGE"]) && is_array($quota_value["STORAGE"])){ - /* use for PHP >= 4.3 */ - $result['quotaUsage']= (int) ($quota_value["STORAGE"]['usage'] / 1024); - $result['gosaMailQuota']= (int) ($quota_value["STORAGE"]['limit'] / 1024); - } else { - /* backward icompatible */ - $result['quotaUsage']= (int) ($quota_value['usage'] / 1024); - $result['gosaMailQuota']= (int) ($quota_value['limit'] / 1024); - } - }elseif(!$quota_value){ - return(false); - } - - error_reporting(E_ALL | E_STRICT); - - return ($result); - } - - - function fixAttributesOnLoad(&$mailObject) - { - /* Kolab shared folder names are like ' shared.uid@server.de ' - So overwrite uid to match these folder names. Else we can't read quota settings etc. - #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ - if(get_class($mailObject) == "mailgroup"){ - $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); - } - - /* Convert attributes and objectClasses */ - foreach ($this->attribute_map as $dest => $source){ - /* Hickert 11.11.05 : Alternate email addresses were saved, but not displayed again. - if (isset($mailObject->attrs[$source])){ - $mailObject->attrs[$dest]= $mailObject->attrs[$source]; - unset ($mailObject->attrs[$source]); - */ - - if (isset($mailObject->attrs[$source])){ - unset($mailObject->attrs[$source]['count']); - $mailObject->attrs[$dest]= $mailObject->attrs[$source]; - $mailObject->$dest= $mailObject->attrs[$source]; - - /* Ensure that cleanup will recognize the ampped attributes too */ - if(isset($mailObject->saved_attributes)){ - $mailObject->saved_attributes[$dest] = $mailObject->attrs[$source]; - $mailObject->saved_attributes[$source] = $mailObject->attrs[$source]; - } - - unset ($mailObject->$dest['count']); - unset ($mailObject->attrs[$source]); - } - } - - /* Adjust server name if needed */ - foreach ($mailObject->config->data['SERVERS']['IMAP'] as $srv => $dummy){ - if (preg_match("%".$mailObject->attrs['gosaMailServer'][0]."$%", $srv)){ - $mailObject->attrs['gosaMailServer']= array(0 => $srv, "count" => 1); - break; - } - } - } - - - function fixAttributesOnStore(&$mailObject) - { - global $config; - - /* If quota is empty, remove quota restrictions by setting quota to 0 */ - if(isset($mailObject->gosaMailQuota) && (empty($mailObject->gosaMailQuota))){ - $mailObject->attrs['gosaMailQuota'] = 0; - } - - /* Convert attributes and objectClasses */ - foreach ($this->attribute_map as $source => $dest){ - if (isset($mailObject->attrs[$source])){ - $mailObject->attrs[$dest]= $mailObject->attrs[$source]; - unset ($mailObject->attrs[$source]); - } - } - $objectclasses= array(); - foreach ($mailObject->attrs['objectClass'] as $oc){ - if ($oc != 'kolabInetOrgPerson' && $oc != 'kolabSharedFolder'){ - $objectclasses[]= $oc; - } - } - $mailObject->attrs['objectClass']= $objectclasses; - if (in_array("posixGroup", $mailObject->attrs['objectClass'])){ - - /* Add kolabSharedFoleder Class */ - $mailObject->attrs['objectClass'][]= 'kolabSharedFolder'; - - /* Work on acl attribute */ - $new_acl= array(); - foreach ($mailObject->attrs['acl'] as $uacl){ - - /* Get user=(mail) & acls */ - list($user, $acl) = split(" ", $uacl); - - /* Add al users which have seperated acls - %members% are all users in this group, - which have the standard group acl - */ - if ($user != "%members%"){ - $new_acl[$user]= $uacl; - } else { - - /* All groupmembers will be added */ - $ldap = $config->get_ldap_link(); - $ldap->cd($config->current['BASE']); - foreach ($mailObject->members as $member){ - - /* Get user mail address .... */ - $ldap->search("(&(objectClass=person)(|(uid=".$member.")(mail=".$member.")))",array("mail")); - $res = $ldap->fetch(); - - /* Default mail address is set to uid - - So if there is no mail address defined the uid is added - */ - $mail = $member; - - /* Use mail address if it is available */ - if(isset($res['mail'][0])){ - $mail = $res['mail'][0]; - } - - /* only append this mail/permission string to acl, - if there arn't already some (special) configs for this user */ - $found =false; - foreach($mailObject->imapacl as $mailA => $acl){ - if(strtolower(trim($mailA))==strtolower(trim($mail))){ - $found = true; - } - } - - /* Skipp user, with no email adress too */ - if($member == $mail){ - $found = true; - } - - /* Append new user acl */ - if(!$found){ - $new_acl[$member]= "$mail $acl"; - } - - /* Old line */ - // $new_acl[$member]= "$member $acl"; - } - } - } - - /* Save shared folder target */ - $mailObject->attrs['gosaSharedFolderTarget']= "kolab+shared.".$mailObject->mail; - - /* Kolab shared folder names are like ' shared.uid@server.de ' - So overwrite uid to match these folder names. Else we can't read quota settings etc. - #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ - $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); - - /* Assign new acls */ - $mailObject->attrs['acl']= array(); - foreach ($new_acl as $key => $value){ - $mailObject->attrs['acl'][]= $value; - } - } else { - $mailObject->attrs['objectClass'][]= 'kolabInetOrgPerson'; - } - - /* Remove imap:// tagging */ - $mailObject->attrs['kolabHomeServer']= preg_replace('%imap://%', '', $mailObject->attrs['kolabHomeServer']); - $mailObject->attrs['gosaMailServer']= $mailObject->attrs['kolabHomeServer']; - $mailObject->attrs['kolabDeleteFlag']= array(); - } - - function fixAttributesOnRemove(&$mailObject) - { - /* Add attribute for object deletion and remove GOsa specific - values from entry. */ - foreach($this->attribute_map as $kolabAttr){ - $mailObject->attrs[$kolabAttr] = array(); - } - - /* Only add kolab delete Flag in case of an user.mailAccount */ - if(!in_array("posixGroup", $mailObject->attrs['objectClass'])){ - $mailObject->attrs['kolabDeleteFlag']= preg_replace('%imap://%', '', $mailObject->gosaMailServer); - }else{ - /* Kolab shared folder names are like ' shared.uid@server.de ' - So overwrite uid to match these folder names. Else we can't read quota settings etc. - #FIXME is there a better way to detect if it is 'shared.' or 'shared+' or 'kolab+shared.' or what ever ?*/ - $mailObject->uid = "shared.".$mailObject->uid."@".preg_replace("/^.*@/","",$mailObject->mail); - - } - } - - - function deleteMailbox($folder) - { - /* Remove shared folders and skip removing users. - KolabD is not able to remove shared folders yet, so we do it instead */ - if(preg_match("/^shared/",$folder)){ - return mailMethodCyrus::deleteMailbox($folder); - } - return (TRUE); - } -} - -// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: -?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_My_Parser.inc b/gosa-plugins/mail/personal/mail/sieve/class_My_Parser.inc new file mode 100644 index 000000000..ac99301a6 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_My_Parser.inc @@ -0,0 +1,78 @@ +registeredExtensions_ = array(); + $this->parent = $parent; + } + + function execute() + { + $ret = $this->dumpParseTree(); + return($ret); + } + + + /* Check if there are errors, collect them and return them */ + function check() + { + return($this->tree_->check()); + } + + + /* Initiate parser, but use some other + * classes, that are rewritten. + */ + function parse($script) + { + $script = preg_replace("/^###GOSA/","",$script); + + $this->registeredExtensions_ = array(); + $this->status_text = "incomplete"; + $this->script_ = $script; + $this->tree_ = new My_Tree(@Scanner::scriptStart(),$this); + $this->tree_->setDumpFunc(array(&$this, 'dumpToken_')); + $this->scanner_ = new My_Scanner($this->script_); + $this->scanner_->setCommentFunc(array($this, 'comment_')); + + if ($this->commands_($this->tree_->getRoot()) && + $this->scanner_->nextTokenIs('script-end')) + { + $this->scanner_->nextToken(); + return $this->success_('success'); + } + + return $this->status_; + } + + + function get_sieve_script() + { + return("###GOSA\n".$this->tree_->get_sieve_script()); + } + + + function save_object() + { + $this->tree_->save_object(); + } + + + function dumpParseTree() + { + return $this->tree_->execute(); + } +} +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_My_Scanner.inc b/gosa-plugins/mail/personal/mail/sieve/class_My_Scanner.inc new file mode 100644 index 000000000..878927a5f --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_My_Scanner.inc @@ -0,0 +1,69 @@ +token_match_ as $class => $regex) + { + if (preg_match('/^'. $regex .'/', mb_substr($script, $pos), $match)) + { + $length = mb_strlen($match[0]); + + if ($class != 'whitespace') + { + array_push($this->tokens_, array( + 'class' => $class, + 'text' => chop(mb_substr($script, $pos, $length)), + 'line' => $line, + )); + } + if ($class == 'unknown') + { + return; + } + + $pos += $length; + $line += mb_substr_count($match[0], "\n"); + break; + } + } + } + array_push($this->tokens_, array( + 'class' => 'script-end', + 'text' => 'script-end', + 'line' => $line, + )); + } + + var $commentFn_ = null; + var $tokenPos_ = 0; + var $tokens_ = array(); + var $token_match_ = array ( + 'left-bracket' => '\[', + 'right-bracket' => '\]', + 'block-start' => '\{', + 'block-end' => '\}', + 'left-parant' => '\(', + 'right-parant' => '\)', + 'comma' => ',', + 'semicolon' => ';', + 'whitespace' => '[ \r\n\t]+', + 'tag' => ':[[:alpha:]_][[:alnum:]_]*(?=\b)', + 'quoted-string' => '"(?:\\[\\"]|[^\x00"])*"', + 'number' => '[[:digit:]]+(?:[KMG])?(?=\b)', + 'comment' => '(?:\/\*(?:[^\*]|\*(?=[^\/]))*\*\/|#[^\r\n]*\r?\n)', +# 'multi-line' => 'text:[ \t]*(?:#[^\r\n]*)?\r?\n(\.[^\r\n]+\r?\n|[^\.]*\r?\n)*\.\r?\n', + 'multi-line' => 'text:[^;]*', + 'identifier' => '[[:alpha:]_][[:alnum:]_]*(?=\b)', + 'unknown token' => '[^ \r\n\t]+' + ); +} + +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_My_Tree.inc b/gosa-plugins/mail/personal/mail/sieve/class_My_Tree.inc new file mode 100644 index 000000000..b1b061e39 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_My_Tree.inc @@ -0,0 +1,782 @@ +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_ .= "
"; + $this->dump_ .= "
"; + } + 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_ .= "
"; + $this->dump_ .= "
"; + } + } + } + + 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; $idoDump_($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 "Missing : ".$class_name.""."
"; + } + } + + function save_object() + { + reset($this->pap); + foreach($this->pap as $key => $obj){ + + if(in_array(get_class($obj),array("sieve_if", + "sieve_elsif", + "sieve_vacation", + "sieve_comment", + "sieve_reject", + "sieve_fileinto", + "sieve_require", + "sieve_redirect"))){ + + + if(isset($this->pap[$key]) && method_exists($this->pap[$key],"save_object")){ + $this->pap[$key]->save_object(); + } + } + } + } + + + /* Remove the object at the given position */ + function remove_object($key_id) + { + if(count($this->pap) == 1){ + msg_dialog::display(_("Warning"), _("Cannot remove last element!"), ERROR_DIALOG); + return; + } + + if(!isset($this->pap[$key_id])){ + trigger_error("Can't remove element with object_id=".$key_id.", there is no object with this identifier. Remove aborted."); + return(false); + } + + $class = get_class($this->pap[$key_id]); + if(in_array($class,array("sieve_if","sieve_elsif","sieve_else"))){ + $block_start= $key_id; + $block_end = $this->get_block_end($key_id); + + for($i = $block_start ; $i <= $block_end ; $i ++ ){ + unset($this->pap[$i]); + } + }else{ + unset($this->pap[$key_id]); + } + $tmp = array(); + foreach($this->pap as $element){ + $tmp[] = $element; + } + $this->pap = $tmp; + } + + + /* This function moves a given element to another position. + * Single elements like "keep;" will simply be moved one posisition down/up. + * Multiple elements like if-elsif-else will be moved as block. + * + * $key_id specified the element that should be moved. + * $direction specifies to move elements "up" or "down" + */ + function move_up_down($key_id,$direction = "down") + { + + /* Get the current element to decide what to move. */ + $e_class = get_class($this->pap[$key_id]); + + if(in_array($e_class,array("sieve_if"))){ + $block_start= $key_id; + $block_end = $this->get_block_end($key_id); + + /* Depending on the direction move up down */ + if($direction == "down"){ + $next_free = $this->_get_next_free_move_slot($block_end,$direction); + }else{ + $next_free = $this->_get_next_free_move_slot($block_start,$direction); + } + + /* Move the given block */ + $this->move_multiple_elements($block_start,$block_end,$next_free); + } + + if(in_array($e_class,array( "sieve_stop", + "sieve_keep", + "sieve_require", + "sieve_comment", + "sieve_vacation", + "sieve_stop", + "sieve_reject", + "sieve_fileinto", + "sieve_redirect", + "sieve_discard"))){ + $this->move_single_element($key_id,$this->_get_next_free_move_slot($key_id,$direction)); + } + } + + + /* Move the given block to position */ + function move_multiple_elements($start,$end,$to) + { + /* Use class names for testing */ + $data = $this->pap; + + /* Get block to move */ + $block_to_move = array_slice($data,$start, ($end - $start +1)); + + /* We want do move this block up */ + if($end > $to){ + + /* Get start block */ + $start_block = array_slice($data,0,$to); + + /* Get Get all elements between the block to move + * and next free position + */ + $block_to_free = array_slice($data,$to ,$start - $to ); + $block_to_end = array_slice($data,$end+1); + $new = array(); + foreach($start_block as $block){ + $new[] = $block; + } + foreach($block_to_move as $block){ + $new[] = $block; + } + foreach($block_to_free as $block){ + $new[] = $block; + } + foreach($block_to_end as $block){ + $new[] = $block; + } + $old = $this->pap; + $this->pap = $new; + } + + + /* We want to move this block down. */ + if($to > $end){ + + /* Get start block */ + $start_block = array_slice($data,0,$start); + + /* Get Get all elements between the block to move + * and next free position + */ + $block_to_free = array_slice($data,$end +1,($to - $end )); + + /* Get the rest + */ + $block_to_end = array_slice($data,$to+1); + + $new = array(); + foreach($start_block as $block){ + $new[] = $block; + } + foreach($block_to_free as $block){ + $new[] = $block; + } + foreach($block_to_move as $block){ + $new[] = $block; + } + foreach($block_to_end as $block){ + $new[] = $block; + } + $old = $this->pap; + $this->pap = $new; + } + } + + + /* This function returns the id of the element + * where the current block ends + */ + function get_block_end($start,$complete = TRUE) + { + /* Only execute if this is a really a block element. + * Block elements is only sieve_if + */ + if(in_array(get_class($this->pap[$start]),array("sieve_if","sieve_elsif","sieve_else"))){ + + $class = get_class($this->pap[$start]); + $next_class = get_class($this->pap[$start+1]); + $block_depth = 0; + + $end = FALSE; + + while(!$end && $start < count($this->pap)){ + + if($class == "sieve_block_start"){ + $block_depth ++; + } + + if($class == "sieve_block_end"){ + $block_depth --; + } + + if($complete){ + if( $block_depth == 0 && + $class == "sieve_block_end" && + !in_array($next_class,array("sieve_else","sieve_elsif"))){ + $end = TRUE; + $start --; + } + }else{ + + if( $block_depth == 0 && + $class == "sieve_block_end" ){ + $end = TRUE; + $start --; + } + } + + $start ++; + $class = get_class($this->pap[$start]); + + if(isset($this->pap[$start+1])){ + $next_class = get_class($this->pap[$start+1]); + }else{ + $next_class =""; + } + } + } + return($start); + } + + + /* This function moves the single element at + * position $from to position $to. + */ + function move_single_element($from,$to) + { + if($from == $to) { + return; + } + + $ret = array(); + $tmp = $this->pap; + + $begin = array(); + $middle = array(); + $end = array(); + $element = $this->pap[$from]; + + if($from > $to ){ + + /* Get all element in fron to element to move */ + if($from != 0){ + $begin = array_slice($tmp,0,$to); + } + + /* Get all elements between */ + $middle = array_slice($tmp,$to , ($from - ($to) )); + + /* Get the rest */ + $end = array_slice($tmp,$from+1); + + foreach($begin as $data){ + $ret[] = $data; + } + $ret[] = $element; + foreach($middle as $data){ + $ret[] = $data; + } + foreach($end as $data){ + $ret[] = $data; + } + $this->pap = $ret; + } + if($from < $to ){ + + /* Get all element in fron to element to move */ + if($from != 0){ + $begin = array_slice($tmp,0,$from); + } + + /* Get all elements between */ + $middle = array_slice($tmp,$from+1 , ($to - ($from))); + + /* Get the rest */ + $end = array_slice($tmp,$to+1); + + foreach($begin as $data){ + $ret[] = $data; + } + foreach($middle as $data){ + $ret[] = $data; + } + $ret[] = $element; + foreach($end as $data){ + $ret[] = $data; + } + $this->pap = $ret; + } + } + + + /* Returns the next free position where we + * can add a new sinle element + * $key_id = Current position + * $direction = Forward or backward. + */ + function _get_next_free_move_slot($key_id,$direction,$include_self = FALSE) + { + $last_class = ""; + $current_class =""; + $next_class = ""; + + /* After this elements we can add new elements + * without having any trouble. + */ + $allowed_to_add_after = array("sieve_keep", + "sieve_require", + "sieve_stop", + "sieve_reject", + "sieve_fileinto", + "sieve_redirect", + "sieve_discard", + "sieve_comment", + "sieve_block_start" + ); + + /* Before this elements we can add new elements + * without having any trouble. + */ + $allowed_to_add_before = array("sieve_keep", + "sieve_require", + "sieve_stop", + "sieve_reject", + "sieve_fileinto", + "sieve_comment", + "sieve_redirect", + "sieve_discard", + "sieve_if", + "sieve_block_end" + ); + + if($direction == "down"){ + + $test = $this->pap; + while($key_id < count($test)){ + if(($key_id+1) == count($test)) { + return($key_id); + } + + if(!$include_self){ + $key_id ++; + } + $include_self = FALSE; + $current_class = get_class($test[$key_id]); + if(in_array($current_class, $allowed_to_add_after)){ + return($key_id); + } + } + }else{ + + $test = $this->pap; + if($key_id == 0) { + return($key_id); + } + if(!$include_self){ + $key_id --; + } + while($key_id >=0 ){ + $current_class = get_class($test[$key_id]); + if(in_array($current_class, $allowed_to_add_before)){ + return($key_id); + } + $key_id --; + } + return(0); + } + } + + + /* Need to be reviewed */ + function get_sieve_script() + { + $tmp =""; + if(count($this->pap)){ + $buffer = ""; + foreach($this->pap as $part) { + if(get_class($part) == "sieve_block_end"){ + $buffer = substr($buffer,0,strlen($buffer)-(strlen(SIEVE_INDENT_TAB))); + } + $tmp2 = $part->get_sieve_script_part(); + + $tmp3 = split("\n",$tmp2); + foreach($tmp3 as $str){ + $str2 = trim($str); + + /* If the current line only contains an '.' + * we must skip the line indent. + * The text: statement uses a single '.' to mark the text end. + * This '.' must be the only char in the current line, no + * whitespaces are allowed here. + */ + if($str2 == "."){ + $tmp.=$str."\n"; + }else{ + $tmp.= $buffer.$str."\n"; + } + } + if(get_class($part) == "sieve_block_start"){ + $buffer .= SIEVE_INDENT_TAB; + } + } + } + if(!preg_match("/Generated by GOsa - Gonicus System Administrator/",$tmp)){ +# $tmp = "#Generated by GOsa - Gonicus System Administrator \n ".$tmp; + } + return($tmp); + } + + function check() + { + $msgs = array(); + + /* Some logical checks. + * like : only sieve_comment can appear before require. + */ + + /* Ensure that there are no command before require + * - Get id of last require tag + * - Collect object types in from of this tag. + * - Check if there are tags collected that are not allowed + */ + $last_found_at = -1; + $objs = array(); + foreach($this->pap as $key => $obj){ + if(get_class($obj) == "sieve_require"){ + $last_found_at = $key; + } + } + foreach($this->pap as $key => $obj){ + if($key == $last_found_at) break; + if(!in_array(get_class($obj),array("sieve_comment","sieve_require"))){ + $objs[] = get_class($obj); + } + } + if(count($objs) && $last_found_at != -1){ + $str = _("Require must be the first command in the script."); + $msgs[] = $str; + msg_dialog::display(_("Error"), $str, ERROR_DIALOG); + } + + foreach($this->pap as $obj){ + $o_msgs = $obj->check(); + foreach($o_msgs as $o_msg){ + $msgs[] = $o_msg; + } + } + return($msgs); + } + + + /* We are forced to add a new require. + * This function is called by the + * sieveElement_Classes->parent->add_require() + */ + function add_require($str) + { + $require_id = -1; + foreach($this->pap as $key => $obj){ + if(get_class($obj) == "sieve_require"){ + $require_id = $key; + } + } + + /* No require found, add one */ + if($require_id == -1){ + $require = new sieve_require(NULL,preg_replace("/[^0-9]/","",microtime()),$this); + $require -> Add_Require($str); + $new = array(); + $new[] = $require; + foreach($this->pap as $obj){ + $new[] = $obj; + } + $this->pap = $new; + } else { + $this->pap[$require_id]->Add_Require($str); + } + } +} + + +/* Create valid sieve string/string-list + * out of a given array + */ +function sieve_create_strings($data,$force_string = FALSE) +{ + $ret = ""; + if(is_array($data)){ + if(count($data) == 1){ + $ret = "\""; + foreach($data as $dat){ + $ret .=$dat; + } + $ret.="\""; + }else{ + foreach($data as $dat){ + $ret.= "\""; + $ret.=$dat; + $ret.="\", "; + } + $ret = preg_replace("/,$/","",trim($ret)); + $ret = "[".$ret."]"; + } +# $ret = preg_replace("/\"\"/","\"",$ret); + }else{ + + $Multiline = preg_match("/\n/",$data); + $data = preg_replace("/\r/","",$data);; + + if($Multiline && !$force_string){ + $ret = "text: \r\n".$data."\r\n.\r\n"; + }else{ + $ret = "\"".$data."\""; + $ret = preg_replace("/\"\"/","\"",$ret); + } + } + $ret = preg_replace("/\n/","\r\n",$ret); + + return($ret); +} + +/* This checks if there is a string at the current position + * in the token array. + * If there is a string list at the current position, + * this function will return a complete list of all + * strings used in this list. + * It also returns an offset of the last token position + */ +function sieve_get_strings($data,$id) +{ + $ret = array(); + if($data[$id]['class'] == "left-bracket"){ + while(isset($data[$id]) && $data[$id]['class'] != "right-bracket" && $id < count($data)){ + + if($data[$id]['class'] == "quoted-string"){ + $text = $data[$id]['text']; + $text= preg_replace("/^\"/","",$text); + $text= preg_replace("/\"$/","",$text); + $ret[] = $text; + } + + $id ++; + } + }elseif($data[$id]['class'] == "quoted-string"){ + $text = $data[$id]['text']; + $text= preg_replace("/^\"/","",$text); + $text= preg_replace("/\"$/","",$text); + $ret[] = $text; + }elseif($data[$id]['class'] == "number"){ + $ret[] = $data[$id]['text']; + }elseif($data[$id]['class'] == "multi-line"){ + $str = trim(preg_replace("/^text:/","",$data[$id]['text'])); + $str = trim(preg_replace("/\.$/","",$str)); + $ret[] = $str; + } + + return(array("OFFSET" => $id, "STRINGS" => $ret)); +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_parser.inc b/gosa-plugins/mail/personal/mail/sieve/class_parser.inc new file mode 100644 index 000000000..345895231 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_parser.inc @@ -0,0 +1,365 @@ +registeredExtensions_ = array(); + $this->status_text = "incomplete"; + + $this->script_ = $script; + $this->tree_ = new Tree(Scanner::scriptStart()); + $this->tree_->setDumpFunc(array(&$this, 'dumpToken_')); + $this->scanner_ = new Scanner($this->script_); + $this->scanner_->setCommentFunc(array($this, 'comment_')); + + if ($this->commands_($this->tree_->getRoot()) && + $this->scanner_->nextTokenIs('script-end')) + { + return $this->success_('success'); + } + + return $this->status_; + } + + function dumpParseTree() + { + return $this->tree_->dump(); + } + + function dumpToken_(&$token) + { + if (is_array($token)) + { + $str = "<" . $token['text'] . "> "; + foreach ($token as $k => $v) + { + $str .= " $k:$v"; + } + return $str; + } + + return strval($token); + } + + function getPrevTokenText_($parent_id) + { + $childs = $this->tree_->getChilds($parent_id); + + for ($i=count($childs); $i>0; --$i) + { + $prev = $this->tree_->getNode($childs[$i-1]); + + if (in_array($prev['text'], array('{', '(', ','))) + { + // use command owning a block or list + $prev = $this->tree_->getNode($parent_id); + } + + if ($prev['class'] != 'comment') + { + return $prev['text']; + } + } + + $prev = $this->tree_->getNode($parent_id); + return $prev['text']; + } + + function getSemantics_($token_text) + { + $semantics = new Semantics($token_text); + $semantics->setExtensionFuncs(array(&$this, 'registerExtension_'), array(&$this, 'isExtensionRegistered_')); + return $semantics; + } + + function registerExtension_($extension) + { + array_push($this->registeredExtensions_, str_replace('"', '', $extension)); + } + + function isExtensionRegistered_($extension) + { + return (in_array($extension, $this->registeredExtensions_) ? true : false); + } + + function success_($text = null) + { + if ($text != null) + { + $this->status_text = $text; + } + + return $this->status_ = true; + } + + function error_($text, $token = null) + { + if ($token != null) + { + $text = 'line '. $token['line'] .': '. $token['class'] . " where $text expected near ". $token['text']; + } + + $this->status_text = $text; + return $this->status_ = false; + } + + function done_() + { + $this->status_ = true; + return false; + } + + /******************************************************************************* + * methods for recursive descent start below + */ + + function comment_($token) + { + $this->tree_->addChild($token); + } + + function commands_($parent_id) + { + while ($this->command_($parent_id)) + ; + + return $this->status_; + } + + function command_($parent_id) + { + if (!$this->scanner_->nextTokenIs('identifier')) + { + if ($this->scanner_->nextTokenIs(array('block-end', 'script-end'))) + { + return $this->done_(); + } + return $this->error_('identifier', $this->scanner_->peekNextToken()); + } + + // Get and check a command token + $token = $this->scanner_->nextToken(); + $semantics = $this->getSemantics_($token['text']); + if (!$semantics->validCommand($this->getPrevTokenText_($parent_id), $token['line'])) + { + return $this->error_($semantics->message); + } + + // Process eventual arguments + $this_node = $this->tree_->addChildTo($parent_id, $token); + if ($this->arguments_($this_node, $semantics) == false) + { + return false; + } + + $token = $this->scanner_->nextToken(); + if ($token['class'] != 'semicolon') + { + if (!$semantics->validToken($token['class'], $token['text'], $token['line'])) + { + return $this->error_($semantics->message); + } + + if ($token['class'] == 'block-start') + { + $this->tree_->addChildTo($this_node, $token); + $ret = $this->block_($this_node, $semantics); + return $ret; + } + + return $this->error_('semicolon', $token); + } + + $this->tree_->addChildTo($this_node, $token); + return $this->success_(); + } + + function arguments_($parent_id, &$semantics) + { + while ($this->argument_($parent_id, &$semantics)) + ; + + if ($this->status_ == true) + { + $this->testlist_($parent_id, $semantics); + } + + return $this->status_; + } + + function argument_($parent_id, &$semantics) + { + if ($this->scanner_->nextTokenIs(array('number', 'tag'))) + { + // Check if semantics allow a number or tag + $token = $this->scanner_->nextToken(); + if (!$semantics->validToken($token['class'], $token['text'], $token['line'])) + { + return $this->error_($semantics->message); + } + + $this->tree_->addChildTo($parent_id, $token); + return $this->success_(); + } + + return $this->stringlist_($parent_id, &$semantics); + } + + function stringlist_($parent_id, &$semantics) + { + if (!$this->scanner_->nextTokenIs('left-bracket')) + { + return $this->string_($parent_id, &$semantics); + } + + $token = $this->scanner_->nextToken(); + if (!$semantics->startStringList($token['line'])) + { + return $this->error_($semantics->message); + } + $this->tree_->addChildTo($parent_id, $token); + + while ($token['class'] != 'right-bracket') + { + if (!$this->string_($parent_id, &$semantics)) + { + return $this->status_; + } + + $token = $this->scanner_->nextToken(); + + if ($token['class'] != 'comma' && $token['class'] != 'right-bracket') + { + return $this->error_('comma or closing bracket', $token); + } + + $this->tree_->addChildTo($parent_id, $token); + } + + $semantics->endStringList(); + return $this->success_(); + } + + function string_($parent_id, &$semantics) + { + if (!$this->scanner_->nextTokenIs(array('quoted-string', 'multi-line'))) + { + return $this->done_(); + } + + $token = $this->scanner_->nextToken(); + if (!$semantics->validToken('string', $token['text'], $token['line'])) + { + return $this->error_($semantics->message); + } + + $this->tree_->addChildTo($parent_id, $token); + return $this->success_(); + } + + function testlist_($parent_id, &$semantics) + { + if (!$this->scanner_->nextTokenIs('left-parant')) + { + return $this->test_($parent_id, $semantics); + } + + $token = $this->scanner_->nextToken(); + if (!$semantics->validToken($token['class'], $token['text'], $token['line'])) + { + return $this->error_($semantics->message); + } + $this->tree_->addChildTo($parent_id, $token); + + while ($token['class'] != 'right-parant') + { + if (!$this->test_($parent_id, $semantics)) + { + return $this->status_; + } + + $token = $this->scanner_->nextToken(); + + if ($token['class'] != 'comma' && $token['class'] != 'right-parant') + { + return $this->error_('comma or closing paranthesis', $token); + } + + $this->tree_->addChildTo($parent_id, $token); + } + + return $this->success_(); + } + + function test_($parent_id, &$semantics) + { + if (!$this->scanner_->nextTokenIs('identifier')) + { + // There is no test + return $this->done_(); + } + + // Check if semantics allow an identifier + $token = $this->scanner_->nextToken(); + if (!$semantics->validToken($token['class'], $token['text'], $token['line'])) + { + return $this->error_($semantics->message); + } + + // Get semantics for this test command + $this_semantics = $this->getSemantics_($token['text']); + if (!$this_semantics->validCommand($this->getPrevTokenText_($parent_id), $token['line'])) + { + return $this->error_($this_semantics->message); + } + + $this_node = $this->tree_->addChildTo($parent_id, $token); + + // Consume eventual argument tokens + if (!$this->arguments_($this_node, $this_semantics)) + { + return false; + } + + // Check if arguments were all there + $token = $this->scanner_->peekNextToken(); + if (!$this_semantics->done($token['class'], $token['text'], $token['line'])) + { + return $this->error_($this_semantics->message); + } + + return true; + } + + function block_($parent_id, &$semantics) + { + if ($this->commands_($parent_id, $semantics)) + { + $token = $this->scanner_->nextToken(); + + if ($token['class'] != 'block-end') + { + return $this->error_('closing curly brace', $token); + } + + $this->tree_->addChildTo($parent_id, $token); + return $this->success_(); + } + return $this->status_; + } +} + +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_scanner.inc b/gosa-plugins/mail/personal/mail/sieve/class_scanner.inc new file mode 100644 index 000000000..3e22bb1d0 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_scanner.inc @@ -0,0 +1,140 @@ +_construct($script); + } + + function _construct(&$script) + { + if ($script === null) + { + return; + } + + $this->tokenize($script); + } + + function setCommentFunc($callback) + { + if ($callback == null || is_callable($callback)) + { + $this->commentFn_ = $callback; + } + } + + function tokenize(&$script) + { + $pos = 0; + $line = 1; + $script_length = mb_strlen($script); + + while ($pos < $script_length) + { + foreach ($this->token_match_ as $class => $regex) + { + if (preg_match('/^'. $regex .'/', mb_substr($script, $pos), $match)) + { + $length = mb_strlen($match[0]); + + if ($class != 'whitespace') + { + array_push($this->tokens_, array( + 'class' => $class, + 'text' => chop(mb_substr($script, $pos, $length)), + 'line' => $line, + )); + } + if ($class == 'unknown') + { + return; + } + + $pos += $length; + $line += mb_substr_count($match[0], "\n"); + break; + } + } + } + + array_push($this->tokens_, array( + 'class' => 'script-end', + 'text' => 'script-end', + 'line' => $line, + )); + } + + function nextTokenIs($class) + { + $offset = 0; + do + { + $next = $this->tokens_[$this->tokenPos_ + $offset++]['class']; + } + while ($next == 'comment'); + + if (is_array($class)) + { + return in_array($next, $class); + } + else if (is_string($class)) + { + return (strcmp($next, $class) == 0); + } + return false; + } + + function peekNextToken() + { + return $this->tokens_[$this->tokenPos_]; + } + + function nextToken() + { + $token = $this->tokens_[$this->tokenPos_++]; + while ($token['class'] == 'comment') + { + if ($this->commentFn_ != null) + { + call_user_func($this->commentFn_, $token); + } + $token = $this->tokens_[$this->tokenPos_++]; + } + return $token; + } + + function scriptStart() + { + return array( + 'class' => 'script-start', + 'text' => 'script-start', + 'line' => 1, + ); + } + + var $commentFn_ = null; + var $tokenPos_ = 0; + var $tokens_ = array(); + var $token_match_ = array ( + 'left-bracket' => '\[', + 'right-bracket' => '\]', + 'block-start' => '\{', + 'block-end' => '\}', + 'left-parant' => '\(', + 'right-parant' => '\)', + 'comma' => ',', + 'semicolon' => ';', + 'whitespace' => '[ \r\n\t]+', + 'tag' => ':[[:alpha:]_][[:alnum:]_]*(?=\b)', + 'quoted-string' => '"(?:\\[\\"]|[^\x00"])*"', + 'number' => '[[:digit:]]+(?:[KMG])?(?=\b)', + 'comment' => '(?:\/\*(?:[^\*]|\*(?=[^\/]))*\*\/|#[^\r\n]*\r?\n)', + 'multi-line' => 'text:[ \t]*(?:#[^\r\n]*)?\r?\n(\.[^\r\n]+\r?\n|[^\.]*\r?\n)*\.\r?\n', + 'identifier' => '[[:alpha:]_][[:alnum:]_]*(?=\b)', + 'unknown token' => '[^ \r\n\t]+' + ); +} + +?> \ No newline at end of file diff --git a/gosa-plugins/mail/personal/mail/sieve/class_semantics.inc b/gosa-plugins/mail/personal/mail/sieve/class_semantics.inc new file mode 100644 index 000000000..1c00051c0 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_semantics.inc @@ -0,0 +1,613 @@ +command_ = $command; + $this->unknown = false; + switch ($command) + { + + /******************** + * control commands + */ + case 'require': + /* require */ + $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 */ + $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 */ + $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 */ + $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"] */ + $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"] */ + $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 */ + $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 */ + /* addflag */ + /* removeflag */ + $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"] */ + $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] */ + $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 + anyof */ + $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] */ + $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 */ + $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] */ + $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 */ + $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"> */ + $this->s_ = array( + 'valid_after' => $this->testsValidAfter_, + 'arguments' => array( + array('class' => 'tag', 'occurrences' => '1', 'values' => array( + array('occurrences' => '1', 'regex' => ':(over|under)', 'name' => 'size-type') + )), + array('class' => 'number', 'occurrences' => '1', 'values' => array( + array('occurrences' => '1', 'regex' => '.*', 'name' => 'limit') + )) + ) + ); + break; + + case 'true': + case 'false': + /* true / false */ + $this->s_ = array( + 'valid_after' => $this->testsValidAfter_ + ); + break; + + + /******************** + * unknown commands + */ + default: + $this->unknown = true; + } + } + + function setExtensionFuncs($setFn, $checkFn) + { + if (is_callable($setFn) && is_callable($checkFn)) + { + $this->registerExtensionFn_ = $setFn; + $this->isExtensionRegisteredFn_ = $checkFn; + } + } + + function setRequire_($extension) + { + call_user_func($this->registerExtensionFn_, $extension); + return true; + } + + function wasRequired_($extension) + { + return call_user_func($this->isExtensionRegisteredFn_, $extension); + } + + function setMatchType_($text) + { + // Do special processing for relational test extension + if ($text == ':count' || $text == ':value') + { + if (!$this->wasRequired_('relational')) + { + $this->message = 'missing require for match-type '. $text; + return false; + } + + array_unshift($this->s_['arguments'], + array('class' => 'string', 'occurrences' => '1', 'values' => array( + array('occurrences' => '1', 'regex' => '"(lt|le|eq|ge|gt|ne)"', 'name' => 'relation-string'), + )) + ); + } + // Do special processing for regex match-type extension + else if ($text == ':regex' && !$this->wasRequired_('regex')) + { + $this->message = 'missing require for match-type '. $text; + return false; + } + $this->matchType_ = $text; + return true; + } + + function setComparator_($text) + { + $this->comparator_ = $text; + return true; + } + + function checkAddrPart_($text) + { + if ($text == ':user' || $text == ':detail') + { + if (!$this->wasRequired_('subaddress')) + { + $this->message = 'missing require for tag '. $text; + return false; + } + } + return true; + } + + function checkTags_() + { + if (isset($this->matchType_) && + $this->matchType_ == ':count' && + $this->comparator_ != '"i;ascii-numeric"') + { + $this->message = 'match-type :count needs comparator i;ascii-numeric'; + return false; + } + return true; + } + + function validCommand($prev, $line) + { + // Check if command is known + if ($this->unknown) + { + $this->message = 'line '. $line .': unknown command "'. $this->command_ .'"'; + return false; + } + + // Check if the command needs to be required + if (isset($this->s_['requires']) && !$this->wasRequired_($this->s_['requires'])) + { + $this->message = 'line '. $line .': missing require for command "'. $this->command_ .'"'; + return false; + } + + // Check if command may appear here + if (!ereg($this->s_['valid_after'], $prev)) + { +# $this->message = 'line '. $line .': "'. $this->command_ .'" may not appear after "'. $prev .'"'; +# return false; + } + + return true; + } + + function validClass_($class, $id) + { + // Check if command expects any arguments + if (!isset($this->s_['arguments'])) + { + $this->message = $id .' where semicolon expected'; + return false; + } + + foreach ($this->s_['arguments'] as $arg) + { + if ($class == $arg['class']) + { + return true; + } + + // Is the argument required + if ($arg['occurrences'] != '?' && $arg['occurrences'] != '*') + { + $this->message = $id .' where '. $arg['class'] .' expected'; + return false; + } + + if (isset($arg['post-call']) && + !call_user_func(array(&$this, $arg['post-call']))) + { + return false; + } + array_shift($this->s_['arguments']); + } + + $this->message = 'unexpected '. $id; + return false; + } + + function startStringList($line) + { + if (!$this->validClass_('string', 'string')) + { + $this->message = 'line '. $line .': '. $this->message; + return false; + } + else if (!isset($this->s_['arguments'][0]['list'])) + { + $this->message = 'line '. $line .': '. 'left bracket where '. $this->s_['arguments'][0]['class'] .' expected'; + return false; + } + + $this->s_['arguments'][0]['occurrences'] = '+'; + return true; + } + + function endStringList() + { + array_shift($this->s_['arguments']); + } + + function validToken($class, &$text, &$line) + { + $name = $class . ($class != $text ? " $text" : ''); + + // Make sure the argument has a valid class + if (!$this->validClass_($class, $name)) + { + $this->message = 'line '. $line .': '. $this->message; + return false; + } + + $arg = &$this->s_['arguments'][0]; + foreach ($arg['values'] as $val) + { + if (preg_match('/^'. $val['regex'] .'$/m', $text)) + { + // Check if the argument value needs a 'require' + if (isset($val['requires']) && !$this->wasRequired_($val['requires'])) + { + $this->message = 'line '. $line .': missing require for '. $val['name'] .' '. $text; + return false; + } + + // Check if a possible value of this argument may occur + if ($val['occurrences'] == '?' || $val['occurrences'] == '1') + { + $val['occurrences'] = '0'; + } + else if ($val['occurrences'] == '+') + { + $val['occurrences'] = '*'; + } + else if ($val['occurrences'] == '0') + { + $this->message = 'line '. $line .': too many '. $val['name'] .' '. $class .'s near '. $text; + return false; + } + + // Call extra processing function if defined + if (isset($val['call']) && !call_user_func(array(&$this, $val['call']), $text) || + isset($arg['call']) && !call_user_func(array(&$this, $arg['call']), $text)) + { + $this->message = 'line '. $line .': '. $this->message; + return false; + } + + // Set occurrences appropriately + if ($arg['occurrences'] == '?' || $arg['occurrences'] == '1') + { + array_shift($this->s_['arguments']); + } + else + { + $arg['occurrences'] = '*'; + } + + // Add argument(s) expected to follow right after this one + if (isset($val['add'])) + { + while ($add_arg = array_pop($val['add'])) + { + array_unshift($this->s_['arguments'], $add_arg); + } + } + + return true; + } + } + + $this->message = 'line '. $line .': unexpected '. $name; + return false; + } + + function done($class, $text, $line) + { + if (isset($this->s_['arguments'])) + { + foreach ($this->s_['arguments'] as $arg) + { + if ($arg['occurrences'] == '+' || $arg['occurrences'] == '1') + { + $this->message = 'line '. $line .': '. $class .' '. $text .' where '. $arg['class'] .' expected'; + return false; + } + } + } + return true; + } +} + +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieve.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieve.inc new file mode 100644 index 000000000..c45d0f18e --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieve.inc @@ -0,0 +1,516 @@ + + * + * 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 +*/ + + +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 "
Trying to receive $this->err_len bytes for result
"; + $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 "UNKNOWN ERROR (Please report this line to danellis@rushmore.com to include in future releases): $this->line
"; + return false; + } /* end else */ + } /* end get_response() */ + + function sieve($host, $port, $user, $pass, $auth="", $auth_types="PLAIN DIGEST-MD5") + { + $this->host=$host; + $this->port=$port; + $this->user=$user; + $this->pass=$pass; + if(!strcmp($auth, "")) /* If there is no auth user, we deem the user itself to be the auth'd user */ + $this->auth = $this->user; + else + $this->auth = $auth; + $this->auth_types=$auth_types; /* Allowed authentication types */ + $this->fp=0; + $this->line=""; + $this->retval=""; + $this->tmpfile=""; + $this->fh=0; + $this->len=0; + $this->capabilities=""; + $this->loggedin=false; + $this->error= ""; + $this->error_raw=""; + } + + function parse_for_quotes($string) + { + /* This function tokenizes a line of input by quote marks and returns them as an array */ + + $start = -1; + $index = 0; + + for($ptr = 0; $ptr < strlen($string); $ptr++){ + if($string[$ptr] == '"' and $string[$ptr] != '\\'){ + if($start == -1){ + $start = $ptr; + } /* end if */ + else{ + $token[$index++] = substr($string, $start + 1, $ptr - $start - 1); + $found = true; + $start = -1; + } /* end else */ + + } /* end if */ + + } /* end for */ + + if(isset($token)) + return $token; + else + return false; + } /* end function */ + + function status($string) + { + //this should probably be replaced by a smarter parser. + + /* Need to remove this and all dependencies from the class */ + + switch (substr($string, 0,2)){ + case "NO": + return F_NO; //there should be some function to extract the error code from this line + //NO ("quota") "You are oly allowed x number of scripts" + break; + case "OK": + return F_OK; + break; + default: + switch ($string[0]){ + case "{": + //do parse here for {}'s maybe modify parse_for_quotes to handle any parse delimiter? + return F_HEAD; + break; + default: + return F_DATA; + break; + } /* end switch */ + } /* end switch */ + } /* end status() */ + + function sieve_login() + { + + $this->fp=@fsockopen($this->host,$this->port); + if($this->fp == false) + return false; + + $this->line=fgets($this->fp,1024); + + //Hack for older versions of Sieve Server. They do not respond with the Cyrus v2. standard + //response. They repsond as follows: "Cyrus timsieved v1.0.0" "SASL={PLAIN,........}" + //So, if we see IMLEMENTATION in the first line, then we are done. + + if(ereg("IMPLEMENTATION",$this->line)) + { + //we're on the Cyrus V2 sieve server + while(sieve::status($this->line) == F_DATA){ + + $this->item = sieve::parse_for_quotes($this->line); + + if(strcmp($this->item[0], "IMPLEMENTATION") == 0) + $this->capabilities["implementation"] = $this->item[1]; + + elseif(strcmp($this->item[0], "SIEVE") == 0 or strcmp($this->item[0], "SASL") == 0){ + + if(strcmp($this->item[0], "SIEVE") == 0) + $this->cap_type="modules"; + else + $this->cap_type="auth"; + + $this->modules = split(" ", $this->item[1]); + if(is_array($this->modules)){ + foreach($this->modules as $this->module) + $this->capabilities[$this->cap_type][$this->module]=true; + } /* end if */ + elseif(is_string($this->modules)) + $this->capabilites[$this->cap_type][$this->modules]=true; + } + else{ + $this->capabilities["unknown"][]=$this->line; + } + $this->line=fgets($this->fp,1024); + + }// end while + } + else + { + //we're on the older Cyrus V1. server + //this version does not support module reporting. We only have auth types. + $this->cap_type="auth"; + + //break apart at the "Cyrus timsieve...." "SASL={......}" + $this->item = sieve::parse_for_quotes($this->line); + + $this->capabilities["implementation"] = $this->item[0]; + + //we should have "SASL={..........}" now. Break out the {xx,yyy,zzzz} + $this->modules = substr($this->item[1], strpos($this->item[1], "{"),strlen($this->item[1])-1); + + //then split again at the ", " stuff. + $this->modules = split($this->modules, ", "); + + //fill up our $this->modules property + if(is_array($this->modules)){ + foreach($this->modules as $this->module) + $this->capabilities[$this->cap_type][$this->module]=true; + } /* end if */ + elseif(is_string($this->modules)) + $this->capabilites[$this->cap_type][$this->module]=true; + } + + + + + if(sieve::status($this->line) == F_NO){ //here we should do some returning of error codes? + $this->error=EC_UNKNOWN; + $this->error_raw = "Server not allowing connections."; + return false; + } + + /* decision login to decide what type of authentication to use... */ + + /* Loop through each allowed authentication type and see if the server allows the type */ + foreach(split(" ",$this->auth_types) as $auth_type) + { + if ($this->capabilities["auth"][$auth_type]) + { + /* We found an auth type that is allowed. */ + $this->auth_in_use = $auth_type; + break; + } + } + + /* Fill error message if no auth types are present */ + if (!isset($this->capabilities["auth"])){ + $this->error=EC_UNKNOWN; + $this->error_raw = "No authentication methods found - please check your sieve setup for missing sasl modules"; + return false; + } + + /* call our authentication program */ + return sieve::authenticate(); + + } + + function sieve_logout() + { + if($this->loggedin==false) + return false; + + fputs($this->fp,"LOGOUT\r\n"); + fclose($this->fp); + $this->loggedin=false; + return true; + } + + function sieve_sendscript($scriptname, $script) + { + if($this->loggedin==false) + return false; + $this->script=stripslashes($script); + $len=strlen($this->script); + fputs($this->fp, "PUTSCRIPT \"$scriptname\" {".$len."+}\r\n"); + fputs($this->fp, "$this->script\r\n"); + + return sieve::get_response(); + + } + + //it appears the timsieved does not honor the NUMBER type. see lex.c in timsieved src. + //don't expect this function to work yet. I might have messed something up here, too. + function sieve_havespace($scriptname, $scriptsize) + { + if($this->loggedin==false) + return false; + fputs($this->fp, "HAVESPACE \"$scriptname\" $scriptsize\r\n"); + return sieve::get_response(); + + } + + function sieve_setactivescript($scriptname) + { + if($this->loggedin==false) + return false; + + fputs($this->fp, "SETACTIVE \"$scriptname\"\r\n"); + return sieve::get_response(); + + } + + function sieve_getscript($scriptname) + { + unset($this->script); + if($this->loggedin==false) + return false; + + fputs($this->fp, "GETSCRIPT \"$scriptname\"\r\n"); + return sieve::get_response(); + + } + + + function sieve_deletescript($scriptname) + { + if($this->loggedin==false) + return false; + + fputs($this->fp, "DELETESCRIPT \"$scriptname\"\r\n"); + + return sieve::get_response(); + } + + + function sieve_listscripts() + { + fputs($this->fp, "LISTSCRIPTS\r\n"); + sieve::get_response(); //should always return true, even if there are no scripts... + if(isset($this->found_script) and $this->found_script) + return true; + else{ + $this->error=EC_NOSCRIPTS; //sieve::getresponse has no way of telling wether a script was found... + $this->error_raw="No scripts found for this account."; + return false; + } + } + + function sieve_alive() + { + if(!isset($this->fp) or $this->fp==0){ + $this->error = EC_NOT_LOGGED_IN; + return false; + } + elseif(feof($this->fp)){ + $this->error = EC_NOT_LOGGED_IN; + return false; + } + else + return true; + } + + function authenticate() + { + + switch ($this->auth_in_use) { + + case "PLAIN": + $auth=base64_encode("$this->user\0$this->auth\0$this->pass"); + + $this->len=strlen($auth); + fputs($this->fp, "AUTHENTICATE \"PLAIN\" {".$this->len."+}\r\n"); + fputs($this->fp, "$auth\r\n"); + + $this->line=fgets($this->fp,1024); + while(sieve::status($this->line) == F_DATA) + $this->line=fgets($this->fp,1024); + + if(sieve::status($this->line) == F_NO) + return false; + $this->loggedin=true; + return true; + break; + + default: + return false; + break; + + }//end switch + + + }//end authenticate() + + +} + + + +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_End.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_End.inc new file mode 100644 index 000000000..3bd0b0436 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_End.inc @@ -0,0 +1,32 @@ +object_id = $object_id; + } + + function execute() + { + $smarty = get_smarty(); + return($smarty->fetch(get_template_path("templates/element_block_end.tpl",TRUE,dirname(__FILE__)))); + } + function check() + { + return(array()); + } + + function get_sieve_script_part() + { + return("}"); + } + function save_object() + { + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_Start.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_Start.inc new file mode 100644 index 000000000..e001cdc58 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Block_Start.inc @@ -0,0 +1,33 @@ +object_id = $object_id; + } + + function execute() + { + $smarty = get_smarty(); + return($smarty->fetch(get_template_path("templates/element_block_start.tpl",TRUE,dirname(__FILE__)))); + } + + function check() + { + return(array()); + } + + function save_object() + { + } + + function get_sieve_script_part() + { + return("{"); + } +} +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Comment.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Comment.inc new file mode 100644 index 000000000..deaa4f312 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Comment.inc @@ -0,0 +1,84 @@ +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 new file mode 100644 index 000000000..1ee28ad43 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Discard.inc @@ -0,0 +1,40 @@ +object_id = $object_id; + } + + function get_sieve_script_part() + { + return("discard;"); + } + function check() + { + return(array()) ; + } + + + function save_object() + { + + } + + function execute() + { + $smarty = get_smarty(); + $smarty->assign("ID", $this->object_id); + $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__))); + $object = $smarty->fetch(get_template_path("templates/element_discard.tpl",TRUE,dirname(__FILE__))); + $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container); + return($str); + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Else_Elsif.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Else_Elsif.inc new file mode 100644 index 000000000..c02e12360 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Else_Elsif.inc @@ -0,0 +1,43 @@ +object_id = $object_id; + } + + function save_object() + { + } + + function execute() + { + $smarty = get_smarty(); + $smarty->assign("ID", $this->object_id); + $object_container = $smarty->fetch(get_template_path("templates/object_container_clear.tpl",TRUE,dirname(__FILE__))); + $object= $smarty->fetch(get_template_path("templates/element_else.tpl",TRUE,dirname(__FILE__))); + $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container); + return($str); + } + + function get_sieve_script_part() + { + return("else"); + } +} + +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Fileinto.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Fileinto.inc new file mode 100644 index 000000000..dc3923f41 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Fileinto.inc @@ -0,0 +1,104 @@ +get_mail_boxes(); + + if(isset($_POST['fileinto_'.$this->object_id])){ + $mb = stripslashes($_POST['fileinto_'.$this->object_id]); + + /* Depending on the user mode we only accept + * existing mailboxes + */ + if($this->user_mode){ + $this->data = $mb; + }else{ + if(in_array_ics($mb,$mbs)){ + $this->data = $mb; + } + } + + /* Check Mode */ + if(isset($_POST['user_mode_'.$this->object_id])){ + $this->user_mode = !$this->user_mode; + } + } + } + + function sieve_fileinto($data,$object_id,$parent) + { + $this->object_id = $object_id; + $this->parent = $parent; + $this->parent->add_require("fileinto"); + + $mbs = $this->get_mail_boxes(); + + /* Set the default mailbox */ + if($data === NULL){ + $data = array('ELEMENTS' => array(array('class' => "quoted-string" ,"text" => $mbs[key($mbs)]))); + } + + /* Load element contents, should normaly be only one string + * but if we found more than one, just append the following strings. + */ + for($i = 0 ; $i < count($data['ELEMENTS']) ; $i++){ + $tmp = sieve_get_strings($data['ELEMENTS'],$i); + $i = $i + $tmp['OFFSET']; + foreach($tmp['STRINGS'] as $str){ + $this->data .= $str; + } + } + + /* Set user mode to active, so we are able to insert + * the destination mail folder manually + */ + if(!in_array_ics($this->data,$mbs)){ + $this->user_mode = TRUE; + } + } + + function get_sieve_script_part() + { + $tmp = ""; + $tmp.= "\"".$this->data."\", "; + $tmp = preg_replace("/,$/","",trim($tmp)); + $tmp = preg_replace ("/\"\"/","\"",$tmp); + return("fileinto ".$tmp.";"); + } + + function execute() + { + $smarty = get_smarty(); + $smarty->assign("Selected",htmlentities($this->data)); + $smarty->assign("Boxes", $this->get_mail_boxes()); + $smarty->assign("User_Mode", $this->user_mode); + $smarty->assign("ID", $this->object_id); + $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__))); + $object= $smarty->fetch(get_template_path("templates/element_fileinto.tpl",TRUE,dirname(__FILE__))); + $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container); + + return($str); + } + + function check() + { + return(array()); + } + + function get_mail_boxes() + { + $list = $this->parent->parent->parent->parent->mailboxList; + return($list); + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_If.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_If.inc new file mode 100644 index 000000000..cb33ae5e7 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_If.inc @@ -0,0 +1,1469 @@ +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] + + + */ + + /* 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] + + + */ + + /* 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] + + + */ + + /* 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 + + */ + + /* Invert ? */ + if($Inverse){ + $script .= "not "; + } + + $script .= "exists ".sieve_create_strings($data['Values']); + break; + } + + + /******************* + * Size + *******************/ + case "size" : + { + /* [not] size + <":over" / ":under"> + + */ + + /* 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 + anyof */ + + + /* 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] + + + */ + + /* 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 = ""; + $name .= ""._("Condition").""; + 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%%/",""._("Click here to add a new test")."",$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 + + + */ + + + $part = "(:all|:localpart|:domain)"; + $operator = "(:regex|:contains|:is|:matches|:count|:value)"; + $value_op = "(lt|le|eq|ge|gt|ne)"; + + $Address_Part = ""; + $Comparator = ""; + $Match_type = ""; + $Match_type_value = ""; + + $Key_List = array(); + $Value_List = array(); + + for($i = 0 ; $i < count($data) ; $i ++){ + + /* Get next node */ + $node = $data[$i]; + + /* Check address part definition */ + if($node['class'] == "tag" && preg_match("/".$part."/i",$node['text'])){ + $Address_Part = $node['text']; + } + + /* Check for match type */ + elseif($node['class'] == "tag" && preg_match("/".$operator."/i",$node['text'])){ + $Match_type = $node['text']; + + /* Get value operator */ + if(in_array($Match_type,array(":value",":count"))){ + $i ++; + $node = $data[$i]; + + if($node['class'] == "quoted-string" && preg_match("/".$value_op."/",$node['text'])){ + $Match_type_value = $node['text']; + } + } + } + + /* Check for a comparator */ + elseif($node['class'] == "tag" && preg_match("/comparator/",$node['text'])){ + $i ++; + $node = $data[$i]; + $Comparator = $node['text']; + } + + /* Check for Key_List */ + elseif(count(sieve_get_strings($data,$i))){ + $tmp2 = sieve_get_strings($data,$i); + $i = $tmp2['OFFSET']; + + if(!count($Key_List)){ + $Key_List = $tmp2['STRINGS']; + }else{ + $Value_List = $tmp2['STRINGS']; + } + } + + } + + + /* Add to Tree */ + $values = array( "Inverse" => $Inverse, + "Comparator" => $Comparator, + "Expert" => FALSE, + "Match_type" => $Match_type, + "Match_type_value"=> $Match_type_value, + "Key_List" => $Key_List, + "Value_List" => $Value_List) ; + if($type == "address"){ + $values["Address_Part"] = $Address_Part; + } + $tmp[$type] = $values; + $tmp[$type]['LastError'] = ""; + break; + } + + + /**************** + * Parse - Size + ****************/ + + case "size": + { + + $ops = "(:over|:under)"; + + $Match_type = ""; + + for($i = $id ; $i < count($data); $i++){ + + /* Get current node */ + $node = $data[$i]; + + /* Get tag (under / over) */ + if($node['class'] == "tag" && preg_match("/".$ops."/",$node['text'])){ + $Match_type = $node['text']; + } + + /* Get Value_List, the value that we want to match for */ + elseif(count(sieve_get_strings($data,$i))){ + $tmp2 = sieve_get_strings($data,$i); + $i = $tmp2['OFFSET']; + + $Value_List = $tmp2['STRINGS']; + } + } + + $tmp[$type]= array( "Inverse" => $Inverse, + "Match_type" => $Match_type, + "Value_List" => $Value_List); + $tmp[$type]['LastError'] = ""; + break; + } + + + /**************** + * Parse - True / False + ****************/ + + case "true": + { + $tmp['true'] = "true"; + $tmp['true']['LastError'] = ""; + break; + } + case "false": + { + $tmp['false'] = "false"; + $tmp['false']['LastError'] = ""; + break; + } + + + /**************** + * Parse - Exists + ****************/ + + case "exists": + { + + /* Skip first values, [if,not,exists] */ + $node = $data[$id]; + while(in_array($node['text'],array("if","not","exists"))){ + $id ++; + $node = $data[$id]; + } + + /* Get values */ + $tmp2 = sieve_get_strings($data,$id); + + + $tmp['exists'] = array('Inverse' => $Inverse, + 'Values' => $tmp2['STRINGS']); + $tmp[$type]['LastError'] = ""; + break; + } + + + /**************** + * Parse - Allof + ****************/ + + case "allof" : + { + /* Get parameter and recursivly call this method + * for each parameter + */ + $id ++; + $tmp2 = $this->get_parameter($data,$id); + + foreach($tmp2 as $parameter){ + $tmp['allof'][] = $this->_parse($parameter); + } + $tmp['allof']['Inverse'] = $Inverse; + break; + } + + + /**************** + * Parse - Anyof + ****************/ + + case "anyof" : + { + /* Get parameter and recursivly call this method + * for each parameter + */ + $id ++; + $tmp2 = $this->get_parameter($data,$id); + + foreach($tmp2 as $parameter){ + $tmp['anyof'][] = $this->_parse($parameter); + } + $tmp['anyof']['Inverse'] = $Inverse; + break; + } + default : $tmp[$id] = $type; + } + + return($tmp); + } + + + function get_parameter($data,$id) + { + $par = array(); + $open_brakets = 0; + $next = NULL; + $num = 0; + for($i = $id ; $i < count($data) ; $i++ ){ + if(in_array($data[$i]['class'],array("left-parant","left-bracket"))){ + $open_brakets ++; + } + if($data[$i]['class'] == "comma" && $open_brakets == 1){ + $num ++; + } + if(!in_array($data[$i]['class'],array("comma","left-parant","right-parant")) || $open_brakets >1 ){ + $par[$num][] = $data[$i]; + } + if(in_array($data[$i]['class'],array("right-parant","right-bracket"))){ + $open_brakets --; + } + } + return($par); + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Keep.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Keep.inc new file mode 100644 index 000000000..3e1d58e1c --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Keep.inc @@ -0,0 +1,38 @@ +object_id = $object_id; + } + + function save_object() + { + } + + function check() + { + return(array()); + } + + function execute() + { + $smarty = get_smarty(); + $smarty->assign("ID", $this->object_id); + $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__))); + $object = $smarty->fetch(get_template_path("templates/element_keep.tpl",TRUE,dirname(__FILE__))); + $str = preg_replace("/%%OBJECT_CONTENT%%/", addcslashes($object,"\\"),$object_container); + return($str); + } + function get_sieve_script_part() + { + return("keep;"); + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Redirect.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Redirect.inc new file mode 100644 index 000000000..bbb2d4bf1 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Redirect.inc @@ -0,0 +1,69 @@ +object_id])){ + $rt = stripslashes($_POST['redirect_to_'.$this->object_id]); + + $rt = trim($rt); + $this->data = $rt; + } + } + + + function check() + { + $msgs = array(); + + if(!tests::is_email($this->data)){ + $msgs[] =_("Please specify a valid email address."); + } + + return($msgs); + } + + function sieve_redirect($data,$object_id) + { + $this->object_id = $object_id; + + if($data === NULL){ + $data = array('ELEMENTS' => array(array('class' => "quoted-string" ,"text" => _("Place a mail address here")))); + } + + for($i = 0 ; $i < count($data['ELEMENTS']) ; $i++){ + $tmp = sieve_get_strings($data['ELEMENTS'],$i); + $i = $i + $tmp['OFFSET']; + foreach($tmp['STRINGS'] as $str){ + $this->data .= $str; + } + } + } + + + function get_sieve_script_part() + { + return("redirect ".sieve_create_strings($this->data).";"); + } + + + function execute() + { + $values = htmlentities($this->data); + $smarty = get_smarty(); + $smarty->assign("ID", $this->object_id); + $smarty->assign("Destinations" , $values); + $smarty->assign("LastError" , $this->check()); + $smarty->assign("LastErrorCnt" , count($this->check())); + $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__))); + $object= $smarty->fetch(get_template_path("templates/element_redirect.tpl",TRUE,dirname(__FILE__))); + $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container); + return($str); + } +} +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Reject.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Reject.inc new file mode 100644 index 000000000..3f0726011 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Reject.inc @@ -0,0 +1,76 @@ +object_id])){ + $msg = stripslashes($_POST['reject_message_'.$this->object_id]); + $this->data = $msg; + } + } + + function check() + { + $msgs = array(); + if(preg_match("/\"/",$this->data)){ + $msgs [] = _("Invalid character found, quotes are not allowed in a reject message."); + } + return($msgs); + } + + function sieve_reject($data,$object_id,$parent) + { + $this->object_id = $object_id; + $this->parent = $parent; + $this->parent->add_require("reject"); + + /* If the given data is emtpy + * (This is the case when we add new elements in the ui) + * Set a default text. + */ + if($data === NULL){ + $this->data = _("Your reject text here"); + }else{ + + for($i = 0 ; $i < count($data['ELEMENTS']) ; $i++){ + $tmp = sieve_get_strings($data['ELEMENTS'],$i); + $i = $i + $tmp['OFFSET']; + foreach($tmp['STRINGS'] as $str){ + $this->data .= $str; + } + } + } + } + + function get_sieve_script_part() + { + return("reject ".sieve_create_strings($this->data).";"); + } + + function execute() + { + /* check if this will be a + * - single string "" + * - or a multi line text: ... ; + */ + $Multiline = preg_match("/\n/",$this->data); + + $smarty = get_smarty(); + $smarty->assign("ID", $this->object_id); + $smarty->assign("Message",$this->data); + $smarty->assign("Multiline",$Multiline); + $smarty->assign("LastError" , $this->check()); + $smarty->assign("LastErrorCnt" , count($this->check())); + $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__))); + $object= $smarty->fetch(get_template_path("templates/element_reject.tpl",TRUE,dirname(__FILE__))); + $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container); + return($str); + } +} +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Require.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Require.inc new file mode 100644 index 000000000..a9b689034 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Require.inc @@ -0,0 +1,109 @@ +parent = $parent; + $this->object_id = $object_id; + if($data !== NULL){ + + for($i = 0 ; $i < count($data['ELEMENTS']) ; $i++){ + $tmp = sieve_get_strings($data['ELEMENTS'],$i); + $i = $i + $tmp['OFFSET']; + foreach($tmp['STRINGS'] as $str){ + $this->data[]= $str; + } + } + } + } + + + /* Add a new require statement and ensure + * that it is not specified twice + */ + function Add_Require($str) + { + $current = array(); + foreach($this->data as $dat){ + $current[] = $dat; + } + if(!in_array($str,$current)){ + $this->data[] = $str; + } + $this->data = array_unique($this->data); + $this->skip_save_object = TRUE; + } + + function save_object() + { + if($this->skip_save_object){ + $this->skip_save_object = FALSE; + return; + } + + /* Get the values should check for, they are seperated by , */ + if(isset($_POST['require_'.$this->object_id])){ + $vls = stripslashes($_POST['require_'.$this->object_id]); + $tmp = array(); + + $tmp2 = split(",",$vls); + foreach($tmp2 as $val){ + + $val = trim($val); + + if(empty($val)) continue; + + $tmp[] = $val; + } + $this->data = $tmp; + } + } + + function check() + { + $msgs = array(); + + if(!count($this->data)){ + $msgs[] = _("Please specify at least one valid requirement."); + } + return($msgs); + } + + function get_sieve_script_part() + { + if(count($this->data)){ + $tmp = sieve_create_strings($this->data); + return("require ".$tmp.";\n"); + }else{ + return(""); + } + } + + function execute() + { + $Require = ""; + foreach($this->data as $key){ + $Require .= $key.", "; + } + $Require = preg_replace("/,$/","",trim($Require)); + + $smarty = get_smarty(); + $smarty->assign("Require",$Require); + $tmp = $this->check(); + $smarty->assign("LastError",$tmp); + $smarty->assign("LastErrorCnt",count($tmp)); + $smarty->assign("ID", $this->object_id); + $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__))); + $object= $smarty->fetch(get_template_path("templates/element_require.tpl",TRUE,dirname(__FILE__))); + $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container); + return($str); + } +} +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Stop.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Stop.inc new file mode 100644 index 000000000..9acc72bd9 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Stop.inc @@ -0,0 +1,39 @@ +object_id = $object_id; + } + + function save_object() + { + } + + function check() + { + return(array()); + } + + function execute() + { + $smarty = get_smarty(); + $smarty->assign("ID", $this->object_id); + $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__))); + $object= $smarty->fetch(get_template_path("templates/element_stop.tpl",TRUE,dirname(__FILE__))); + $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container); + return($str); + } + + function get_sieve_script_part() + { + return("stop; \n"); + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Vacation.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Vacation.inc new file mode 100644 index 000000000..1af166e9d --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveElement_Vacation.inc @@ -0,0 +1,179 @@ +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] */ + + /* Not all attribute types are supported by the sieve class right now */ + $known_attrs = array(":days",":subject",":from",":mime",":handle"); + + /* skip if empty */ + if(($data === NULL) || !is_array($data)) return; + + /* Walk through elements */ + $p= count($data['ELEMENTS']); + for ($i= 0; $i < $p; $i++){ + + /* get current element */ + $node = $data['ELEMENTS'][$i]; + + /* Check if tag is in the specified list of attributes */ + if($node['class'] == "tag" && in_array($node['text'],$known_attrs)){ + + $var = preg_replace("/\:/","",$node['text']); + $this->$var = $data['ELEMENTS'][$i+1]['text']; + $i ++; + } + + /* Check for addresses */ + if($node['class'] == "tag" && $node['text'] == ":addresses") { + $this->addresses = array(); + $i ++; + + /* Multiple or single address given */ + if($data['ELEMENTS'][$i]['class'] == "left-bracket"){ + while($data['ELEMENTS'][$i]['class'] != "right-bracket" && ($i < count($data['ELEMENTS']))){ + $i ++; + if($data['ELEMENTS'][$i]['class'] == "quoted-string"){ + $this->addresses[] = preg_replace("/\"/i","",$data['ELEMENTS'][$i]['text']); + } + } + }else{ + $this->addresses[] = preg_replace("/\"/i","",$data['ELEMENTS'][$i]['text']); + } + } + + /* Add the vacation message */ + if(in_array($node['class'],array("quoted-string","multi-line"))){ + + $tmp = sieve_get_strings($data['ELEMENTS'],$i); + $strs= $tmp['STRINGS']; + + $data = ""; + foreach($strs as $str){ + $data .= $str; + } + $this->reason = $data; + } + } + } + + function get_sieve_script_part() + { + $str = "vacation "; + if($this->days){ + $str.= ":days ".$this->days; + } + + if(count($this->addresses)){ + $str .= ":addresses ".sieve_create_strings($this->addresses); + if($this->subject){ + $str.= ":subject ".sieve_create_strings($this->subject); + } + } + if($this->mime){ + $str.= ":mime ".sieve_create_strings($this->mime); + } + + /* Append reason and ensure that this will be + * handled as multiline text element + * by adding a "\n" new line + */ + $str .= "\n ".sieve_create_strings($this->reason."\n"); + return($str." ; \n"); + } + + function save_object() + { + /* Get release date */ + if(isset($_POST['vacation_release_'.$this->object_id])){ + $this->days = stripslashes($_POST['vacation_release_'.$this->object_id]); + } + + /* Check if we want to toggle the expert mode */ + if(isset($_POST['Toggle_Expert_'.$this->object_id])){ + $this->Expert = !$this->Expert; + } + + /* Get release date */ + if(isset($_POST['vacation_receiver_'.$this->object_id])){ + $vr = stripslashes ($_POST['vacation_receiver_'.$this->object_id]); + $tmp = array(); + $tmp2 = split(",",$vr); + foreach($tmp2 as $val){ + $ad = trim($val); + if(!empty($ad)){ + $tmp[] = $ad; + } + } + $this->addresses = $tmp; + } + + /* Get reason */ + if(isset($_POST['vacation_reason_'.$this->object_id])){ + $vr = stripslashes ($_POST['vacation_reason_'.$this->object_id]); + $this->reason = trim($vr); + } + } + + function check() + { + $msgs = array(); + $err = FALSE; + foreach($this->addresses as $addr){ + if(!tests::is_email($addr)){ + $err = true; + } + } + if($err){ + $msgs[] = _("Alternative sender address must be a valid email addresses."); + } + return($msgs); + } + + function execute() + { + $Addresses = ""; + foreach($this->addresses as $key){ + $Addresses .= $key.", "; + } + $Addresses = preg_replace("/,$/","",trim($Addresses)); + + $smarty = get_smarty(); + $smarty->assign("LastError",$this->check()); + $smarty->assign("LastErrorCnt",count($this->check())); + $smarty->assign("Reason",$this->reason); + $smarty->assign("Addresses",$Addresses); + $smarty->assign("Subject",$this->subject); + $smarty->assign("Days",$this->days); + $smarty->assign("ID",$this->object_id); + $smarty->assign("Expert",$this->Expert); + + $object_container = $smarty->fetch(get_template_path("templates/object_container.tpl",TRUE,dirname(__FILE__))); + $object= $smarty->fetch(get_template_path("templates/element_vacation.tpl",TRUE,dirname(__FILE__))); + $str = preg_replace("/%%OBJECT_CONTENT%%/",addcslashes($object,"\\"),$object_container); + return($str); + } +} + +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_sieveManagement.inc b/gosa-plugins/mail/personal/mail/sieve/class_sieveManagement.inc new file mode 100644 index 000000000..417853e4b --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_sieveManagement.inc @@ -0,0 +1,1057 @@ + + + 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")."".$p->status_text.""; + }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")."".$p->status_text.""; + }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"), '

'.to_string($this->Sieve_Error).''), 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"), '

'.to_string($this->sieve_handler->error_raw).''), 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"), '

'.to_string($this->Sieve_Error).''), 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"), '

'.to_string($this->sieve_handler->error_raw).''), 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" => ""._("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 = ""; + }else{ + $del = " "; + } + + if($active || $script['IS_NEW'] || !$this->parent->acl_is_writeable("sieveManagement")){ + $activate = " "; + }else{ + $activate = ""; + } + + $field6 = array("string" => $activate."".$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"), '

'.to_string($this->Sieve_Error).''), 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"), '

'.to_string($this->sieve_handle->error_raw).''), ERROR_DIALOG); + $this->scripts[$key]['MSG'] = "". + _("Failed to save sieve script").": ". + to_string($this->sieve_handle->error_raw). + ""; + } + } + } + return($everything_went_fine); + } +} +// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/class_tree.inc b/gosa-plugins/mail/personal/mail/sieve/class_tree.inc new file mode 100644 index 000000000..d4bdfc764 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/class_tree.inc @@ -0,0 +1,153 @@ +_construct($root); + } + + function _construct(&$root) + { + $this->childs_ = array(); + $this->parents_ = array(); + $this->nodes_ = array(); + $this->maxId_ = 0; + + $this->parents_[0] = null; + $this->nodes_[0] = $root; + } + + function addChild(&$child) + { + return $this->addChildTo($this->maxId_, $child); + } + + function addChildTo($parent_id, &$child) + { + if (!is_int($parent_id) || + !isset($this->nodes_[$parent_id])) + { + return null; + } + + if (!isset($this->childs_[$parent_id])) + { + $this->childs_[$parent_id] = array(); + } + + $child_id = ++$this->maxId_; + $this->nodes_[$child_id] = $child; + $this->parents_[$child_id] = $parent_id; + array_push($this->childs_[$parent_id], $child_id); + + return $child_id; + } + + function getRoot() + { + if (!isset($this->nodes_[0])) + { + return null; + } + + return 0; + } + + function getParent($node_id) + { + if (!is_int($node_id) || + !isset($this->nodes_[$node_id])) + { + return null; + } + + return $this->parents_[$node_id]; + } + + function getChilds($node_id) + { + if (!is_int($node_id) || + !isset($this->nodes_[$node_id])) + { + return null; + } + + if (!isset($this->childs_[$node_id])) + { + return array(); + } + + return $this->childs_[$node_id]; + } + + function getNode($node_id) + { + if (!is_int($node_id) || + !isset($this->nodes_[$node_id])) + { + return null; + } + + return $this->nodes_[$node_id]; + } + + function setDumpFunc($callback) + { + if ($callback === NULL || is_callable($callback)) + { + $this->dumpFn_ = $callback; + } + } + + function dump() + { + $this->dump_ = "tree\n"; + $this->doDump_(0, '', true); + return $this->dump_; + } + + function doDump_($node_id, $prefix, $last) + { + if ($last) + { + $infix = '`--- '; + $child_prefix = $prefix . ' '; + } + else + { + $infix = '|--- '; + $child_prefix = $prefix . '| '; + } + + $node = $this->nodes_[$node_id]; + if ($this->dumpFn_ !== NULL) + { + $this->dump_ .= $prefix . $infix . call_user_func($this->dumpFn_, $node) . "\n"; + } + else + { + $this->dump_ .= "$prefix$infix$node\n"; + } + + if (isset($this->childs_[$node_id])) + { + $childs = $this->childs_[$node_id]; + $last_child = count($childs); + + for ($i=1; $i <= $last_child; ++$i) + { + $this->doDump_($childs[$i-1], $child_prefix, ($i == $last_child ? true : false)); + } + } + } +} + +?> diff --git a/gosa-plugins/mail/personal/mail/sieve/libsieve.inc b/gosa-plugins/mail/personal/mail/sieve/libsieve.inc new file mode 100644 index 000000000..3b94e4975 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/libsieve.inc @@ -0,0 +1,8 @@ + diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/add_element.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/add_element.tpl new file mode 100644 index 000000000..d98c52986 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/add_element.tpl @@ -0,0 +1,14 @@ +

{t}Add a new element{/t}

+{t}Please select the type of element you want to add{/t} +
+ + +

 

+
+
+ +   + +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/block_indent_start.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/block_indent_start.tpl new file mode 100644 index 000000000..482f637d7 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/block_indent_start.tpl @@ -0,0 +1,12 @@ + + + + + + + +
+   + + + +
 
+
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/block_indent_stop.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/block_indent_stop.tpl new file mode 100644 index 000000000..857aa6893 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/block_indent_stop.tpl @@ -0,0 +1,5 @@ +
+
 
+
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/create_script.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/create_script.tpl new file mode 100644 index 000000000..fa44081c0 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/create_script.tpl @@ -0,0 +1,21 @@ +

Create a new sieve script

+{t}Please enter the name for the new script below. Script names must consist of lower case characters only.{/t} + +
+
+

 

+
+{t}Script name{/t} +
+
+ +
+ +   + +
+ diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/edit_frame_base.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/edit_frame_base.tpl new file mode 100644 index 000000000..83d62a026 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/edit_frame_base.tpl @@ -0,0 +1,42 @@ + + + + + + + + +
+ + + + + {if $Mode != "Source-Only"} + + {if $Mode == "Source"} + + {else} + + {/if} + {/if} +
+ + {if $Script_Error != ""} +
+ {$Script_Error} +
+ {/if} + + + {if $Mode == "Structured"} + {$Contents} + {else} + + {/if} + +
+
+ +   + +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_address.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_address.tpl new file mode 100644 index 000000000..ea6580f35 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_address.tpl @@ -0,0 +1,142 @@ +{if $Expert} + {if $LastError != ""} + + + + +
+ {$LastError} +
+ {/if} + + + + + + +
+ {t}Address{/t} + + +
+ + + + + + + + + + + + + + + + + + {if $match_type == ":count" || $match_type == ":value"} + + + + + {/if} + + + +
+ {t}Match type{/t} + + + +
+ {t}Invert test{/t}? + + {if $Inverse} + + {else} + + {/if} +
+ {t}Part of address that should be used{/t} + + +
+ {t}Comparator{/t} + + +
+ {t}Operator{/t} + + +
 
+ + + + + +
+ {t}Address fields to include{/t}
+ +
+ {t}Values to match for{/t}
+ +
+ {else} + + {if $LastError != ""} + + + + +
+ {$LastError} +
+ {/if} + + + + {if $match_type == ":count" || $match_type == ":value"} + + + + + +
+ {else} + + {/if} + {t}Address{/t} + + {if $Inverse} + + {else} + + {/if} +   + + + {if $match_type == ":count" || $match_type == ":value"} + + {/if} + + + + + + +
+ {/if} diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_allof.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_allof.tpl new file mode 100644 index 000000000..024c011e7 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_allof.tpl @@ -0,0 +1,16 @@ + + + + + +
+ {if $Inverse} + + {else} + + {/if} +
+ {t}All of{/t} +
+ {$Contents} +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_anyof.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_anyof.tpl new file mode 100644 index 000000000..f6e1b2203 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_anyof.tpl @@ -0,0 +1,16 @@ + + + + + +
+ {if $Inverse} + + {else} + + {/if} +
+ {t}Any of{/t} +
+ {$Contents} +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_block_end.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_block_end.tpl new file mode 100644 index 000000000..41c3a2c0b --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_block_end.tpl @@ -0,0 +1,5 @@ + diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_block_start.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_block_start.tpl new file mode 100644 index 000000000..526162453 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_block_start.tpl @@ -0,0 +1,12 @@ + diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_boolean.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_boolean.tpl new file mode 100644 index 000000000..44f5f7b52 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_boolean.tpl @@ -0,0 +1,12 @@ + + + + +
+ {t}Bool{/t} + + +
+
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_comment.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_comment.tpl new file mode 100644 index 000000000..56edf9455 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_comment.tpl @@ -0,0 +1,23 @@ + + + + + + + + +
+ {t}Comment{/t} + + {if $Small} + + {else} + + {/if} +
+ {if $Small} + {$Comment} + {else} + + {/if} +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_discard.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_discard.tpl new file mode 100644 index 000000000..e26f77a3a --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_discard.tpl @@ -0,0 +1,12 @@ + + + + + + + +
+ {t}Discard{/t} +
+ {t}Discard message{/t} +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_else.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_else.tpl new file mode 100644 index 000000000..739fd0550 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_else.tpl @@ -0,0 +1,7 @@ + + + + +
+ {t}Else{/t} +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_elsif.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_elsif.tpl new file mode 100644 index 000000000..4da7c47fc --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_elsif.tpl @@ -0,0 +1,8 @@ + + + + +
+ {t}Else If{/t} + {$Contents} +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_envelope.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_envelope.tpl new file mode 100644 index 000000000..f0bcb67f0 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_envelope.tpl @@ -0,0 +1,134 @@ + + {if $Expert} + {if $LastError != ""} + + + + +
+ {$LastError} +
+ {/if} + + + + + + +
+ {t}Envelope{/t} + + +
+ + + + + + + + + + + + + + {if $match_type == ":count" || $match_type == ":value"} + + + + + {/if} + + + +
+ {t}Match type{/t} + + + +
+ {t}Invert test{/t}? + + {if $Inverse} + + {else} + + {/if} +
+ {t}Comparator{/t} + + +
+ {t}Operator{/t} + + +
 
+ + + + + +
+ {t}Address fields to include{/t}
+ +
+ {t}Values to match for{/t}
+ +
+ + {else} + {if $LastError != ""} + + + + +
+ {$LastError} +
+ {/if} + + + {if $match_type == ":count" || $match_type == ":value"} + + + + + +
+ {else} + + {/if} + + + {t}Envelope{/t} + + {if $Inverse} + + {else} + + {/if} +   + + + {if $match_type == ":count" || $match_type == ":value"} + + {/if} + + + + + + +
+ {/if} diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_exists.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_exists.tpl new file mode 100644 index 000000000..29882d3f4 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_exists.tpl @@ -0,0 +1,20 @@ + + + + + +
+ {if $LastError != ""} + {$LastError} +
+ {/if} + {t}Exists{/t} + {if $Inverse} + + {else} + + {/if} + +
+ +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_fileinto.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_fileinto.tpl new file mode 100644 index 000000000..c6ae998e0 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_fileinto.tpl @@ -0,0 +1,30 @@ + + + + + + + + + + +
+ {t}Move mail into folder{/t} + + {if $User_Mode} + + {else} + + {/if} +
+ + {t}Folder{/t} + {if $User_Mode} + + {else} + + {/if} + +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_header.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_header.tpl new file mode 100644 index 000000000..8dcd30989 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_header.tpl @@ -0,0 +1,136 @@ + {if $Expert} + {if $LastError != ""} + + + + +
+ {$LastError} +
+ {/if} + + + + + + + +
+ {t}Header{/t} + + +
+ + + + + + + + + + + + + + {if $match_type == ":count" || $match_type == ":value"} + + + + + {/if} + + + + +
+ {t}Match type{/t} + + + +
+ {t}Invert test{/t}? + + {if $Inverse} + + {else} + + {/if} +
+ {t}Comparator{/t} + + +
+ {t}operator{/t} + + +
 
+ + + + + +
+ {t}Address fields to include{/t}
+ +
+ {t}Values to match for{/t}
+ +
+ + {else} + {if $LastError != ""} + + + + +
+ {$LastError} +
+ {/if} + + + + + {if $match_type == ":count" || $match_type == ":value"} + + + + + + +
+ {else} + + {/if} + {t}Header{/t} + + {if $Inverse} + + {else} + + {/if} +   + + + {if $match_type == ":count" || $match_type == ":value"} + + {/if} + + + + + + +
+ {/if} diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_if.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_if.tpl new file mode 100644 index 000000000..98f9b4a5d --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_if.tpl @@ -0,0 +1,8 @@ + + + + +
+ {t}Condition{/t} + {$Contents} +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_keep.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_keep.tpl new file mode 100644 index 000000000..f3c5d8608 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_keep.tpl @@ -0,0 +1,12 @@ + + + + + + + +
+ {t}Keep{/t} +
+ {t}Keep message{/t} +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_redirect.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_redirect.tpl new file mode 100644 index 000000000..778ff1a50 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_redirect.tpl @@ -0,0 +1,22 @@ + + {foreach from=$LastError item=val key=key} + + + + + {/foreach} + + + + + + +
+
{$LastError[$key]}
+ +
+ {t}Redirect{/t} +
+ {t}Redirect mail to following recipients{/t}
+ +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_reject.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_reject.tpl new file mode 100644 index 000000000..3b4d84d6a --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_reject.tpl @@ -0,0 +1,28 @@ + + +{foreach from=$LastError item=val key=key} + + + + + {/foreach} + + + + + + +
+
{$LastError[$key]}
+ +
+ {t}Reject mail{/t} +   + {if $Multiline} + + {else} + + {/if} +
+ +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_require.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_require.tpl new file mode 100644 index 000000000..3a3f261f3 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_require.tpl @@ -0,0 +1,21 @@ + + {foreach from=$LastError item=val key=key} + + + + + {/foreach} + + + + + + +
+
{$LastError[$key]}
+
+ {t}Require{/t} +
+ +
+ diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_size.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_size.tpl new file mode 100644 index 000000000..a8e234693 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_size.tpl @@ -0,0 +1,25 @@ + + + + +
+ {t}Size{/t} + {if $LastError != ""} + {$LastError} +
+ {/if} + + {if $Inverse} + + {else} + + {/if} + + + + +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_stop.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_stop.tpl new file mode 100644 index 000000000..975f10bda --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_stop.tpl @@ -0,0 +1,12 @@ + + + + + + + +
+ {t}Stop{/t}
+
+ {t}Stop execution here{/t} +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/element_vacation.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/element_vacation.tpl new file mode 100644 index 000000000..174148790 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/element_vacation.tpl @@ -0,0 +1,56 @@ + + + {foreach from=$LastError item=val key=key} + + + + {/foreach} + {if $Expert} + + + + + + + + + + + + + + + + {else} + + + + + + + + {/if} +
+
{$LastError[$key]}
+
+ {t}Vacation Message{/t} + + +
+ {t}Release interval{/t}  + + +  {t}days{/t} +
+ {t}Alternative sender addresses{/t} + + +
+ +
+ {t}Vacation message{/t} + + +
+ +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/import_script.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/import_script.tpl new file mode 100644 index 000000000..22df06caa --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/import_script.tpl @@ -0,0 +1,15 @@ +

{t}Import sieve script{/t}

+{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} +
+
+{t}Script to import{/t}  + +
+
+

 

+
+
+ +   + +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/management.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/management.tpl new file mode 100644 index 000000000..315e47e08 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/management.tpl @@ -0,0 +1,27 @@ +

{t}List of sieve scripts{/t}

+ + {$List} + +

+ +   + +

diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/object_container.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/object_container.tpl new file mode 100644 index 000000000..14925b1a5 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/object_container.tpl @@ -0,0 +1,54 @@ + + + + + + + + + +
+   + + + {t}Move up{/t} +     + + {t}Move down{/t} +     + + {t}Remove element{/t} +     + + + + + + + +
+ + %%OBJECT_CONTENT%% +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/object_container_clear.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/object_container_clear.tpl new file mode 100644 index 000000000..4f5579fe5 --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/object_container_clear.tpl @@ -0,0 +1,28 @@ + + + + + + + + + +
+   + + + {t}Move up{/t} + + + {t}Move down{/t} + + + {t}Remove element{/t} + +
+ + %%OBJECT_CONTENT%% +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/object_test_container.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/object_test_container.tpl new file mode 100644 index 000000000..e1577177a --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/object_test_container.tpl @@ -0,0 +1,17 @@ + + + + + +
+ {if $DisplayAdd} + + {/if} + {if $DisplayDel} + + {/if} + + %%OBJECT_CONTENT%% +
diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/remove_script.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/remove_script.tpl new file mode 100644 index 000000000..5bb5b49ae --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/remove_script.tpl @@ -0,0 +1,17 @@ +
+ {t}Warning{/t} +
+

+ {$Warning}
+ {t}Please double check if your really want to do this since there is no way for GOsa to get your data back.{/t} +

+ +

+ {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} +

+ +

+ +   + +

diff --git a/gosa-plugins/mail/personal/mail/sieve/templates/select_test_type.tpl b/gosa-plugins/mail/personal/mail/sieve/templates/select_test_type.tpl new file mode 100644 index 000000000..dd7a8fb2e --- /dev/null +++ b/gosa-plugins/mail/personal/mail/sieve/templates/select_test_type.tpl @@ -0,0 +1,14 @@ +

{t}Select the type of test you want to add{/t}

+ +{t}Available test types{/t} :  + + +

 

+
+
+ +   + +