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 = ""; //
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;
65 var $folder_prefix = "";
66 var $user_prefix = "";
68 var $account_name = "";
70 function mailgroup (&$config, $dn= NULL, $ui= NULL)
71 {
72 /* Initialise all available attributes ... if possible
73 */
74 plugin::plugin($config, $dn);
75 if (isset($this->attrs['cn'][0])){
76 $this->uid = $this->cn = $this->attrs['cn'][0];
77 }
78 $this->orig_cn = $this->cn;
80 /* Set mailMethod to the one defined in gosa.conf
81 */
82 if ($this->config->get_cfg_value("mailmethod")){
83 $this->mmethod= $this->config->get_cfg_value("mailmethod");
84 }
86 /* Check if selected mail method exists
87 */
88 $cls = get_correct_class_name("mailMethod$this->mmethod");
89 if ($cls && class_exists($cls)){
90 $this->method= $cls;
91 } else {
92 msg_dialog::display(_("Configuration error"), sprintf(_("Cannot locate mail method '%s'!"), $this->mmethod), ERROR_DIALOG);
93 }
95 /* Load Mailserver
96 */
97 if(isset($this->attrs['gosaMailServer'][0])){
98 $this->gosaMailServer = $this->attrs['gosaMailServer'][0];
99 }
101 /* Get folder type */
102 if(preg_match("/olab/i",$this->config->get_cfg_value("mailmethod"))){
103 if(isset($this->attrs['kolabFolderType'])){
104 $tmp = split("\.",$this->attrs['kolabFolderType'][0]);
105 $this->kolabFolderTypeType = $tmp[0];
106 $this->kolabFolderTypeSubType = $tmp[1];
107 }
108 }
110 /* Create new instance of our defined mailclass
111 */
112 $method= new $this->method($this->config);
114 $this->folder_prefix = $method->folder_prefix;
115 $this->user_prefix = $method->user_prefix;
117 /* Build account name
118 */
119 $uattrib = $method->uattrib;
121 /* Map uid to cn, because we are in a group currently */
122 if($uattrib == "uid") $uattrib ="cn";
124 if (isset($this->attrs[$uattrib][0])){
126 $this->account_name= $this->attrs[$uattrib][0];
127 if(preg_match("/@/",$this->account_name)){
128 $cn = "";
129 if(isset($this->attrs['cn'][0])){
130 $cn = $this->attrs['cn'][0];
131 }
132 $this->account_name = preg_replace("/^[^@]*/",$cn,$this->account_name);
133 }
134 }
136 /* If this isn't a new mailgroup, read all required data from ldap
137 */
138 if (($dn != "new")&&($dn !== NULL)){
140 /* Load attributes which represent multiple entries
141 */
142 foreach (array("gosaMailAlternateAddress", "gosaMailForwardingAddress") as $val){
143 $this->$val = array();
144 if (isset($this->attrs["$val"]["count"])){
145 for ($i= 0; $i<$this->attrs["$val"]["count"]; $i++){
146 array_push($this->$val, $this->attrs["$val"][$i]);
147 }
148 }
149 }
151 /* Only do IMAP actions if gosaMailServer attribute is set
152 */
153 if (isset ($this->attrs["gosaMailServer"][0])){
155 if ($method->connect($this->attrs["gosaMailServer"][0])){
157 /* If we do NOT use kolab or equal methods,
158 read imap the acls from the mail method class.
159 They will be merged later with the ldap specified acls.
160 */
161 if(!preg_match("/olab/i",$this->mmethod) && !empty($this->mmethod)){
162 $this->imapacl= $method->getSharedFolderPermissions($this->folder_prefix.$this->account_name);
164 /* Need to filter what a member acl could be... */
165 $vote= array();
166 $peak= 0;
167 $leader= "";
168 foreach ($this->imapacl as $user => $acl){
170 if ($user != "anyone" ){
171 if (!isset($vote[$acl])){
172 $vote[$acl]= 1;
173 } else {
174 $vote[$acl]++;
175 }
176 if ($vote[$acl] > $peak){
177 $leader= $acl;
178 $peek= $vote[$acl];
179 }
180 }
181 }
182 /* Highest count wins as %members%, remove all members
183 with the same acl */
184 if(!empty($leader)){
185 $this->imapacl['%members%']= $leader;
186 }
187 foreach ($this->imapacl as $user => $acl){
188 if ($this->acl == $leader && in_array($user, $this->attrs['memberUid'])){
189 unset($this->imapacl[$user]);
190 }
191 }
192 }
194 /* Adapt attributes if needed */
195 $method->fixAttributesOnLoad($this);
197 /* get Quota */
198 $quota= $method->getQuota($this->folder_prefix.$this->account_name);
200 /* Update quota values */
201 if(is_array($quota)){
202 if ($quota['gosaMailQuota'] == 2147483647){
203 $this->quotaUsage= "";
204 $this->gosaMailQuota= "";
205 } else {
206 $this->quotaUsage= $quota['quotaUsage'];
207 $this->gosaMailQuota= $quota['gosaMailQuota'];
208 }
209 }else{
210 $this->quotaUsage = "";
211 $this->gosaMailQuota = "";
212 }
213 $method->disconnect();
214 } // ENDE $method->connect($this->attrs["gosaMailServer"][0])){
215 } // ENDE gosaMailServer
216 } // ENDE dn != "new"
219 /* Get global filter config */
220 if (!session::is_set("gmailfilter")){
221 $ui= get_userinfo();
222 $base= get_base_from_people($ui->dn);
223 $gmailfilter= array( "depselect" => $base,
224 "muser" => "",
225 "regex" => "*");
226 session::set("gmailfilter", $gmailfilter);
227 }
229 /* Load permissions */
230 $tmp = array();
231 $ldap = $this->config->get_ldap_link();
233 /* Read acls from ldap and merge them with
234 * acls read from mail method.
235 */
236 if (isset($this->attrs['acl'])){
238 for ($i= 0; $i<$this->attrs['acl']['count']; $i++){
239 list($user, $permission)= split(' ', $this->attrs['acl'][$i]);
241 /* Add to list */
242 $this->imapacl[$user]= $permission;
244 /* Get all user permissions sorted by acl, to detect the most used acl
245 This acl is then used for %members%
246 */
247 if ($user != "anyone" && $user != "%members%"){
248 $tmp[$permission][] = $user;
249 }
251 /* There is an entry in $this->imapacl like this this ...
252 $this->attrs['imapacl']['anyone'] = "p";
253 $this->attrs['imapacl']['%members%'] = "lprs";
254 $this->attrs['imapacl'][''] = ""; <------ This is used to diplay an empty
255 Field for special acls in our template.
256 If there is at least one special acl in out imapacl,
257 we don't need this entry anymore, because it is already displayed.
258 */
259 if ($user != "anyone" && $user != "%members%"){
260 unset($this->imapacl['']);
261 }
262 }
263 }
265 /**
266 * Detect group members which use the same acl
267 * as used for %members% and remove them.
268 **/
270 /* In this section we detect which acl is the most used.
271 This will be used as %members% acl.
272 */
273 $tmp2 = array();
274 foreach($tmp as $acl => $user){
275 $tmp2[count($tmp[$acl])]=$acl;
276 }
277 /* Most used at last
278 */
279 ksort($tmp2);
281 /* Assign last (most used acl) to %members% acl
282 */
283 $str = array_pop($tmp2);
284 if(!empty($str)) {
285 $this->imapacl['%members%']=$str;
286 }
287 if(!isset($this->imapacl['%members%'])){
288 $this->imapacl['%members%'] = "lrspw";
289 }
292 /* Open ldap connection
293 */
294 $ldap = $this->config->get_ldap_link();
295 $ldap->cd($this->config->current['BASE']);
297 /* Remove those users, that use %members% acl && are member of this group. */
298 foreach($this->imapacl as $mail => $permission){
299 $ldap->search("(&(objectClass=person)(|(mail=".$mail.")(uid=".$mail.")))",array("uid"));
300 $atr = $ldap->fetch();
301 if((isset($this->attrs['memberUid'])) && (is_array($this->attrs['memberUid']))){
302 if((isset($atr['uid'][0]))&&(in_array($atr['uid'][0],$this->attrs['memberUid']))&&($permission == $this->imapacl['%members%'])){
303 unset($this->imapacl[$mail]);
304 }
305 }
306 }
308 /**
309 * ENDE: Detect group member with same acl and replace them with %members%
310 **/
311 $this->indexed_user = array("%members%","anyone");
313 /* Append an empty entry, for special acl handling */
314 if(count($this->imapacl)==2){
315 $this->imapacl[''] ="lrsw";
316 $this->indexed_user[] = '';
317 }
319 /* Load Mailserver
320 */
321 if(isset($this->attrs['gosaMailServer'][0])){
322 $this->gosaMailServer = $this->attrs['gosaMailServer'][0];
323 }
324 /* Fill translations */
325 $this->perms["lrsw"]= _("read");
326 $this->perms["lrswp"]= _("post");
327 $this->perms["p"]= _("external post");
328 $this->perms["lrswip"]= _("append");
329 $this->perms["lrswipcd"]= _("write");
330 $this->perms["lrswipcda"]= _("admin");
331 $this->perms[""]= _("none");
332 }
336 function execute()
337 {
338 /* Call parent execute */
339 //plugin::execute();
340 $display = "";
342 /* Log view */
343 if($this->is_account && !$this->view_logged){
344 $this->view_logged = TRUE;
345 new log("view","groups/".get_class($this),$this->dn);
346 }
348 /* Load templating engine */
349 $smarty= get_smarty();
351 /* Assign acls */
352 $tmp = $this->plInfo();
353 foreach($tmp['plProvidedAcls'] as $name => $translation) {
354 $smarty->assign($name."ACL",$this->getacl($name));
355 }
357 if (session::get('js')==FALSE){
358 $smarty->assign("javascript", "false");
359 } else {
360 $smarty->assign("javascript", "true");
361 }
363 /* Handle actions should not be done, when
364 * editing multiple entries at once. e.g. account state
365 */
366 if(!$this->multiple_support_active){
368 /* Do we need to flip is_account state? */
369 if(isset($_POST['modify_state'])){
370 if($this->is_account && $this->acl_is_removeable()){
371 $this->is_account= FALSE;
372 }elseif(!$this->is_account && $this->acl_is_createable()){
373 $this->is_account= TRUE;
374 }
375 }
377 $display = "";
379 /* Do we represent a valid account? */
380 if (!$this->is_account && $this->parent === NULL){
382 $display.= "<img alt=\"\" src=\"images/small-error.png\" align=middle> <b>".msgPool::noValidExtension(_("mail"))."</b>";
383 return ($display);
384 }
386 /* Show tab dialog headers */
387 $display= "";
388 if ($this->parent !== NULL){
389 if ($this->is_account){
390 $display.= $this->show_disable_header(_("Remove mail account"),
391 msgPool::featuresEnabled(_("mail")));
392 } else {
393 $display.= $this->show_enable_header(_("Create mail account"),
394 msgPool::featuresDisabled(_("mail")));
396 /* Show checkbox that allows us to remove imap entry too*/
397 if($this->initially_was_account){
398 $c = "";
399 if($this->remove_folder_from_imap){
400 $c= " checked ";
401 }
402 $display .= "<h2>Shared folder delete options</h2>
403 <input class='center' type='checkbox' name='remove_folder_from_imap' value='1' ".$c."
404 title='"._("Remove shared folder from mail server database when entry gets removed in LDAP")."'>";
405 $display .= _("Remove the shared folder and all its contents after saving this account");
406 }
407 return ($display);
408 }
409 }
410 }
412 /* Add ACL? */
413 if($this->acl_is_writeable("acl")){
414 foreach ($this->indexed_user as $nr => $user){
415 if (isset($_POST["add_$nr"])){
416 $this->imapacl[""]= "l";
417 }
418 if (isset($_POST["del_$nr"])){
419 unset ($this->imapacl[$user]);
420 }
421 }
422 }
424 /* Trigger forward add dialog? */
425 if($this->acl_is_writeable("gosaMailForwardingAddress")){
426 if (isset($_POST['add_local_forwarder'])){
427 $this->forward_dialog= TRUE;
428 $this->dialog= TRUE;
429 }
430 }
432 /* Cancel forward add dialog? */
433 if($this->acl_is_writeable("gosaMailForwardingAddress")){
434 if (isset($_POST['add_locals_cancel'])){
435 $this->forward_dialog= FALSE;
436 $this->dialog= FALSE;
437 }
438 }
440 /* Finished adding of locals? */
441 if ((isset($_POST['add_locals_finish'])) && ($this->acl_is_writeable("gosaMailForwardingAddress"))) {
442 if (count ($_POST['local_list']) && $this->acl_is_writeable("gosaMailForwardingAddress")){
444 /* Walk through list of forwarders, ignore own addresses */
445 foreach ($_POST['local_list'] as $val){
446 if (!in_array ($val, $this->gosaMailAlternateAddress) &&
447 $val != $this->mail){
449 $this->addForwarder($val);
450 }
451 }
452 }
453 $this->forward_dialog= FALSE;
454 $this->dialog= FALSE;
455 }
457 /* Add forward email addresses */
458 if ((isset($_POST['add_forwarder'])) && ($this->acl_is_writeable("gosaMailForwardingAddress"))){
459 if ($_POST['forward_address'] != ""){
461 /* Valid email address specified? */
462 $address= $_POST['forward_address'];
463 if (!tests::is_email($address)){
464 msg_dialog::display(_("Error"), msgPool::invalid(_("forward address")), ERROR_DIALOG);
465 } elseif ($address == $this->mail
466 || in_array($address, $this->gosaMailAlternateAddress)) {
468 msg_dialog::display(_("Error"), _("Cannot forward to users own mail address!"), ERROR_DIALOG);
470 } else {
472 /* Add it */
473 if ($this->acl_is_writeable("gosaMailForwardingAddress")){
474 $this->addForwarder ($address);
475 }
477 }
478 }
479 }
481 /* Delete forward email addresses */
482 if (isset($_POST['delete_forwarder']) && ($this->acl_is_writeable("gosaMailForwardingAddress"))){
483 if (count($_POST['forwarder_list'])&& $this->acl_is_writeable("gosaMailForwardingAddress")){
485 $this->delForwarder ($_POST['forwarder_list']);
486 }
487 }
489 /* Add alternate email addresses */
490 if (isset($_POST['add_alternate'])){
491 if ($_POST['alternate_address'] != "" && $this->acl_is_writeable("gosaMailAlternateAddress")){
493 if (!tests::is_email($_POST['alternate_address'])){
494 msg_dialog::display(_("Error"),msgPool::invalid(_("Alternate address")), ERROR_DIALOG);
496 } elseif (($user= $this->addAlternate ($_POST['alternate_address'])) != ""){
497 $ui= get_userinfo();
498 if ($user != $ui->username){
499 msg_dialog::display(_("Error"),msgPool::duplicated(_("Mail address")), ERROR_DIALOG);
500 }
501 }
502 }
503 }
505 /* Delete alternate email addresses */
506 if($this->acl_is_writeable("gosaMailAlternateAddress")){
507 if (isset($_POST['delete_alternate']) && isset ($_POST['alternates_list'])){
508 if (count($_POST['alternates_list']) && $this->acl_is_writeable("gosaMailAlternateAddress")){
509 $this->delAlternate ($_POST['alternates_list']);
510 }
511 }
512 }
514 /* Show forward add dialog */
515 if ($this->forward_dialog){
516 $ldap= $this->config->get_ldap_link();
518 /* Save data */
519 $gmailfilter= session::get("gmailfilter");
520 foreach( array("depselect", "muser", "regex") as $type){
521 if (isset($_POST[$type])){
522 $gmailfilter[$type]= $_POST[$type];
523 }
524 }
525 if (isset($_GET['search'])){
526 $s= mb_substr($_GET['search'], 0, 1, "UTF8")."*";
527 if ($s == "**"){
528 $s= "*";
529 }
530 $gmailfilter['regex']= $s;
531 }
532 session::set("gmailfilter", $gmailfilter);
534 /* Get actual list */
535 $mailusers= array ();
536 if ($gmailfilter['regex'] != '*' && $gmailfilter['regex'] != ""){
537 $regex= $gmailfilter['regex'];
538 $filter= "(|(mail=$regex)(gosaMailAlternateAddress=$regex))";
539 } else {
540 $filter= "";
541 }
542 if ($gmailfilter['muser'] != ""){
543 $user= $gmailfilter['muser'];
544 $filter= "$filter(|(uid=$user)(cn=$user)(givenName=$user)(sn=$user))";
545 }
547 /* Add already present people to the filter */
548 $exclude= "";
549 foreach ($this->gosaMailForwardingAddress as $mail){
550 $exclude.= "(mail=$mail)";
551 }
552 if ($exclude != ""){
553 $filter.= "(!(|$exclude))";
554 }
556 $res= get_list("(&(objectClass=gosaMailAccount)$filter)", "users", $gmailfilter['depselect'],
557 array("sn", "mail", "givenName"), GL_SUBSEARCH | GL_SIZELIMIT);
558 $ldap->cd($gmailfilter['depselect']);
559 $ldap->search ("(&(objectClass=gosaMailAccount)$filter)", array("sn", "mail", "givenName"));
560 error_reporting (0);
561 while ($attrs= $ldap->fetch()){
562 if(preg_match('/%/', $attrs['mail'][0])){
563 continue;
564 }
565 $name= $this->make_name($attrs);
566 $mailusers[$attrs['mail'][0]]= $name."<".
567 $attrs['mail'][0].">";
568 }
569 error_reporting (E_ALL | E_STRICT);
570 natcasesort ($mailusers);
571 reset ($mailusers);
573 /* Show dialog */
574 $smarty->assign("search_image", get_template_path('images/lists/search.png'));
575 $smarty->assign("usearch_image", get_template_path('images/lists/search-user.png'));
576 $smarty->assign("tree_image", get_template_path('images/lists/search-subtree.png'));
577 $smarty->assign("infoimage", get_template_path('images/info.png'));
578 $smarty->assign("launchimage", get_template_path('images/lists/action.png'));
579 $smarty->assign("mailusers", $mailusers);
580 $smarty->assign("deplist", $this->config->idepartments);
581 $smarty->assign("apply", apply_filter());
582 $smarty->assign("alphabet", generate_alphabet());
583 $smarty->assign("hint", print_sizelimit_warning());
584 foreach( array("depselect", "muser", "regex") as $type){
585 $smarty->assign("$type", $gmailfilter[$type]);
586 }
587 $smarty->assign("hint", print_sizelimit_warning());
588 $display.= $smarty->fetch (get_template_path('mail_locals.tpl', TRUE, dirname(__FILE__)));
589 return ($display);
590 }
592 /* Assemble normal permissions */
593 if (isset($this->imapacl['anyone'])){
594 $smarty->assign("default_permissions", $this->imapacl['anyone']);
595 }
596 $smarty->assign("member_permissions", "lrsp");
597 if (isset($this->imapacl['%members%'])){
598 $smarty->assign("member_permissions", $this->imapacl['%members%']);
599 }
601 /* Assemble extra attributes */
602 $perm= $this->getacl( "acl");
603 $tmp= "";
604 $nr= 0;
605 $count= count($this->imapacl);
606 $this->indexed_user= array();
607 $this->indexed_acl= array();
608 foreach($this->imapacl as $user => $acl){
610 /* Add additional acl settings */
611 if ($user != "anyone" && $user != "%members%"){
613 $Dis = "";
614 if(!preg_match("/w/",$perm)){
615 $Dis = " disabled ";
616 }
618 /* Reset given Acls to ensure that nobody can read username and acls if not allwoed */
619 if(!preg_match("/r/",$perm)){
620 $user = "";
621 $nr = "none";
622 $key = "none";
623 }
625 $tmp.= "<tr>
626 <td>
627 <input name=\"user_$nr\" size=20 maxlength=60 value=\"$user\" ".$Dis.">
628 </td>
629 <td>
630 <select size=\"1\" name=\"perm_$nr\" ".$Dis.">";
632 /* Add acl options for this additional acl setting */
633 if(preg_match("/r/",$perm)){
634 foreach ($this->perms as $key => $value){
635 if ($acl == $key){
636 $tmp.= "<option value=\"$key\" selected>$value</option>";
637 } else {
638 $tmp.= "<option value=\"$key\">$value</option>";
639 }
640 }
641 }
642 $tmp.= "</select> ";
646 if ($nr == $count - 1){
647 if($this->acl_is_writeable("acl")){
648 $tmp.= "<input type=submit value=\""._("Add")."\" ".
649 "name=\"add_$nr\" >";
650 }
651 }
652 if ($count > 3){
653 if($this->acl_is_writeable("acl")){
654 $tmp.= "<input type=submit value=\""._("Remove")."\" ".
655 "name=\"del_$nr\" ></td></tr>";
656 }
657 }
658 }
659 $this->indexed_user[$nr]= $user;
660 $this->indexed_acl[$nr++]= $acl;
661 }
662 $smarty->assign("plusattributes", $tmp);
664 /* Show main page */
665 $mailserver= array();
666 $ui = get_userinfo();
667 foreach ($this->config->data['SERVERS']['IMAP'] as $key => $val){
668 if(!preg_match("/r/",$ui->get_category_permissions($val['server_dn'],"server"))) continue;
669 $mailserver[]= $key;
670 }
672 /* Append currently selected server if we are not allowed to view it.
673 */
674 if(isset($this->config->data['SERVERS']['IMAP'][$this->gosaMailServer]) &&
675 !in_array($this->gosaMailServer,$mailserver)){
676 $mailserver[] = $this->gosaMailServer;
677 }
679 $smarty->assign("mailServers", $mailserver);
680 foreach(array("gosaMailServer", "gosaMailQuota", "perms", "mail",
681 "gosaMailAlternateAddress", "gosaMailForwardingAddress") as $val){
682 $smarty->assign("$val", $this->$val);
683 }
684 if (is_numeric($this->gosaMailQuota) && $this->gosaMailQuota != 0){
685 if($this->acl_is_readable("gosaMailQuota")){
686 $smarty->assign("quotausage", progressbar(round(($this->quotaUsage * 100)/ $this->gosaMailQuota),100,15,true));
687 $smarty->assign("quotadefined", "true");
688 }else{
689 $smarty->assign("quotadefined", "true");
690 $smarty->assign("quotausage", "-");
691 }
692 } else {
693 $smarty->assign("quotadefined", "false");
694 }
696 if(preg_match("/olab/i",$this->config->get_cfg_value("mailmethod"))){
698 $smarty->assign("kolab", TRUE);
699 $smarty->assign("JS",session::get('js'));
700 $smarty->assign("kolabFolderTypeTypes", array ( '' => _('Unspecified'), 'mail' => _('Mails'),
701 'task' => _('Tasks') , 'journal' => _('Journals'),
702 'calendar' => _('Calendar'), 'contact' => _('Contacts'),
703 'note' => _('Notes')));
704 if($this->kolabFolderTypeType == "mail"){
705 $smarty->assign("kolabFolderTypeSubTypes", array(
706 '' => _('Unspecified'), 'inbox' => _("Inbox") ,
707 'drafts' => _("Drafts"), 'sentitems' => _("Sent items"),
708 'junkemail' => _("Junk mail")));
709 }else{
710 $smarty->assign("kolabFolderTypeSubTypes", array( 'default' => _("Default")));
711 }
712 $smarty->assign("kolabFolderTypeType", $this->kolabFolderTypeType);
713 $smarty->assign("kolabFolderTypeSubType", $this->kolabFolderTypeSubType);
714 }else{
715 $smarty->assign("kolab", FALSE);
716 }
718 /* Multiple support handling */
719 foreach($this->attributes as $attr){
720 if(in_array($attr,$this->multi_boxes)){
721 $smarty->assign("use_".$attr,TRUE);
722 }else{
723 $smarty->assign("use_".$attr,FALSE);
724 }
725 }
727 /* Multiple support handling */
728 foreach(array("kolabFolderType") as $attr){
729 if(in_array($attr,$this->multi_boxes)){
730 $smarty->assign("use_".$attr,TRUE);
731 }else{
732 $smarty->assign("use_".$attr,FALSE);
733 }
734 }
736 $smarty->assign("Forward_all",$this->gosaMailForwardingAddress);
737 $smarty->assign("Forward_some",$this->gosaMailForwardingAddress_Some);
739 $smarty->assign("multiple_support",$this->multiple_support_active);
740 $display.= $smarty->fetch (get_template_path('mail.tpl', TRUE, dirname(__FILE__)));
741 return ($display);
742 }
745 /* remove object from parent */
746 function remove_from_parent()
747 {
748 if(!$this->initially_was_account){
749 return;
750 }
752 /* Added these ObjectClass and Attributes, because they were not
753 removed correctly, only in case of kolab ...
754 */
755 if(preg_match("/olab/i",$this->config->get_cfg_value("mailmethod"))){
756 $this->attributes[]="acl";
757 $this->objectclasses[] = "kolabSharedFolder";
758 }
759 /* include global link_info */
760 $ldap= $this->config->get_ldap_link();
762 /* Remove and write to LDAP */
763 plugin::remove_from_parent();
765 /* Zero arrays */
766 $this->attrs['gosaMailAlternateAddress']= array();
767 $this->attrs['gosaMailForwardingAddress']= array();
768 $this->attrs['gosaSharedFolderTarget']= array();
770 /* Connect to IMAP server for account deletion */
771 if ($this->initially_was_account){
773 $method= new $this->method($this->config);
774 $method->fixAttributesOnRemove($this);
775 if ($method->connect($this->gosaMailServer) && $this->remove_folder_from_imap){
777 /* Remove account from IMAP server */
778 $method->deleteMailbox($this->folder_prefix.$this->account_name);
779 $method->disconnect();
780 }
781 }
782 /* Keep uid */
783 unset ($this->attrs['uid']);
785 $ldap->cd($this->dn);
786 $ldap->modify ($this->attrs);
787 if (!$ldap->success()){
788 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
789 }
792 new log("remove","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
794 /* Optionally execute a command after we're done */
795 $this->handle_post_events("remove");
796 }
799 /* Save data to object */
800 function save_object()
801 {
803 /* Add special kolab attributes */
804 if(preg_match("/olab/i",$this->config->get_cfg_value("mailmethod"))){
805 if(isset($_POST['kolabFolderTypeType']) && $this->acl_is_writeable("kolabFolderType")){
806 $this->kolabFolderTypeType = get_post("kolabFolderTypeType");
807 $this->kolabFolderTypeSubType = get_post("kolabFolderTypeSubType");
808 }
809 }
811 /* Check if user wants to remove the shared folder from imap too */
812 if($this->initially_was_account && !$this->is_account){
813 if(isset($_POST['remove_folder_from_imap'])){
814 $this->remove_folder_from_imap = true;
815 }else{
816 $this->remove_folder_from_imap = false;
817 }
818 }
820 /* Assemble mail delivery mode
821 The mode field in ldap consists of values between braces, this must
822 be called when 'mail' is set, because checkboxes may not be set when
823 we're in some other dialog.
825 Example for gosaMailDeliveryMode [LR ]
826 L: Local delivery
827 R: Reject when exceeding mailsize limit
828 S: Use spam filter
829 V: Use vacation message
830 C: Use custom sieve script
831 I: Only insider delivery */
832 if (isset($_POST['mailedit'])){
834 plugin::save_object();
836 $tmp= preg_replace("/[^a-z]/i","",$this->gosaMailDeliveryMode);
838 /* Handle delivery flags */
839 if($this->acl_is_writeable("gosaMailDeliveryModeL")){
840 if(!preg_match("/L/",$tmp) && !isset($_POST['drop_own_mails'])){
841 $tmp.="L";
842 }elseif(preg_match("/L/",$tmp) && isset($_POST['drop_own_mails'])){
843 $tmp = preg_replace("/L/","",$tmp);
844 }
845 }
847 $opts = array(
848 "R" => "use_mailsize_limit",
849 "S" => "use_spam_filter",
850 "V" => "use_vacation",
851 "C" => "own_script",
852 "I" => "only_local");
854 foreach($opts as $flag => $post){
855 if($this->acl_is_writeable("gosaMailDeliveryMode".$flag)){
856 if(!preg_match("/".$flag."/",$tmp) && isset($_POST[$post])){
857 $tmp.= $flag;
858 }elseif(preg_match("/".$flag."/",$tmp) && !isset($_POST[$post])){
859 $tmp = preg_replace("/".$flag."/","",$tmp);
860 }
861 }
862 }
864 $tmp= "[$tmp]";
865 if ($this->gosaMailDeliveryMode != $tmp){
866 $this->is_modified= TRUE;
867 }
868 $this->gosaMailDeliveryMode= $tmp;
870 /* Collect data and re-assign it to the imapacl array */
871 if ($this->acl_is_writeable("acl")){
872 $this->imapacl= array();
873 $this->imapacl['%members%']= $_POST['member_permissions'];
874 $this->imapacl['anyone']= $_POST['default_permissions'];
875 foreach ($this->indexed_user as $nr => $user){
876 if (!isset($_POST["user_$nr"])){
877 continue;
878 }
879 if ($_POST["user_$nr"] != $user ||
880 $_POST["perm_$nr"] != $this->indexed_acl[$nr]){
881 $this->is_modified= TRUE;
882 }
883 $this->imapacl[$_POST["user_$nr"]]= $_POST["perm_$nr"];
884 }
885 }
886 }
888 }
891 /* Save data to LDAP, depending on is_account we save or delete */
892 function save()
893 {
894 $ldap= $this->config->get_ldap_link();
895 $ldap->cd($this->config->current['BASE']);
897 /* Call parents save to prepare $this->attrs */
898 plugin::save();
900 /* Save arrays */
901 $this->attrs['gosaMailAlternateAddress'] = $this->gosaMailAlternateAddress;
902 $this->attrs['gosaMailForwardingAddress'] = $this->gosaMailForwardingAddress;
903 $this->attrs['gosaSharedFolderTarget'] = "share+".$this->account_name;
904 $this->attrs['acl']= array();
906 /* Prepare Mail server attribute */
907 if(preg_match("/olab/i",$this->mmethod)){
908 if (empty($this->gosaMailServer)||is_array($this->gosaMailServer)){
909 if(isset($this->attrs['gosaMailServer'][0])){
910 $this->gosaMailServer = $this->attrs['gosaMailServer'][0];
911 }
912 }
913 }
915 /* Exchange '%member%' pseudo entry */
916 $memberacl= $this->imapacl['%members%'];
917 foreach ($this->members as $user){
918 if (!isset($this->imapacl[$user])){
919 $this->imapacl[$user]= $memberacl;
920 }
921 }
923 /* Prepare kolab attributes to be written */
924 if(preg_match("/olab/i",$this->mmethod)){
925 if(!empty($this->kolabFolderTypeType)){
926 $this->attrs['kolabFolderType'] = $this->kolabFolderTypeType.".".$this->kolabFolderTypeSubType;
927 }else{
928 $this->attrs['kolabFolderType'] = array();
929 }
930 }
932 /* Get naming attribute for mail accounts */
933 $tmp = new $this->method($this->config);
934 $uattrib = $tmp->uattrib;
936 /* Create ACL array
937 What is done here.
939 1. Do not write acl entries for empty entries.
940 2. Check if given user is a valid GOsa user.
941 - If he is one, check if he has a valid mail extension
942 -If this is true, add the user to the ACL entry.
943 -If this is NOT true, skip ACL entries for this user.
944 - He is not a GOsa Account, so write the ACL. (Manually entered ACL)
945 3. In case of "olab" mail method, remove the entry from the $this->imapacl array
946 because the kolab deamon will set the acls for us.
948 */
949 $acls_set_for = array();
950 foreach ($this->imapacl as $user => $acl){
952 /* Skip empty entries */
953 if (empty($user) || $user == ""){
954 unset($this->imapacl[$user]);
955 }
957 /* Skip placeholder */
958 if (empty($user) || $user == "" || preg_match("/%members%/",$user)){
959 continue;
960 }
962 /* Check if your is a real GOsa user
963 * If user is a real GOsa user but do not have an email address - SKIP adding acls
964 * If user is a real GOsa user with an email address - add acls
965 */
966 $ldap->search("(&(objectClass=person)(|(uid=".$user.")(mail=".$user.")))",array("mail","uid"));
967 if($ldap->count()){
969 /* Has the user a valid mail account? */
970 $attrs = $ldap->fetch();
971 if(isset($attrs['mail'][0])){
973 $name = $attrs[$uattrib][0];
975 /* Do not overwrite manually set ACLs with group member acls
976 */
977 if(!in_array($name,$acls_set_for)){
978 $this->attrs['acl'][]= $name." ".$acl;
979 }
980 $acls_set_for[] = $name;
983 /* Do not write imap acl directly i nkolab mode, let the kolab deamon do this. */
984 unset($this->imapacl[$user]);
985 if(!preg_match("/olab/i",$this->mmethod)){
986 $this->imapacl[$name] = $acl;
987 }
989 }else{
991 /* User is a valid GOsa account, but he has no mail extension. Skip ACLs */
992 unset($this->imapacl[$user]);
993 }
994 }else{
996 /* Seems to be a manually a added acl
997 * Write this acl.
998 */
1000 /* Do not overwrite manually set ACLs with group member acls
1001 */
1002 if(!in_array($user,$acls_set_for)){
1003 $this->attrs['acl'][]= $user." ".$acl;
1004 $acls_set_for[] = $user;
1005 }
1007 /* In case of kolab methods, let the deamon add the imap acls */
1008 if(preg_match("/olab/i",$this->mmethod)){
1009 unset($this->imapacl[$user]);
1010 }
1011 }
1012 }
1014 /* Handle mail method actions, set acls, quota ...*/
1015 if ((!$this->is_template)&&(!empty($this->gosaMailServer))){
1016 $method= new $this->method($this->config);
1017 $method->fixAttributesOnStore($this);
1018 if (($method->connect($this->gosaMailServer))){
1019 $method->updateMailbox($this->folder_prefix.$this->account_name);
1020 $method->setQuota($this->folder_prefix.$this->account_name, $this->gosaMailQuota);
1022 /* Only write imap acls directly if we are not
1023 * using a kolab like mail method.
1024 */
1025 if(!preg_match("/olab/i",$this->mmethod)){
1026 $method->setSharedFolderPermissions($this->folder_prefix.$this->account_name, $this->imapacl);
1027 }
1028 $method->disconnect();
1029 }
1030 }
1032 /* Save data to LDAP */
1033 $ldap->cd($this->dn);
1034 $this->cleanup();
1035 $ldap->modify ($this->attrs);
1036 if (!$ldap->success()){
1037 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
1038 }
1040 if($this->initially_was_account){
1041 new log("modify","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1042 }else{
1043 new log("create","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1044 }
1047 /* Optionally execute a command after we're done */
1048 if ($this->initially_was_account == $this->is_account){
1049 if ($this->is_modified){
1050 $this->handle_post_events("modify");
1051 }
1052 } else {
1053 $this->handle_post_events("add");
1054 }
1055 }
1059 /* Check formular input */
1060 function check()
1061 {
1062 $ldap= $this->config->get_ldap_link();
1064 /* Call common method to give check the hook */
1065 $message= plugin::check();
1067 if(!$this->is_account) return array();
1069 //$message[] = $str;
1071 /* must: mail */
1072 if ($this->mail == ""){
1073 $message[]= msgPool::required(_("Mail address"));
1074 }
1075 if (!tests::is_email($this->mail)){
1076 $message[]= msgPool::invalid(_("Mail address"),"","",_("your-name@your-domain.com"));
1077 }
1078 $ldap->cd($this->config->current['BASE']);
1079 $ldap->search ("(&(!(objectClass=gosaUserTemplate))(objectClass=gosaMailAccount)(|(mail=".$this->mail.")(gosaMailAlternateAddress=".
1080 $this->mail."))(!(uid=".$this->orig_cn."))(!(cn=".$this->orig_cn.")))");
1081 if ($ldap->count() != 0){
1082 $message[]= msgPool::duplicated(_("Mail address"));
1083 }
1085 /* Check quota */
1086 if ($this->gosaMailQuota != '' && $this->acl_is_writeable("gosaMailQuota")){
1087 if (!is_numeric($this->gosaMailQuota)) {
1088 $message[]= msgPool::invalid(_("Quota size"),$this->gosaMailQuota,"/[0-9]/");
1089 } else {
1090 $this->gosaMailQuota= (int) $this->gosaMailQuota;
1091 }
1092 }
1094 /* Check rejectsize for integer */
1095 if ($this->gosaMailMaxSize != '' && $this->acl_is_writeable("gosaMailQuota")){
1096 if (!is_numeric($this->gosaMailMaxSize)){
1097 $message[]= msgPool::invalid(_("Mail max size"));
1098 } else {
1099 $this->gosaMailMaxSize= (int) $this->gosaMailMaxSize;
1100 }
1101 }
1103 /* Need gosaMailMaxSize if use_mailsize_limit is checked */
1104 if (is_integer(strpos($this->gosaMailDeliveryMode, "reject")) && $this->gosaMailMaxSize == ""){
1105 $message[]= _("You need to set the maximum mail size in order to reject anything.");
1106 }
1108 if(ord($this->imapacl['anyone'][0])==194){
1109 $message[] = _("Please choose valid permission settings. Default permission can't be emtpy.");
1110 }
1112 if(empty($this->gosaMailServer)){
1113 $message[] = msgPool::required(_("Mail server"));
1114 }
1116 return ($message);
1117 }
1119 /* Adapt from template, using 'dn' */
1120 function adapt_from_template($dn, $skip= array())
1121 {
1122 plugin::adapt_from_template($dn, $skip);
1124 foreach (array("gosaMailAlternateAddress", "gosaMailForwardingAddress") as $val){
1126 if (in_array($val, $skip)){
1127 continue;
1128 }
1130 $this->$val= array();
1131 if (isset($this->attrs["$val"]["count"])){
1132 for ($i= 0; $i<$this->attrs["$val"]["count"]; $i++){
1133 $value= $this->attrs["$val"][$i];
1134 foreach (array("sn", "givenName", "uid") as $repl){
1135 if (preg_match("/%$repl/i", $value)){
1136 $value= preg_replace ("/%$repl/i", $this->parent->$repl, $value);
1137 }
1138 }
1139 array_push($this->$val, $value);
1140 }
1141 }
1142 }
1143 }
1145 /* Add entry to forwarder list */
1146 function addForwarder($address)
1147 {
1148 $this->gosaMailForwardingAddress[]= $address;
1149 $this->gosaMailForwardingAddress= array_unique($this->gosaMailForwardingAddress);
1151 /* Update multiple edit values too */
1152 if($this->multiple_support_active){
1153 $this->gosaMailForwardingAddress_Some=
1154 array_remove_entries (array($address),$this->gosaMailForwardingAddress_Some);
1155 }
1157 sort ($this->gosaMailForwardingAddress);
1158 reset ($this->gosaMailForwardingAddress);
1159 $this->is_modified= TRUE;
1160 }
1162 /* Remove list of addresses from forwarder list */
1163 function delForwarder($addresses)
1164 {
1165 $this->gosaMailForwardingAddress= array_remove_entries ($addresses,
1166 $this->gosaMailForwardingAddress);
1168 /* Update multiple edit values too */
1169 if($this->multiple_support_active){
1170 $this->gosaMailForwardingAddress_Some = array_remove_entries ($addresses,
1171 $this->gosaMailForwardingAddress_Some);
1172 }
1173 $this->is_modified= TRUE;
1174 }
1178 function addAlternate($address)
1179 {
1180 $ldap= $this->config->get_ldap_link();
1182 $address= strtolower($address);
1184 /* Is this address already assigned in LDAP? */
1185 $ldap->cd ($this->config->current['BASE']);
1186 $ldap->search ("(&(objectClass=gosaMailAccount)(|(mail=$address)".
1187 "(gosaMailAlternateAddress=$address)))");
1189 if ($ldap->count() > 0){
1190 $attrs= $ldap->fetch ();
1191 return ($attrs["uid"][0]);
1192 }
1194 /* Add to list of alternates */
1195 if (!in_array($address, $this->gosaMailAlternateAddress)){
1196 $this->gosaMailAlternateAddress[]= $address;
1197 }
1199 sort ($this->gosaMailAlternateAddress);
1200 reset ($this->gosaMailAlternateAddress);
1201 $this->is_modified= TRUE;
1203 return ("");
1204 }
1207 function delAlternate($addresses)
1208 {
1209 $this->gosaMailAlternateAddress= array_remove_entries ($addresses,
1210 $this->gosaMailAlternateAddress);
1211 $this->is_modified= TRUE;
1212 }
1215 function make_name($attrs)
1216 {
1217 $name= "";
1218 if (isset($attrs['sn'][0])){
1219 $name= $attrs['sn'][0];
1220 }
1221 if (isset($attrs['givenName'][0])){
1222 if ($name != ""){
1223 $name.= ", ".$attrs['givenName'][0];
1224 } else {
1225 $name.= $attrs['givenName'][0];
1226 }
1227 }
1228 if ($name != ""){
1229 $name.= " ";
1230 }
1232 return ($name);
1233 }
1235 function getCopyDialog()
1236 {
1237 if(!$this->is_account) return("");
1239 $smarty = get_smarty();
1240 $smarty->assign("gosaMailAlternateAddress",$this->gosaMailAlternateAddress);
1241 $smarty->assign("gosaMailForwardingAddress",$this->gosaMailForwardingAddress);
1242 $smarty->assign("mail",$this->mail);
1243 $display= $smarty->fetch (get_template_path('paste_mail.tpl', TRUE, dirname(__FILE__)));
1244 $ret = array();
1245 $ret['string'] = $display;
1246 $ret['status'] = "";
1247 return($ret);
1248 }
1250 function saveCopyDialog()
1251 {
1252 if(!$this->is_account) return;
1254 /* Perform ADD / REMOVE ... for mail alternate / mail forwarding addresses
1255 */
1256 $this->execute();
1257 if(isset($_POST['mail'])){
1258 $this->mail = $_POST['mail'];
1259 }
1260 }
1263 function PrepareForCopyPaste($source)
1264 {
1265 plugin::PrepareForCopyPaste($source);
1267 /* Reset alternate mail addresses */
1268 $this->gosaMailAlternateAddress = array();
1269 }
1272 /* Return plugin informations for acl handling */
1273 static function plInfo()
1274 {
1275 return (array(
1276 "plShortName" => _("Mail"),
1277 "plDescription" => _("Group mail"),
1278 "plSelfModify" => FALSE,
1279 "plDepends" => array(),
1280 "plPriority" => 10,
1281 "plSection" => array("administration"),
1282 "plCategory" => array("groups"),
1283 "plProvidedAcls"=> array(
1284 "mail" => _("Mail address"),
1285 "gosaMailQuota" => _("Quota size"),
1286 "gosaMailServer" => _("Mail server"),
1287 "kolabFolderType" => _("Folder type")." ("._("Kolab").")",
1288 "gosaMailAlternateAddress" => _("Alternate addresses"),
1289 "gosaMailForwardingAddress" => _("Forwarding addresses"),
1290 "acl" => _("Permissions"))
1291 ));
1292 }
1295 /* Remove given ACL for given member (uid,mail) ..
1296 */
1297 function removeUserAcl($index )
1298 {
1299 if(isset($this->imapacl[$index])){
1300 unset($this->imapacl[$index]);
1301 }
1302 }
1304 function multiple_execute()
1305 {
1306 return($this->execute());
1307 }
1310 function init_multiple_support($attrs,$all)
1311 {
1312 plugin::init_multiple_support($attrs,$all);
1314 $this->gosaMailForwardingAddress = array();
1315 if(isset($attrs['gosaMailForwardingAddress'])){
1316 for($i = 0 ; $i < $attrs['gosaMailForwardingAddress']['count'] ; $i++){
1317 $this->gosaMailForwardingAddress[] = $attrs['gosaMailForwardingAddress'][$i];
1318 }
1319 }
1321 $this->gosaMailForwardingAddress_Some = array();
1322 if(isset($all['gosaMailForwardingAddress'])){
1323 for($i = 0 ; $i < $all['gosaMailForwardingAddress']['count'] ; $i++){
1324 if(!in_array($all['gosaMailForwardingAddress'][$i],$this->gosaMailForwardingAddress)){
1325 $this->gosaMailForwardingAddress_Some[] = $all['gosaMailForwardingAddress'][$i];
1326 }
1327 }
1328 }
1329 }
1331 function multiple_save_object()
1332 {
1333 if(isset($_POST['multiple_mail_group_posted'])){
1334 plugin::multiple_save_object();
1336 foreach(array("kolabFolderType") as $attr){
1337 if(isset($_POST['use_'.$attr])){
1338 $this->multi_boxes[] = $attr;
1339 }
1340 }
1342 /* Add special kolab attributes */
1343 if(preg_match("/olab/i",$this->config->get_cfg_value("mailmethod"))){
1344 if(isset($_POST['kolabFolderTypeType']) && $this->acl_is_writeable("kolabFolderType")){
1345 $this->kolabFolderTypeType = get_post("kolabFolderTypeType");
1346 $this->kolabFolderTypeSubType = get_post("kolabFolderTypeSubType");
1347 }
1348 }
1350 /* Collect data and re-assign it to the imapacl array */
1351 if ($this->acl_is_writeable("acl")){
1352 $this->imapacl= array();
1353 $this->imapacl['%members%']= $_POST['member_permissions'];
1354 $this->imapacl['anyone']= $_POST['default_permissions'];
1355 foreach ($this->indexed_user as $nr => $user){
1356 if (!isset($_POST["user_$nr"])){
1357 continue;
1358 }
1359 if ($_POST["user_$nr"] != $user ||
1360 $_POST["perm_$nr"] != $this->indexed_acl[$nr]){
1361 $this->is_modified= TRUE;
1362 }
1363 $this->imapacl[$_POST["user_$nr"]]= $_POST["perm_$nr"];
1364 }
1365 }
1366 }
1367 }
1370 /* Return selected values for multiple edit */
1371 function get_multi_edit_values()
1372 {
1373 $ret = plugin::get_multi_edit_values();
1374 $ret['Forward_some'] = $this->gosaMailForwardingAddress_Some;
1375 $ret['Forward_all'] = $this->gosaMailForwardingAddress;
1376 if(in_array('kolabFolderType',$this->multi_boxes)){
1377 $ret['kolabFolderTypeType'] = $this->kolabFolderTypeType;
1378 $ret['kolabFolderTypeSubType'] = $this->kolabFolderTypeSubType;
1379 }
1380 if(in_array("acl",$this->multi_boxes)){
1381 $ret['imapacl'] = $this->imapacl;
1382 }
1383 return($ret);
1384 }
1386 function set_multi_edit_values($attrs)
1387 {
1388 $forward = array();
1389 foreach($attrs['Forward_some'] as $addr){
1390 if(in_array($addr,$this->gosaMailForwardingAddress)){
1391 $forward[] = $addr;
1392 }
1393 }
1394 foreach($attrs['Forward_all'] as $addr){
1395 $forward[] = $addr;
1396 }
1397 plugin::set_multi_edit_values($attrs);
1398 $this->gosaMailForwardingAddress = $forward;
1399 }
1400 }
1402 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1403 ?>