Code

Updated Group-Mail
[gosa.git] / gosa-plugins / mail / admin / groups / mail / class_groupMail.inc
1 <?php
3 class mailgroup extends plugin
4 {
5   var $uid                        = "";       // User id 
6   var $cn                         = "";       // cn
7   var $orig_cn                    = "";       // cn
9   var $method                     = "mailMethod"; // Used Mail method 
10   var $mmethod                    = "";           // Contains the gosa.conf MAILMETHOD
11   var $mail                       = "";           // Default mail address 
13   var $gosaMailAlternateAddress   = array();  // Set default Alternate Mail Adresses to empty array
14   var $gosaMailForwardingAddress  = array();  // Forwarding also empty
16   var $gosaMailForwardingAddress_Some  = array();  // Used in multiple edit 
18   var $gosaMailServer             = "";       // Selected mailserver 
19   var $gosaMailQuota              = "";       // Defined Quota 
20   var $quotaUsage                 = 0;        // Currently used quota
22   var $gosaVacationMessage        = "";       // Vocation message 
24   var $imapacl                    = array('anyone'    => 'p',     // Set acls for everyone
25       '%members%' => 'lrswp',  // %members% are all group-members
26       ''          => 'p');    // Every user added gets this right
28   var $kolabFolderTypeSubType = "";
29   var $kolabFolderTypeType = "";
31   var $gosaSpamSortLevel          = "";     
32   var $gosaSpamMailbox            = "";
33   var $gosaSharedFolderTarget     ;
35   var $forward_dialog             = FALSE;    
37   var $members                    = array();  // Group members
39   var $mailusers                  = array();
40   var $perms                      = array();
41   var $gosaMailDeliveryMode       = "[L        ]";   // 
42   var $gosaMailMaxSize            = "";       // 
43   
44   var $remove_folder_from_imap    = true;
46   /* Helper */
47   var $indexed_acl= array();
48   var $indexed_user= array();
50   var $view_logged = FALSE;
52   /* attribute list for save action */
53   var $attributes= array( "mail",   "gosaMailServer", "gosaMailQuota", "gosaMailMaxSize",
54       "gosaMailAlternateAddress", "gosaMailForwardingAddress",
55       "gosaMailDeliveryMode", "gosaSpamSortLevel", "gosaSpamMailbox",
56       "acl","gosaSharedFolderTarget", "gosaVacationMessage");
58   var $objectclasses= array("gosaMailAccount");
59   var $CopyPasteVars          = array("quotaUsage","imapacl");
61   var $multiple_support = TRUE;
63   function mailgroup (&$config, $dn= NULL, $ui= NULL)
64   {
65     /* Initialise all available attributes ... if possible
66      */
67     plugin::plugin($config, $dn);
68     $this->orig_cn = $this->cn;
70     /* Set mailMethod to the one defined in gosa.conf 
71      */
72     if (isset($this->config->current['MAILMETHOD'])){
73       $this->mmethod= $this->config->current['MAILMETHOD'];
74     }
76     /* Check if selected mail method exists 
77      */
78     $cls = get_correct_class_name("mailMethod$this->mmethod");
79     if ($cls && class_exists($cls)){
80       $this->method= $cls;
81     } else {
82       msg_dialog::display(_("Configuration error"), sprintf(_("Cannot locate mail method '%s'!"), $this->mmethod), ERROR_DIALOG);
83     }
85     /* Load Mailserver  
86      */
87     if(isset($this->attrs['gosaMailServer'][0])){
88       $this->gosaMailServer =  $this->attrs['gosaMailServer'][0];
89     }
91     /* Convert cn to uid in case of existing entry
92      */
93     if (isset($this->attrs['cn'][0])){
94       $this->uid= $this->attrs['cn'][0];
95     }
97     /* Get folder type */
98     if(isset($this->config->current['MAILMETHOD'])&&preg_match("/olab/i",$this->config->current['MAILMETHOD'])){
99       if(isset($this->attrs['kolabFolderType'])){
100         $tmp = split("\.",$this->attrs['kolabFolderType'][0]);
101         $this->kolabFolderTypeType = $tmp[0];
102         $this->kolabFolderTypeSubType = $tmp[1];
103       }
104     }
106     /* If this isn't a new mailgroup, read all required data from ldap
107      */
108     if (($dn != "new")&&($dn !== NULL)){
110       /* Load attributes which represent multiple entries  
111        */
112       foreach (array("gosaMailAlternateAddress", "gosaMailForwardingAddress") as $val){
113         $this->$val = array();
114         if (isset($this->attrs["$val"]["count"])){
115           for ($i= 0; $i<$this->attrs["$val"]["count"]; $i++){
116             array_push($this->$val, $this->attrs["$val"][$i]);
117           }
118         }
119       }
121       /* Only do IMAP actions if gosaMailServer attribute is set 
122        */
123       if (isset ($this->attrs["gosaMailServer"][0])){
125         /* Create new instance of our defined mailclass
126          */
127         $method= new $this->method($this->config);
128         if ($method->connect($this->attrs["gosaMailServer"][0])){
130           /* If we do NOT use kolab or equal methods, 
131              read imap the acls from the mail method class.
132              They will be merged later with the ldap specified acls.
133            */
134           if(!preg_match("/olab/i",$this->mmethod) && !empty($this->mmethod)){
135             $this->imapacl=  $method->getSharedFolderPermissions($this->uid);
137             /* Need to filter what a member acl could be... */
138             $vote= array();
139             $peak= 0;
140             $leader= "";
141             foreach ($this->imapacl as $user => $acl){
143               if ($user != "anyone" ){
144                 if (!isset($vote[$acl])){
145                   $vote[$acl]= 1;
146                 } else {
147                   $vote[$acl]++;
148                 }
149                 if ($vote[$acl] > $peak){
150                   $leader= $acl;
151                   $peek= $vote[$acl];
152                 }
153               }
154             }
155             /* Highest count wins as %members%, remove all members
156                with the same acl */
157             if(!empty($leader)){
158               $this->imapacl['%members%']= $leader;
159             }
160             foreach ($this->imapacl as $user => $acl){
161               if ($this->acl == $leader && in_array($user, $this->attrs['memberUid'])){
162                 unset($this->imapacl[$user]);
163               }
164             }
165           }
167           /* Adapt attributes if needed */
168           $method->fixAttributesOnLoad($this);
170           /*  get Quota */
171           $quota= $method->getQuota($this->uid);
173           /* Update quota values */
174           if(is_array($quota)){
175             if ($quota['gosaMailQuota'] == 2147483647){
176               $this->quotaUsage= "";
177               $this->gosaMailQuota= "";
178             } else {
179               $this->quotaUsage= $quota['quotaUsage'];
180               $this->gosaMailQuota= $quota['gosaMailQuota'];
181             }
182           }else{
183             $this->quotaUsage     = "";
184             $this->gosaMailQuota  = "";
185           }
186           $method->disconnect();
187         }   // ENDE $method->connect($this->attrs["gosaMailServer"][0])){
188       }   // ENDE gosaMailServer
189     }   // ENDE dn != "new"
192     /* Get global filter config */
193     if (!session::is_set("gmailfilter")){
194       $ui= get_userinfo();
195       $base= get_base_from_people($ui->dn);
196       $gmailfilter= array( "depselect"       => $base,
197           "muser"            => "",
198           "regex"           => "*");
199       session::set("gmailfilter", $gmailfilter);
200     }
202     /* Load permissions */
203     $tmp = array();
204     $ldap = $this->config->get_ldap_link();
206     /* Read acls  from ldap and merge them with
207      *  acls read from mail method.
208      */
209     if (isset($this->attrs['acl'])){
211       for ($i= 0; $i<$this->attrs['acl']['count']; $i++){
212         list($user, $permission)= split(' ', $this->attrs['acl'][$i]);
214         /* Add to list */
215         $this->imapacl[$user]= $permission;
217         /* Get all user permissions sorted by acl, to detect the most used acl
218            This acl is then used for %members%
219          */
220         if ($user != "anyone" && $user != "%members%"){
221           $tmp[$permission][] = $user;
222         }
224         /* There is an entry in $this->imapacl like this this ... 
225            $this->attrs['imapacl']['anyone'] = "p";
226            $this->attrs['imapacl']['%members%'] = "lprs";
227            $this->attrs['imapacl'][''] = ""; <------ This is used to diplay an empty 
228            Field for special acls in our template.
229            If there is at least one special acl in out imapacl,
230            we don't need this entry anymore, because it is already displayed. 
231          */
232         if ($user != "anyone" && $user != "%members%"){
233           unset($this->imapacl['']);
234         }
235       }
236     }
238     /**
239      * Detect group members which use the same acl
240      *  as used for %members% and remove them.
241      **/
243     /* In this section we detect which acl is the most used.
244        This will be used as %members% acl.
245      */
246     $tmp2 = array(); 
247     foreach($tmp as $acl => $user){
248       $tmp2[count($tmp[$acl])]=$acl;
249     }
250     /* Most used at last 
251      */
252     ksort($tmp2);      
254     /* Assign last (most used acl) to %members% acl 
255      */
256     $str = array_pop($tmp2);
257     if(!empty($str)) {
258       $this->imapacl['%members%']=$str;
259     }
260     if(!isset($this->imapacl['%members%'])){
261       $this->imapacl['%members%'] = "lrspw";
262     }
265     /* Open ldap connection 
266      */
267     $ldap = $this->config->get_ldap_link();
268     $ldap->cd($this->config->current['BASE']);
270     /* Remove those users, that use %members% acl && are member of this group. */
271     foreach($this->imapacl as $mail => $permission){
272       $ldap->search("(&(objectClass=person)(|(mail=".$mail.")(uid=".$mail.")))",array("uid"));
273       $atr = $ldap->fetch();
274       if((isset($this->attrs['memberUid'])) && (is_array($this->attrs['memberUid']))){
275         if((isset($atr['uid'][0]))&&(in_array($atr['uid'][0],$this->attrs['memberUid']))&&($permission == $this->imapacl['%members%'])){
276           unset($this->imapacl[$mail]);
277         }
278       }
279     }
281     /**
282      * ENDE: Detect group member with same acl and replace them with %members%
283      **/
284     $this->indexed_user = array("%members%","anyone");
286     /* Append an empty entry, for special acl handling */
287     if(count($this->imapacl)==2){
288       $this->imapacl[''] ="lrsw";
289       $this->indexed_user[] = '';
290     }
292     /* Load Mailserver
293      */
294     if(isset($this->attrs['gosaMailServer'][0])){
295       $this->gosaMailServer =  $this->attrs['gosaMailServer'][0];
296     }
297     /* Fill translations */
298     $this->perms["lrsw"]= _("read");
299     $this->perms["lrswp"]= _("post");
300     $this->perms["p"]= _("external post");
301     $this->perms["lrswip"]= _("append");
302     $this->perms["lrswipcd"]= _("write");
303     $this->perms["lrswipcda"]= _("admin");
304     $this->perms[""]= _("none");
305   }
309   function execute()
310   {
311     /* Call parent execute */
312     //plugin::execute();
313     $display = "";
315     /* Log view */
316     if($this->is_account && !$this->view_logged){
317       $this->view_logged = TRUE;
318       new log("view","groups/".get_class($this),$this->dn);
319     }
321     /* Load templating engine */
322     $smarty= get_smarty();
324     /* Assign acls */
325     $tmp = $this->plInfo();
326     foreach($tmp['plProvidedAcls'] as $name => $translation) {
327       $smarty->assign($name."ACL",$this->getacl($name));
328     }
330     if (session::get('js')==FALSE){
331       $smarty->assign("javascript", "false");
332     } else {
333       $smarty->assign("javascript", "true");
334     }
336     /* Handle actions should not be done, when 
337      *  editing multiple entries at once. e.g. account state
338      */ 
339     if(!$this->multiple_support_active){
341       /* Do we need to flip is_account state? */
342       if(isset($_POST['modify_state'])){
343         if($this->is_account && $this->acl_is_removeable()){
344           $this->is_account= FALSE;
345         }elseif(!$this->is_account && $this->acl_is_createable()){
346           $this->is_account= TRUE;
347         }
348       }
350       $display = "";
352       /* Do we represent a valid account? */
353       if (!$this->is_account && $this->parent === NULL){
355         $display.= "<img alt=\"\" src=\"images/small-error.png\" align=middle>&nbsp;<b>".msgPool::noValidExtension(_("mail"))."</b>";
356         return ($display);
357       }
359       /* Show tab dialog headers */
360       $display= "";
361       if ($this->parent !== NULL){
362         if ($this->is_account){
363           $display.= $this->show_disable_header(_("Remove mail account"),
364               msgPool::featuresEnabled(_("mail")));
365         } else {
366           $display.= $this->show_enable_header(_("Create mail account"),
367               msgPool::featuresDisabled(_("mail")));
369           /* Show checkbox that allows us to remove imap entry too*/
370           if($this->initially_was_account){
371             $c = "";
372             if($this->remove_folder_from_imap){
373               $c= " checked ";
374             }
375             $display .= "<h2>Shared folder delete options</h2>
376               <input class='center' type='checkbox' name='remove_folder_from_imap' value='1' ".$c."
377               title='"._("Remove shared folder from mail server database when entry gets removed in LDAP")."'>";
378             $display .= _("Remove the shared folder and all its contents after saving this account");
379           }
380           return ($display);
381         }
382       }
383     }
385     /* Add ACL? */
386     if($this->acl_is_writeable("acl")){
387       foreach ($this->indexed_user as $nr => $user){
388         if (isset($_POST["add_$nr"])){
389           $this->imapacl[""]= "l";
390         }
391         if (isset($_POST["del_$nr"])){
392           unset ($this->imapacl[$user]);
393         }
394       }
395     }
397     /* Trigger forward add dialog? */
398     if($this->acl_is_writeable("gosaMailForwardingAddress")){
399       if (isset($_POST['add_local_forwarder'])){
400         $this->forward_dialog= TRUE;
401         $this->dialog= TRUE;
402       }
403     }
405     /* Cancel forward add dialog? */
406     if($this->acl_is_writeable("gosaMailForwardingAddress")){
407       if (isset($_POST['add_locals_cancel'])){
408         $this->forward_dialog= FALSE;
409         $this->dialog= FALSE;
410       }
411     }
413     /* Finished adding of locals? */
414     if ((isset($_POST['add_locals_finish'])) && ($this->acl_is_writeable("gosaMailForwardingAddress"))) {
415       if (count ($_POST['local_list']) && $this->acl_is_writeable("gosaMailForwardingAddress")){
417         /* Walk through list of forwarders, ignore own addresses */
418         foreach ($_POST['local_list'] as $val){
419           if (!in_array ($val, $this->gosaMailAlternateAddress) &&
420               $val != $this->mail){
422             $this->addForwarder($val);
423           }
424         }
425       }
426       $this->forward_dialog= FALSE;
427       $this->dialog= FALSE;
428     }
430     /* Add forward email addresses */
431     if ((isset($_POST['add_forwarder'])) && ($this->acl_is_writeable("gosaMailForwardingAddress"))){
432       if ($_POST['forward_address'] != ""){
434         /* Valid email address specified? */
435         $address= $_POST['forward_address'];
436         if (!tests::is_email($address)){
437           msg_dialog::display(_("Error"), msgPool::invalid(_("forward address")), ERROR_DIALOG);
438         } elseif ($address == $this->mail
439             || in_array($address, $this->gosaMailAlternateAddress)) {
441           msg_dialog::display(_("Error"), _("Cannot forward to users own mail address!"), ERROR_DIALOG);
443         } else {
445           /* Add it */
446           if ($this->acl_is_writeable("gosaMailForwardingAddress")){
447             $this->addForwarder ($address);
448           }
450         }
451       }
452     }
454     /* Delete forward email addresses */
455     if (isset($_POST['delete_forwarder']) && ($this->acl_is_writeable("gosaMailForwardingAddress"))){
456       if (count($_POST['forwarder_list'])&& $this->acl_is_writeable("gosaMailForwardingAddress")){
458         $this->delForwarder ($_POST['forwarder_list']);
459       }
460     }
462     /* Add alternate email addresses */
463     if (isset($_POST['add_alternate'])){
464       if ($_POST['alternate_address'] != "" && $this->acl_is_writeable("gosaMailAlternateAddress")){
466         if (!tests::is_email($_POST['alternate_address'])){
467           msg_dialog::display(_("Error"),msgPool::invalid(_("Alternate address")), ERROR_DIALOG);
469         } elseif (($user= $this->addAlternate ($_POST['alternate_address'])) != ""){
470           $ui= get_userinfo();
471           if ($user != $ui->username){
472           msg_dialog::display(_("Error"),msgPool::duplicated(_("Mail address")), ERROR_DIALOG);
473           }
474         }
475       }
476     }
478     /* Delete alternate email addresses */
479     if($this->acl_is_writeable("gosaMailAlternateAddress")){
480       if (isset($_POST['delete_alternate']) && isset ($_POST['alternates_list'])){
481         if (count($_POST['alternates_list']) && $this->acl_is_writeable("gosaMailAlternateAddress")){
482           $this->delAlternate ($_POST['alternates_list']);
483         }
484       }
485     }
487     /* Show forward add dialog */
488     if ($this->forward_dialog){
489       $ldap= $this->config->get_ldap_link();
491       /* Save data */
492       $gmailfilter= session::get("gmailfilter");
493       foreach( array("depselect", "muser", "regex") as $type){
494         if (isset($_POST[$type])){
495           $gmailfilter[$type]= $_POST[$type];
496         }
497       }
498       if (isset($_GET['search'])){
499         $s= mb_substr($_GET['search'], 0, 1, "UTF8")."*";
500         if ($s == "**"){
501           $s= "*";
502         }
503         $gmailfilter['regex']= $s;
504       }
505       session::set("gmailfilter", $gmailfilter);
507       /* Get actual list */
508       $mailusers= array ();
509       if ($gmailfilter['regex'] != '*' && $gmailfilter['regex'] != ""){
510         $regex= $gmailfilter['regex'];
511         $filter= "(|(mail=$regex)(gosaMailAlternateAddress=$regex))";
512       } else {
513         $filter= "";
514       }
515       if ($gmailfilter['muser'] != ""){
516         $user= $gmailfilter['muser'];
517         $filter= "$filter(|(uid=$user)(cn=$user)(givenName=$user)(sn=$user))";
518       }
520       /* Add already present people to the filter */
521       $exclude= "";
522       foreach ($this->gosaMailForwardingAddress as $mail){
523         $exclude.= "(mail=$mail)";
524       }
525       if ($exclude != ""){
526         $filter.= "(!(|$exclude))";
527       }
529       $res= get_list("(&(objectClass=gosaMailAccount)$filter)", "users", $gmailfilter['depselect'],
530                      array("sn", "mail", "givenName"), GL_SUBSEARCH | GL_SIZELIMIT);
531       $ldap->cd($gmailfilter['depselect']);
532       $ldap->search ("(&(objectClass=gosaMailAccount)$filter)", array("sn", "mail", "givenName"));
533       error_reporting (0);
534       while ($attrs= $ldap->fetch()){
535         if(preg_match('/%/', $attrs['mail'][0])){
536           continue;
537         }
538         $name= $this->make_name($attrs);
539         $mailusers[$attrs['mail'][0]]= $name."&lt;".
540           $attrs['mail'][0]."&gt;";
541       }
542       error_reporting (E_ALL | E_STRICT);
543       natcasesort ($mailusers);
544       reset ($mailusers);
546       /* Show dialog */
547       $smarty->assign("search_image", get_template_path('images/lists/search.png'));
548       $smarty->assign("usearch_image", get_template_path('images/lists/search-user.png'));
549       $smarty->assign("tree_image", get_template_path('images/lists/search-subtree.png'));
550       $smarty->assign("infoimage", get_template_path('images/info.png'));
551       $smarty->assign("launchimage", get_template_path('images/lists/action.png'));
552       $smarty->assign("mailusers", $mailusers);
553       $smarty->assign("deplist", $this->config->idepartments);
554       $smarty->assign("apply", apply_filter());
555       $smarty->assign("alphabet", generate_alphabet());
556       $smarty->assign("hint", print_sizelimit_warning());
557       foreach( array("depselect", "muser", "regex") as $type){
558         $smarty->assign("$type", $gmailfilter[$type]);
559       }
560       $smarty->assign("hint", print_sizelimit_warning());
561       $display.= $smarty->fetch (get_template_path('mail_locals.tpl', TRUE, dirname(__FILE__)));
562       return ($display);
563     }
565     /* Assemble normal permissions */
566     if (isset($this->imapacl['anyone'])){
567       $smarty->assign("default_permissions", $this->imapacl['anyone']);
568     }
569     $smarty->assign("member_permissions", "lrsp");
570     if (isset($this->imapacl['%members%'])){
571       $smarty->assign("member_permissions", $this->imapacl['%members%']);
572     }
574     /* Assemble extra attributes */
575     $perm= $this->getacl( "acl");
576     $tmp= "";
577     $nr= 0;
578     $count= count($this->imapacl);
579     $this->indexed_user= array();
580     $this->indexed_acl= array();
581     foreach($this->imapacl as $user => $acl){
583       /* Add additional acl settings */
584       if ($user != "anyone" && $user != "%members%"){
586         $Dis  = "";
587         if(!preg_match("/w/",$perm)){
588           $Dis = " disabled ";
589         }
590   
591         /* Reset given Acls to ensure that nobody can read username and acls if not allwoed */
592         if(!preg_match("/r/",$perm)){
593           $user = "";
594           $nr   = "none";
595           $key  = "none";  
596         }
598         $tmp.= "<tr>  
599                  <td>
600                   <input name=\"user_$nr\" size=20 maxlength=60 value=\"$user\" ".$Dis.">
601                  </td>
602                  <td>
603                  <select size=\"1\" name=\"perm_$nr\" ".$Dis.">";
605         /* Add acl options for this additional acl setting */
606         if(preg_match("/r/",$perm)){
607           foreach ($this->perms as $key => $value){
608             if ($acl == $key){
609               $tmp.= "<option value=\"$key\" selected>$value</option>";
610             } else {
611               $tmp.= "<option value=\"$key\">$value</option>";
612             }
613           }
614         }
615         $tmp.= "</select>&nbsp;";
618         
619         if ($nr == $count - 1){
620           if($this->acl_is_writeable("acl")){
621             $tmp.= "<input type=submit value=\""._("Add")."\" ".
622               "name=\"add_$nr\" >";
623           }
624         }
625         if ($count > 3){
626           if($this->acl_is_writeable("acl")){
627             $tmp.= "<input type=submit value=\""._("Remove")."\" ".
628               "name=\"del_$nr\" ></td></tr>";        
629           }
630         }
631       }
632       $this->indexed_user[$nr]= $user;
633       $this->indexed_acl[$nr++]= $acl;
634     }
635     $smarty->assign("plusattributes", $tmp);
637     /* Show main page */
638     $mailserver= array();
639     $ui = get_userinfo();
640     foreach ($this->config->data['SERVERS']['IMAP'] as $key => $val){
641       if(!preg_match("/r/",$ui->get_category_permissions($val['server_dn'],"server"))) continue;
642       $mailserver[]= $key;
643     }
645     /* Append currently selected server if we are not allowed to view it. 
646      */
647     if(isset($this->config->data['SERVERS']['IMAP'][$this->gosaMailServer]) && 
648         !in_array($this->gosaMailServer,$mailserver)){
649       $mailserver[] = $this->gosaMailServer;
650     }
652     $smarty->assign("mailServers", $mailserver);
653     foreach(array("gosaMailServer", "gosaMailQuota", "perms", "mail",
654           "gosaMailAlternateAddress", "gosaMailForwardingAddress") as $val){
655       $smarty->assign("$val", $this->$val);
656     }
657     if (is_numeric($this->gosaMailQuota) && $this->gosaMailQuota != 0){
658       if($this->acl_is_readable("gosaMailQuota")){
659         $smarty->assign("quotausage", progressbar(round(($this->quotaUsage * 100)/ $this->gosaMailQuota),100,15,true));
660         $smarty->assign("quotadefined", "true");
661       }else{
662         $smarty->assign("quotadefined", "true");
663         $smarty->assign("quotausage", "-");
664       }
665     } else {
666       $smarty->assign("quotadefined", "false");
667     }
669     if(isset($this->config->current['MAILMETHOD'])&&preg_match("/olab/i",$this->config->current['MAILMETHOD'])){
671       $smarty->assign("kolab", TRUE);
672       $smarty->assign("JS",session::get('js'));
673       $smarty->assign("kolabFolderTypeTypes",    array (   ''      => _('Unspecified'),  'mail' => _('Mails'),
674                                                             'task'  => _('Tasks') ,       'journal' => _('Journals'),
675                                                             'calendar' => _('Calendar'),       'contact' => _('Contacts'), 
676                                                             'note'  => _('Notes')));
677       if($this->kolabFolderTypeType == "mail"){
678         $smarty->assign("kolabFolderTypeSubTypes", array(    
679               ''          => _('Unspecified'),  'inbox'     => _("Inbox")   , 
680               'drafts'    => _("Drafts"),       'sentitems' => _("Sent items"),
681               'junkemail' => _("Junk mail")));
682       }else{
683         $smarty->assign("kolabFolderTypeSubTypes", array(  'default' => _("Default")));
684       }
685       $smarty->assign("kolabFolderTypeType",     $this->kolabFolderTypeType);
686       $smarty->assign("kolabFolderTypeSubType",  $this->kolabFolderTypeSubType);
687     }else{
688       $smarty->assign("kolab", FALSE);
689     }
691     /* Multiple support handling */
692     foreach($this->attributes as $attr){
693       if(in_array($attr,$this->multi_boxes)){
694         $smarty->assign("use_".$attr,TRUE);
695       }else{
696         $smarty->assign("use_".$attr,FALSE);
697       }
698     }
700     /* Multiple support handling */
701     foreach(array("kolabFolderType") as $attr){
702       if(in_array($attr,$this->multi_boxes)){
703         $smarty->assign("use_".$attr,TRUE);
704       }else{
705         $smarty->assign("use_".$attr,FALSE);
706       }
707     }
709     $smarty->assign("Forward_all",$this->gosaMailForwardingAddress);
710     $smarty->assign("Forward_some",$this->gosaMailForwardingAddress_Some);
712     $smarty->assign("multiple_support",$this->multiple_support_active);
713     $display.= $smarty->fetch (get_template_path('mail.tpl', TRUE, dirname(__FILE__)));
714     return ($display);
715   }
718   /* remove object from parent */
719   function remove_from_parent()
720   {
721     if(!$this->initially_was_account){
722       return;
723     }
724   
725     /* Added these ObjectClass and Attributes, because they were not 
726        removed correctly, only in case of kolab ... 
727      */
728     if(isset($this->config->current['MAILMETHOD'])&&preg_match("/olab/i",$this->config->current['MAILMETHOD'])){
729       $this->attributes[]="acl";
730       $this->objectclasses[] = "kolabSharedFolder";
731     }
732     /* include global link_info */
733     $ldap= $this->config->get_ldap_link();
735     /* Remove and write to LDAP */
736     plugin::remove_from_parent();
738     /* Zero arrays */
739     $this->attrs['gosaMailAlternateAddress']= array();
740     $this->attrs['gosaMailForwardingAddress']= array();
741     $this->attrs['gosaSharedFolderTarget']= array();
743     /* Connect to IMAP server for account deletion */
744     if ($this->initially_was_account){
745  
746       $method= new $this->method($this->config);
747       $method->fixAttributesOnRemove($this);
748       if ($method->connect($this->gosaMailServer) && $this->remove_folder_from_imap){
750         /* Remove account from IMAP server */
751         $method->deleteMailbox($this->uid);
752         $method->disconnect();
753       }
754     }
755     /* Keep uid */
756     unset ($this->attrs['uid']);
758     $ldap->cd($this->dn);
759     $ldap->modify ($this->attrs); 
760     if (!$ldap->success()){
761       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
762     }
765     new log("remove","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
767     /* Optionally execute a command after we're done */
768     $this->handle_post_events("remove");
769   }
772   /* Save data to object */
773   function save_object()
774   {
776     /* Add special kolab attributes */    
777     if(isset($this->config->current['MAILMETHOD'])&&preg_match("/olab/i",$this->config->current['MAILMETHOD'])){
778       if(isset($_POST['kolabFolderTypeType']) && $this->acl_is_writeable("kolabFolderType")){
779         $this->kolabFolderTypeType = get_post("kolabFolderTypeType");
780         $this->kolabFolderTypeSubType = get_post("kolabFolderTypeSubType");
781       }
782     }
783   
784     /* Check if user wants to remove the shared folder from imap too */
785     if($this->initially_was_account && !$this->is_account){
786       if(isset($_POST['remove_folder_from_imap'])){
787         $this->remove_folder_from_imap = true;
788       }else{
789         $this->remove_folder_from_imap = false;
790       }
791     }
793     /* Assemble mail delivery mode
794        The mode field in ldap consists of values between braces, this must
795        be called when 'mail' is set, because checkboxes may not be set when
796        we're in some other dialog.
798        Example for gosaMailDeliveryMode [LR        ]
799 L: Local delivery
800 R: Reject when exceeding mailsize limit
801 S: Use spam filter
802 V: Use vacation message
803 C: Use custom sieve script
804 I: Only insider delivery */
805     if (isset($_POST['mailedit'])){
807       plugin::save_object();
809       $tmp= preg_replace("/[^a-z]/i","",$this->gosaMailDeliveryMode);
811       /* Handle delivery flags */
812       if($this->acl_is_writeable("gosaMailDeliveryModeL")){
813         if(!preg_match("/L/",$tmp) && !isset($_POST['drop_own_mails'])){
814           $tmp.="L";
815         }elseif(preg_match("/L/",$tmp) && isset($_POST['drop_own_mails'])){
816           $tmp = preg_replace("/L/","",$tmp);
817         }
818       }
820       $opts = array(
821           "R"   => "use_mailsize_limit",
822           "S"   => "use_spam_filter",
823           "V"   => "use_vacation",
824           "C"   => "own_script",
825           "I"   => "only_local");
827       foreach($opts as $flag => $post){
828         if($this->acl_is_writeable("gosaMailDeliveryMode".$flag)){
829           if(!preg_match("/".$flag."/",$tmp) && isset($_POST[$post])){
830             $tmp.= $flag;
831           }elseif(preg_match("/".$flag."/",$tmp) && !isset($_POST[$post])){
832             $tmp = preg_replace("/".$flag."/","",$tmp);
833           }
834         }
835       }
837       $tmp= "[$tmp]";
838       if ($this->gosaMailDeliveryMode != $tmp){
839         $this->is_modified= TRUE;
840       }
841       $this->gosaMailDeliveryMode= $tmp;
843       /* Collect data and re-assign it to the imapacl array */
844       if ($this->acl_is_writeable("acl")){
845         $this->imapacl= array();
846         $this->imapacl['%members%']= $_POST['member_permissions'];
847         $this->imapacl['anyone']= $_POST['default_permissions'];
848         foreach ($this->indexed_user as $nr => $user){
849           if (!isset($_POST["user_$nr"])){
850             continue;
851           }
852           if ($_POST["user_$nr"] != $user ||
853               $_POST["perm_$nr"] != $this->indexed_acl[$nr]){
854             $this->is_modified= TRUE;
855           }
856           $this->imapacl[$_POST["user_$nr"]]= $_POST["perm_$nr"];
857         }
858       }
859     }
861   }
864   /* Save data to LDAP, depending on is_account we save or delete */
865   function save()
866   {
867     $ldap= $this->config->get_ldap_link();
868     $ldap->cd($this->config->current['BASE']);
870     /* Call parents save to prepare $this->attrs */
871     plugin::save();
873     /* Save arrays */
874     $this->attrs['gosaMailAlternateAddress']  = $this->gosaMailAlternateAddress;
875     $this->attrs['gosaMailForwardingAddress'] = $this->gosaMailForwardingAddress;
876     $this->attrs['gosaSharedFolderTarget']    = "share+".$this->uid;
877     $this->attrs['acl']= array();
879     /* Prepare Mail server attribute */
880     if(preg_match("/olab/i",$this->mmethod)){
881       if (empty($this->gosaMailServer)||is_array($this->gosaMailServer)){
882         if(isset($this->attrs['gosaMailServer'][0])){
883           $this->gosaMailServer = $this->attrs['gosaMailServer'][0];
884         }
885       }
886     }  
887  /* Exchange '%member%' pseudo entry */
888     $memberacl= $this->imapacl['%members%'];
889     foreach ($this->members as $user){
890       if (!isset($this->imapacl[$user])){
891         $this->imapacl[$user]= $memberacl;
892       }
893     }
895     /* Prepare kolab attributes to be written  */
896     if(preg_match("/olab/i",$this->mmethod)){
897       if(!empty($this->kolabFolderTypeType)){
898         $this->attrs['kolabFolderType'] = $this->kolabFolderTypeType.".".$this->kolabFolderTypeSubType;
899       }else{
900         $this->attrs['kolabFolderType'] = array();
901       }
902     }
904     /* Get naming attribute for mail accounts */
905     $tmp = new $this->method($this->config);
906     $uattrib = $tmp->uattrib;
908     /* Create ACL array
909        What is done here.
911        1.  Do not write acl entries for empty entries.
912        2.  Check if given user is a valid GOsa user.
913        - If he is one, check if he has a valid mail extension
914        -If this is true, add the user to the ACL entry.
915        -If this is NOT true, skip ACL entries for this user.
916        - He is not a GOsa Account, so write the ACL. (Manually entered ACL)
917        3. In case of "olab" mail method, remove the entry from the $this->imapacl array
918        because the kolab deamon will set the acls for us.
920      */
921     $acls_set_for = array();
922     foreach ($this->imapacl as $user => $acl){
924       /* Skip empty entries */
925       if (empty($user) || $user == ""){
926         unset($this->imapacl[$user]);
927       }
929       /* Skip placeholder */
930       if (empty($user) || $user == "" || preg_match("/%members%/",$user)){
931         continue;
932       }
934       /* Check if your is a real GOsa user
935        * If user is a real GOsa user but do not have an email address - SKIP adding acls
936        * If user is a real GOsa user with an email address - add acls
937        */
938       $ldap->search("(&(objectClass=person)(|(uid=".$user.")(mail=".$user.")))",array("mail","uid"));
939       if($ldap->count()){
941         /* Has the user a valid mail account? */
942         $attrs = $ldap->fetch();
943         if(isset($attrs['mail'][0])){
945           $name = $attrs[$uattrib][0];
947           /* Do not overwrite manually set ACLs with group member acls 
948           */
949           if(!in_array($name,$acls_set_for)){
950             $this->attrs['acl'][]= $name." ".$acl;
951           }
952           $acls_set_for[] = $name;
953       
955           /* Do not write imap acl directly i nkolab mode, let the kolab deamon do this. */
956           unset($this->imapacl[$user]);
957           if(!preg_match("/olab/i",$this->mmethod)){
958             $this->imapacl[$name] = $acl;
959           }
961         }else{
963           /* User is a valid GOsa account, but he has no mail extension. Skip ACLs */
964           unset($this->imapacl[$user]);
965         }
966       }else{
968         /* Seems to be a manually a added acl
969          * Write this acl.
970          */
972         /* Do not overwrite manually set ACLs with group member acls 
973          */
974         if(!in_array($user,$acls_set_for)){
975           $this->attrs['acl'][]= $user." ".$acl;
976           $acls_set_for[] = $user;
977         }
979         /* In case of kolab methods, let the deamon add the imap acls */
980         if(preg_match("/olab/i",$this->mmethod)){
981           unset($this->imapacl[$user]);
982         }
983       }
984     }
986     /* Handle mail method actions, set acls, quota ...*/
987     if ((!$this->is_template)&&(!empty($this->gosaMailServer))){
988       $method= new $this->method($this->config);
989       $method->fixAttributesOnStore($this);
990       if (($method->connect($this->gosaMailServer))){
991         $method->updateMailbox($this->uid);
992         $method->setQuota($this->uid, $this->gosaMailQuota);
994         /* Only write imap acls directly if we are not
995          *  using a kolab like mail method.
996          */
997         if(!preg_match("/olab/i",$this->mmethod)){
998           $method->setSharedFolderPermissions($this->uid, $this->imapacl);
999         }
1000         $method->disconnect();
1001       }
1002     }
1004     /* Save data to LDAP */
1005     $ldap->cd($this->dn);
1006     $this->cleanup();
1007     $ldap->modify ($this->attrs); 
1008     if (!$ldap->success()){
1009       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
1010     }
1011     
1012     if($this->initially_was_account){
1013       new log("modify","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1014     }else{
1015       new log("create","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());  
1016     }
1017     
1019     /* Optionally execute a command after we're done */
1020     if ($this->initially_was_account == $this->is_account){
1021       if ($this->is_modified){
1022         $this->handle_post_events("modify");
1023       }
1024     } else {
1025       $this->handle_post_events("add");
1026     }
1027   }
1031   /* Check formular input */
1032   function check()
1033   {
1034     $ldap= $this->config->get_ldap_link();
1036     /* Call common method to give check the hook */
1037     $message= plugin::check();
1039     if(!$this->is_account) return array();
1040     
1041     //$message[] = $str;      
1043     /* must: mail */
1044     if ($this->mail == ""){
1045       $message[]= msgPool::required(_("Mail address"));
1046     }
1047     if (!tests::is_email($this->mail)){
1048       $message[]= msgPool::invalid(_("Mail address"),"","",_("your-name@your-domain.com"));
1049     }
1050     $ldap->cd($this->config->current['BASE']);
1051     $ldap->search ("(&(!(objectClass=gosaUserTemplate))(objectClass=gosaMailAccount)(|(mail=".$this->mail.")(gosaMailAlternateAddress=".
1052         $this->mail."))(!(uid=".$this->orig_cn."))(!(cn=".$this->orig_cn.")))");
1053     if ($ldap->count() != 0){
1054       $message[]= msgPool::duplicated(_("Mail address"));
1055     }
1056   
1057     /* Check quota */
1058     if ($this->gosaMailQuota != '' && $this->acl_is_writeable("gosaMailQuota")){
1059       if (!is_numeric($this->gosaMailQuota)) {
1060         $message[]= msgPool::invalid(_("Quota size"),$this->gosaMailQuota,"/[0-9]/");
1061       } else {
1062         $this->gosaMailQuota= (int) $this->gosaMailQuota;
1063       }
1064     }
1066     /* Check rejectsize for integer */
1067     if ($this->gosaMailMaxSize != '' && $this->acl_is_writeable("gosaMailQuota")){
1068       if (!is_numeric($this->gosaMailMaxSize)){
1069         $message[]= msgPool::invalid(_("Mail max size"));
1070       } else {
1071         $this->gosaMailMaxSize= (int) $this->gosaMailMaxSize;
1072       }
1073     }
1075     /* Need gosaMailMaxSize if use_mailsize_limit is checked */
1076     if (is_integer(strpos($this->gosaMailDeliveryMode, "reject")) && $this->gosaMailMaxSize == ""){
1077       $message[]= _("You need to set the maximum mail size in order to reject anything.");
1078     }
1080     if(ord($this->imapacl['anyone'][0])==194){
1081       $message[] = _("Please choose valid permission settings. Default permission can't be emtpy.");
1082     }
1084     if(empty($this->gosaMailServer)){
1085       $message[] = msgPool::required(_("Mail server"));
1086     }
1088     return ($message);
1089   }
1091   /* Adapt from template, using 'dn' */
1092   function adapt_from_template($dn, $skip= array())
1093   {
1094     plugin::adapt_from_template($dn, $skip);
1096     foreach (array("gosaMailAlternateAddress", "gosaMailForwardingAddress") as $val){
1097  
1098       if (in_array($val, $skip)){
1099         continue;
1100       }
1102       $this->$val= array();
1103       if (isset($this->attrs["$val"]["count"])){
1104         for ($i= 0; $i<$this->attrs["$val"]["count"]; $i++){
1105           $value= $this->attrs["$val"][$i];
1106           foreach (array("sn", "givenName", "uid") as $repl){
1107             if (preg_match("/%$repl/i", $value)){
1108               $value= preg_replace ("/%$repl/i", $this->parent->$repl, $value);
1109             }
1110           }
1111           array_push($this->$val, $value);
1112         }
1113       }
1114     }
1115   }
1117   /* Add entry to forwarder list */
1118   function addForwarder($address)
1119   {
1120     $this->gosaMailForwardingAddress[]= $address;
1121     $this->gosaMailForwardingAddress= array_unique($this->gosaMailForwardingAddress);
1123     /* Update multiple edit values too */
1124     if($this->multiple_support_active){
1125       $this->gosaMailForwardingAddress_Some= 
1126         array_remove_entries (array($address),$this->gosaMailForwardingAddress_Some);
1127     }
1129     sort ($this->gosaMailForwardingAddress);
1130     reset ($this->gosaMailForwardingAddress);
1131     $this->is_modified= TRUE;
1132   }
1134   /* Remove list of addresses from forwarder list */
1135   function delForwarder($addresses)
1136   {
1137     $this->gosaMailForwardingAddress= array_remove_entries ($addresses,
1138         $this->gosaMailForwardingAddress);
1140     /* Update multiple edit values too */
1141     if($this->multiple_support_active){
1142       $this->gosaMailForwardingAddress_Some = array_remove_entries ($addresses,
1143           $this->gosaMailForwardingAddress_Some);
1144     }
1145     $this->is_modified= TRUE;
1146   }
1150   function addAlternate($address)
1151   {
1152     $ldap= $this->config->get_ldap_link();
1154     $address= strtolower($address);
1156     /* Is this address already assigned in LDAP? */
1157     $ldap->cd ($this->config->current['BASE']);
1158     $ldap->search ("(&(objectClass=gosaMailAccount)(|(mail=$address)".
1159         "(gosaMailAlternateAddress=$address)))");
1161     if ($ldap->count() > 0){
1162       $attrs= $ldap->fetch ();
1163       return ($attrs["uid"][0]);
1164     }
1166     /* Add to list of alternates */
1167     if (!in_array($address, $this->gosaMailAlternateAddress)){
1168       $this->gosaMailAlternateAddress[]= $address;
1169     }
1171     sort ($this->gosaMailAlternateAddress);
1172     reset ($this->gosaMailAlternateAddress);
1173     $this->is_modified= TRUE;
1175     return ("");
1176   }
1179   function delAlternate($addresses)
1180   {
1181     $this->gosaMailAlternateAddress= array_remove_entries ($addresses,
1182         $this->gosaMailAlternateAddress);
1183     $this->is_modified= TRUE;
1184   }
1187   function make_name($attrs)
1188   {
1189     $name= "";
1190     if (isset($attrs['sn'][0])){
1191       $name= $attrs['sn'][0];
1192     }
1193     if (isset($attrs['givenName'][0])){
1194       if ($name != ""){
1195         $name.= ", ".$attrs['givenName'][0];
1196       } else {
1197         $name.= $attrs['givenName'][0];
1198       }
1199     }
1200     if ($name != ""){
1201       $name.= " ";
1202     }
1204     return ($name);
1205   }
1207   function getCopyDialog()
1208   {
1209     if(!$this->is_account) return("");
1211     $smarty = get_smarty();
1212     $smarty->assign("gosaMailAlternateAddress",$this->gosaMailAlternateAddress);
1213     $smarty->assign("gosaMailForwardingAddress",$this->gosaMailForwardingAddress);
1214     $smarty->assign("mail",$this->mail);
1215     $display= $smarty->fetch (get_template_path('paste_mail.tpl', TRUE, dirname(__FILE__)));
1216     $ret = array();
1217     $ret['string'] = $display;
1218     $ret['status'] = "";
1219     return($ret);
1220   }
1222   function saveCopyDialog()
1223   {
1224     if(!$this->is_account) return;
1226     /* Perform ADD / REMOVE ... for mail alternate / mail forwarding addresses 
1227     */
1228     $this->execute();
1229     if(isset($_POST['mail'])){
1230       $this->mail = $_POST['mail'];
1231     }
1232   }
1235   function PrepareForCopyPaste($source)
1236   {
1237     plugin::PrepareForCopyPaste($source);
1238  
1239     /* Reset alternate mail addresses */
1240     $this->gosaMailAlternateAddress = array();
1241   }
1244   /* Return plugin informations for acl handling  */
1245   static function plInfo()
1246   {
1247     return (array(
1248           "plShortName"   => _("Mail"),
1249           "plDescription" => _("Group mail"),
1250           "plSelfModify"  => FALSE,
1251           "plDepends"     => array(),
1252           "plPriority"    => 10,
1253           "plSection"     => array("administration"),
1254           "plCategory"    => array("groups"), 
1255           "plProvidedAcls"=> array(
1256             "mail"                      => _("Mail address"),
1257             "gosaMailQuota"             => _("Quota size"),
1258             "gosaMailServer"            => _("Mail server"),
1259             "kolabFolderType"           => _("Folder type")." ("._("Kolab").")",
1260             "gosaMailAlternateAddress"  => _("Alternate addresses"),
1261             "gosaMailForwardingAddress" => _("Forwarding addresses"),
1262             "acl"                       => _("Permissions"))
1263           ));
1264   }
1266   
1267   /* Remove given ACL for given member (uid,mail) ..
1268    */
1269   function removeUserAcl($index )
1270   {
1271     if(isset($this->imapacl[$index])){
1272       unset($this->imapacl[$index]);
1273     }
1274   }
1276   function multiple_execute()
1277   {
1278     return($this->execute());
1279   }
1282   function init_multiple_support($attrs,$all)
1283   {
1284     plugin::init_multiple_support($attrs,$all);
1286     $this->gosaMailForwardingAddress = array();
1287     if(isset($attrs['gosaMailForwardingAddress'])){
1288       for($i = 0 ; $i < $attrs['gosaMailForwardingAddress']['count'] ; $i++){
1289         $this->gosaMailForwardingAddress[] = $attrs['gosaMailForwardingAddress'][$i];
1290       }
1291     }
1293     $this->gosaMailForwardingAddress_Some = array();
1294     if(isset($all['gosaMailForwardingAddress'])){
1295       for($i = 0 ; $i < $all['gosaMailForwardingAddress']['count'] ; $i++){
1296         if(!in_array($all['gosaMailForwardingAddress'][$i],$this->gosaMailForwardingAddress)){
1297           $this->gosaMailForwardingAddress_Some[] = $all['gosaMailForwardingAddress'][$i];
1298         }
1299       }
1300     }
1301   }
1303   function multiple_save_object()
1304   {
1305     if(isset($_POST['multiple_mail_group_posted'])){
1306       plugin::multiple_save_object();
1307       
1308       foreach(array("kolabFolderType") as $attr){
1309         if(isset($_POST['use_'.$attr])){
1310           $this->multi_boxes[] = $attr;
1311         }
1312       }
1314       /* Add special kolab attributes */
1315       if(isset($this->config->current['MAILMETHOD'])&&preg_match("/olab/i",$this->config->current['MAILMETHOD'])){
1316         if(isset($_POST['kolabFolderTypeType']) && $this->acl_is_writeable("kolabFolderType")){
1317           $this->kolabFolderTypeType = get_post("kolabFolderTypeType");
1318           $this->kolabFolderTypeSubType = get_post("kolabFolderTypeSubType");
1319         }
1320       }
1322       /* Collect data and re-assign it to the imapacl array */
1323       if ($this->acl_is_writeable("acl")){
1324         $this->imapacl= array();
1325         $this->imapacl['%members%']= $_POST['member_permissions'];
1326         $this->imapacl['anyone']= $_POST['default_permissions'];
1327         foreach ($this->indexed_user as $nr => $user){
1328           if (!isset($_POST["user_$nr"])){
1329             continue;
1330           }
1331           if ($_POST["user_$nr"] != $user ||
1332               $_POST["perm_$nr"] != $this->indexed_acl[$nr]){
1333             $this->is_modified= TRUE;
1334           }
1335           $this->imapacl[$_POST["user_$nr"]]= $_POST["perm_$nr"];
1336         }
1337       }
1338     }
1339   }
1340   
1341   
1342   /* Return selected values for multiple edit */
1343   function get_multi_edit_values()
1344   {
1345     $ret = plugin::get_multi_edit_values();
1346     $ret['Forward_some'] = $this->gosaMailForwardingAddress_Some;    
1347     $ret['Forward_all'] = $this->gosaMailForwardingAddress;    
1348     if(in_array('kolabFolderType',$this->multi_boxes)){
1349       $ret['kolabFolderTypeType'] = $this->kolabFolderTypeType;
1350       $ret['kolabFolderTypeSubType'] = $this->kolabFolderTypeSubType;
1351     }
1352     if(in_array("acl",$this->multi_boxes)){
1353       $ret['imapacl'] = $this->imapacl;
1354     }
1355     return($ret);
1356   }
1358   function set_multi_edit_values($attrs)
1359   {
1360     $forward = array();
1361     foreach($attrs['Forward_some'] as $addr){
1362       if(in_array($addr,$this->gosaMailForwardingAddress)){
1363         $forward[] = $addr;
1364       }
1365     }
1366     foreach($attrs['Forward_all'] as $addr){
1367       $forward[] = $addr;
1368     }
1369     plugin::set_multi_edit_values($attrs);
1370     $this->gosaMailForwardingAddress = $forward;
1371   }
1374   // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1375 ?>