Code

Updated copy & paste for groups.
[gosa.git] / gosa-core / plugins / admin / groups / class_group.inc
1 <?php
2 /*
3  * This code is part of GOsa (http://www.gosa-project.org)
4  * Copyright (C) 2003-2008 GONICUS GmbH
5  *
6  * ID: $$Id$$
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
23 class group extends plugin
24 {
25   /* Group attributes */
26   var $cn= "";
27   var $description= "";
28   var $gidNumber= "";
29   var $memberUid= array();
30   var $memberUid_used_by_some= array();
32   /* Helpers */
33   var $base= "";
34   var $force_gid= FALSE;
35   var $fon_group= FALSE;
36   var $smbgroup= FALSE;
37   var $groupType= FALSE;
38   var $sambaSID= "";
39   var $sambaDomainName= "DEFAULT";
40   var $SID= "";
41   var $ridBase= 0;
42   var $members= array();
43   var $users= array();
44   var $member= array();
45   var $allusers= array();
46   var $saved_gidNumber= "";
47   var $oldgroupType= "";
48   var $orig_dn= "";
49   var $orig_cn= "";
50   var $orig_base= "";
51   var $has_mailAccount= FALSE;
52   var $userSelect= FALSE;
53   var $nagios_group =FALSE;
54   var $sambaGroupType;
55   var $dialog;
56   var $rfc2307bis= FALSE;
57   var $OnlyShowFirstEntries =200;
58   var $dnMapping= array();
59   var $view_logged = FALSE;
60   var $allowGroupsWithSameNameInOtherSubtrees = true;
61   var $baseSelector;
63   /* attribute list for save action */
64   var $attributes= array("cn", "description", "gidNumber","memberUid","sambaGroupType","sambaSID");
65   var $objectclasses= array("top", "posixGroup");
67   var $CopyPasteVars  = array("force_gid","fon_group","smbgroup","groupType","sambaSID","sambaDomainName","SID","nagios_group","sambaGroupType");
69   var $multiple_support = TRUE;
72     // Lists 
73     private $memberList;    // Single group editing
74     private $commonList;    // (Multiple support active)
75     private $partialList;   // (Multiple support active)
78   function group (&$config, $dn= NULL)
79   {
80      /* Set rfc2307bis flag */
81      if ($config->get_cfg_value("core","rfc2307bis") == "true"){
82        $this->rfc2307bis= TRUE;
83        $this->attributes[]= "member";
84        $this->objectclasses[]= "groupOfNames";
85      }
87     plugin::plugin ($config, $dn);
89     $this->trustModeDialog = new trustModeDialog($this->config, $this->dn,NULL);
90     $this->trustModeDialog->setAcl('groups/group');
92     /* Load attributes depending on the samba version */
93     $this->orig_dn= $dn;
94     $this->orig_cn= $this->cn;
96     /* Get member list */
97     if (isset($this->attrs['memberUid'][0])){
98       $tmp= array();
99       for ($i= 0; $i<$this->attrs['memberUid']['count']; $i++){
100         $tmp[$this->attrs['memberUid'][$i]]= $this->attrs['memberUid'][$i];
101       }
102       $this->memberUid= $tmp;
103       ksort ($this->memberUid);
104     }
106     /* Save gidNumber for later use */
107     if (isset($this->attrs['gidNumber'])){
108       $this->saved_gidNumber= $this->attrs['gidNumber'][0];
109     }
111     /* Is a samba group? */
112     if (isset($this->attrs['objectClass'])){
113       if (array_search ('sambaGroupMapping', $this->attrs['objectClass']) == FALSE ){
114         $this->smbgroup= FALSE;
115       } else {
116         $this->smbgroup= TRUE;
117         if (isset($this->attrs['sambaSID'])){
118           $this->sambaSID= $this->attrs['sambaSID'][0];
119         }
120       }
121       if (array_search ('goFonPickupGroup', $this->attrs['objectClass']) == FALSE ){
122         $this->fon_group= FALSE;
123       } else {
124         $this->fon_group= TRUE;
125       }
126       if (array_search ('nagiosContactGroup', $this->attrs['objectClass']) == FALSE ){
127         $this->nagios_group= FALSE;
128       } else {
129         $this->nagios_group= TRUE;
130       }
131     }
133     /* Set mail flag */
134     if (isset($this->attrs['objectClass']) && in_array('gosaMailAccount', $this->attrs['objectClass'])){
135       $this->has_mailAccount= TRUE;
136     }
138     /* Get samba Domain in case of samba 3 */
139     if ($this->sambaSID != ""){
140       $this->SID= preg_replace ("/-[^-]+$/", "", $this->sambaSID);
141       $ldap= $this->config->get_ldap_link();
142       $ldap->cd($this->config->current['BASE']);
143       $ldap->search ("(&(objectClass=sambaDomain)(sambaSID=$this->SID))",array("sambaAlgorithmicRidBase"));
144       if ($ldap->count() != 0){
145         $attrs= $ldap->fetch();
146         if(isset($attrs['sambaAlgorithmicRidBase'])){  
147           $this->ridBase= $attrs['sambaAlgorithmicRidBase'][0];  
148         } else {  
149           $this->ridBase= $this->config->get_cfg_value("core","sambaRidBase");
150         } 
152         /* Get domain name for SID */
153         $this->sambaDomainName= "DEFAULT";
154         foreach ($this->config->data['SERVERS']['SAMBA'] as $key => $val){
155           if ($val['SID'] == $this->SID){
156             $this->sambaDomainName= $key;
157             break;
158           }
159         }
160       } else {
161         if ($this->config->get_cfg_value("core","sambaRidBase") != ""){
162           $this->sambaDomainName= "DEFAULT";
163           $this->ridBase= $this->config->get_cfg_value("core","sambaRidBase");
164           $this->SID= $this->config->get_cfg_value("core","sambaSID");
165         } else {
166           msg_dialog::display(_("Configuration error"), _("Cannot find group SID in your configuration!"), ERROR_DIALOG);
167         }
168       }
170       /* Get group type */
171       $this->groupType= (int)substr(strrchr($this->sambaSID, "-"), 1);
172       if ($this->groupType < 500 || $this->groupType > 553){
173         $this->groupType= 0;
174       }
175       $this->oldgroupType= $this->groupType;
176     }
178     if ($this->dn == "new"){
179       if(session::is_set('CurrentMainBase')){
180         $this->base = session::get('CurrentMainBase');
181       }else{
182         $ui= get_userinfo();
183         $this->base= dn2base($ui->dn);
184       }
185     } else {
187       /* Get object base */
188       $this->base =preg_replace ("/^[^,]+,".preg_quote(get_groups_ou(), '/')."/i","",$this->dn);
189     }
190     $this->orig_base = $this->base;
192     /* This is always an account */
193     $this->is_account= TRUE;
195     /* Instanciate base selector */
196     $this->baseSelector= new baseSelector($this->get_allowed_bases(), $this->base);
197     $this->baseSelector->setSubmitButton(false);
198     $this->baseSelector->setHeight(300);
199     $this->baseSelector->update(true);
203     // Prepare lists
204     $this->memberList = new sortableListing();
205     $this->memberList->setDeleteable(true);
206     $this->memberList->setInstantDelete(true);
207     $this->memberList->setEditable(false);
208     $this->memberList->setWidth("100%");
209     $this->memberList->setHeight("300px");
210     $this->memberList->setHeader(array('~',_("Given name"),_("Surename"),_("Uid")));
211     $this->memberList->setColspecs(array('20px','*','*','*','20px'));
212     $this->memberList->setDefaultSortColumn(1);
214     $this->reload(TRUE);
215   }
217   function execute()
218   {
219     /* Call parent execute */
220     plugin::execute();
222     /* Log view */
223     if($this->is_account && !$this->view_logged){
224       $this->view_logged = TRUE;
225       new log("view","groups/".get_class($this),$this->dn);
226     }
228     /* Do we represent a valid group? */
229     if (!$this->is_account && $this->parent === NULL){
230       $display= "<img alt=\"\" src=\"images/small-error.png\" align=\"middle\">&nbsp;<b>".msgPool::noValidExtension()."</b>";
231       return ($display);
232     }
234     // Act on list events 
235     foreach(array('memberList','commonList','partialList') as $list){
237         // Check if list is available, depends on multi- or sinlge- group editing. 
238         if($this->$list){
239             $this->$list->save_object();
240             $action = $this->$list->getAction();
241             if($action['action'] == 'delete' && preg_match("/w/",$this->getacl("memberUid"))){
242                 foreach ($action['targets'] as $id){
243                     $value = $this->$list->getKey($id);
244                     unset ($this->members["$value"]);
245                     $this->removeUser($value);
246                 }
247                 $this->reload();
248             }
249         }
250     }
252     /* Add objects? */
253     if (isset($_POST["edit_membership"]) && preg_match("/w/",$this->getacl("memberUid"))){
254       $this->userSelect= new userSelect($this->config, get_userinfo());
255     }
257     /* Add objects finished? */
258     if (isset($_POST["add_users_cancel"])){
259       $this->userSelect= NULL;
260     }
262     /* Add user to group */
263     if (isset($_POST['add_users_finish']) && $this->userSelect){
264   
265       $users = $this->userSelect->detectPostActions();
266       if(isset($users['targets'])){
267         $headpage = $this->userSelect->getHeadpage();
268         foreach($users['targets'] as $dn){
269           $attrs = $headpage->getEntry($dn);
270           $value = $attrs['uid'][0];
271           $this->addUser($value);
272           $this->members["$value"]= $this->allusers[$value];
273           $this->reload();
274         }
275       }
276       $this->userSelect= NULL;
277     }
279     $smarty= get_smarty();
280  
281     // Handle trust mode dialog
282     $this->dialog = FALSE;
283     $trustModeDialog = $this->trustModeDialog->execute();
284     if($this->trustModeDialog->trustSelect){
285         $this->dialog = TRUE;
286         return($trustModeDialog);
287     }
288     $smarty->assign("trustModeDialog" , $trustModeDialog);
292     $smarty->assign("nagios", $this->config->pluginEnabled("nagiosAccount"));
293     $smarty->assign("pickupGroup", $this->config->pluginEnabled("phoneAccount"));
295     /* Manage object add dialog */
296     if ($this->userSelect){
297       $this->dialog = TRUE;
298       return($this->userSelect->execute());
299     }
301     /* Create base acls */
302     $smarty->assign("base", $this->baseSelector->render());
304     $domains= array();
305     foreach($this->config->data['SERVERS']['SAMBA'] as $name => $content){
306       $domains[$name]= $name;
307     }
308     $smarty->assign("sambaDomains", $domains);
309     $smarty->assign("sambaDomainName", $this->sambaDomainName);
310     $groupTypes= array(0 => _("Samba group"), 512 => _("Domain admins"), 513 => _("Domain users"),
311         514 => _("Domain guests"));
313     /* Don't loose special groups! If not key'ed above, add it to
314        the combo box... */      
315     if ($this->groupType >= 500 && $this->groupType <= 553 && !isset($groupTypes[$this->groupType])){
316       $groupTypes[$this->groupType]= sprintf(_("Special group (%d)"), $this->groupType);
317     }
319     $smarty->assign("groupTypes", $groupTypes);
320     $smarty->assign("groupType", $this->groupType);
321     
323     /* Members and users */
324     if(!$this->multiple_support_active){
325         $this->memberList->setAcl($this->getacl("memberUid"));
326         $data = $lData = array();
327         foreach($this->members as $uid => $member){
328             $data[$uid] = $member;
329             $givenName = $sn = _("Unknown");
330             if(isset($member['sn'][0])) $sn = $member['sn'][0];
331             if(isset($member['givenName'][0])) $givenName = $member['givenName'][0];
332             $image = image('images/false.png');
333             if(isset($member['sn'])){
334                 $image = image('plugins/users/images/select_user.png');
335             }
336             $lData[$uid] = array('data' => array($image,$sn, $givenName, $uid));
337         }
338         $this->memberList->setListData($data,$lData);
339         $this->memberList->update();
340         $smarty->assign("memberList", $this->memberList->render());
341     }else{
342     
343         $this->commonList->setAcl($this->getacl("memberUid"));
344         $this->partialList->setAcl($this->getacl("memberUid"));
346         $data = $lData = array();
347         foreach($this->memberUid as $uid => $member){
348             $member = $this->members[$member];
349             $data[$uid] = $member;
350             $givenName = $sn = _("Unknown");
351             if(isset($member['sn'][0])) $sn = $member['sn'][0];
352             if(isset($member['givenName'][0])) $givenName = $member['givenName'][0];
353             $image = image('images/false.png');
354             if(isset($member['sn'])){
355                 $image = image('plugins/users/images/select_user.png');
356             }
357             $lData[$uid] = array('data' => array($image,$sn, $givenName, $uid));
358         }
359         $this->commonList->setListData($data,$lData);
360         $this->commonList->update();
361         $smarty->assign("commonList", $this->commonList->render());
363         $data = $lData = array();
364         foreach($this->memberUid_used_by_some as $uid => $member){
365             $member = $this->members[$member];
366             $data[$uid] = $member;
367             $givenName = $sn = _("Unknown");
368             if(isset($member['sn'][0])) $sn = $member['sn'][0];
369             if(isset($member['givenName'][0])) $givenName = $member['givenName'][0];
370             $image = image('images/false.png');
371             if(isset($member['sn'])){
372                 $image = image('plugins/users/images/select_user.png');
373             }
374             $lData[$uid] = array('data' => array($image,$sn, $givenName, $uid));
375         }
376         $this->partialList->setListData($data,$lData);
377         $this->partialList->update();
378         $smarty->assign("partialList", $this->partialList->render());
379     }
381     /* Checkboxes */
382     foreach (array("force_gid", "smbgroup") as $val){
383       if ($this->$val == "1"){
384         $smarty->assign("$val", "checked");
385       } else {
386         $smarty->assign("$val", "");
387       }
388     }
389     if ($this->force_gid != "1"){
390       $smarty->assign("forceMode", "disabled");
391     }else{
392       $smarty->assign("forceMode", "");
393     }
394     if ($this->fon_group){
395       $smarty->assign("fon_group", "checked");
396     } else {
397       $smarty->assign("fon_group", "");
398     }
400     if ($this->nagios_group){
401       $smarty->assign("nagios_group", "checked");
402     } else {
403       $smarty->assign("nagios_group", "");
404     }
406     /* Fields */
407     foreach (array("cn", "description", "gidNumber") as $val){
408       $smarty->assign("$val", $this->$val);
409     }
411     $tmp = $this->plInfo();
412     foreach($tmp['plProvidedAcls'] as $name => $translation){
413       $smarty->assign($name."ACL",$this->getacl($name));
414     }
415     
416     if($this->acl_is_writeable("base")){
417       $smarty->assign("baseSelect",true);
418     }else{
419       $smarty->assign("baseSelect",false);
420     }
422     /* Multiple edit handling */
423     $smarty->assign("multiple_support",$this->multiple_support_active);
425     foreach($this->attributes as $val){
426       if(in_array($val,$this->multi_boxes)){
427         $smarty->assign("use_".$val,TRUE);
428       }else{
429         $smarty->assign("use_".$val,FALSE);
430       }
431     }
432     foreach(array("base","smbgroup","groupType","sambaDomainName","fon_group","nagios_group") as $val){
433       if(in_array($val,$this->multi_boxes)){
434         $smarty->assign("use_".$val,TRUE);
435       }else{
436         $smarty->assign("use_".$val,FALSE);
437       }
438     }
440     return($smarty->fetch (get_template_path('generic.tpl', TRUE)));
441   }
443   function addUser($uid)
444   {
445     /* In mutliple edit we have to handle two arrays.
446      *  memberUid               : Containing users used in all groups
447      *  memberUid_used_by_some  : Those which are not used in all groups
448      * So we have to remove the given $uid from the ..used_by_some array first.
449      */
450     if($this->multiple_support_active){
451       if(isset($this->memberUid_used_by_some[$uid])){
452         unset($this->memberUid_used_by_some[$uid]);
453       }
454     }  
456     /* Ensure that the requested object is known to the group class 
457      */
458     if(!isset($this->dnMapping[$uid])){
459       $ldap = $this->config->get_ldap_link();
460       $ldap->cd($this->config->current['BASE']);
461       $ldap->search("(&(objectClass=gosaAccount)(uid=".$uid."))",array("dn", "uid","sn","givenName"));
462       if($ldap->count() == 0 ){
463         msg_dialog::display(_("Error"), 
464             sprintf(_("Adding UID '%s' to group '%s' failed: cannot find user object!"), 
465               $uid,$this->cn), 
466             ERROR_DIALOG);
467         return;
468       }elseif($ldap->count() >= 2){
469         msg_dialog::display(_("Error"), 
470             sprintf(_("Add UID '%s' to group '%s' failed: UID is used more than once!"),
471               $uid,$this->cn), 
472             ERROR_DIALOG);
473         return;
474       }else{
475         while($attrs = $ldap->fetch()){
476           $this->dnMapping[$attrs['uid'][0]] = $attrs['dn'];
477           $this->members[$attrs['uid'][0]] = $attrs;
478           $this->allusers[$attrs['uid'][0]]= $attrs;
479         }
480       }
481     }
483     $this->memberUid[$uid]= $uid;
484   }
487   function removeUser($uid)
488   {
489     $temp= array();
490     if(isset($this->memberUid[$uid])){
491       unset($this->memberUid[$uid]);
492     }
494     /* We have two array contianing group members in multiple edit.
495      *  this->memberUid             : Groups used by all currently edited groups 
496      *  this->memberUid_used_by_some: Used by some 
497      * So we have to remove the specified uid from both arrays.
498      */
499     if($this->multiple_support_active){
500       if(isset($this->memberUid_used_by_some[$uid])){
501         unset($this->memberUid_used_by_some[$uid]);
502       }
503     }
504   }
506   /* Reload data */
507   function reload($silent = FALSE)
508   {
509     /* Prepare ldap link */
510     $ldap= $this->config->get_ldap_link();
511     $ldap->cd($this->config->current['BASE']);
514     /* Resolve still unresolved memberuids to fill the list with sn/giveName attributes 
515         (Store gathered sn/givenName informations in $this->allusers too, 
516          to be prepared when adding/deleting users)
517      */    
518     $filter = "";
520     // Merge in partial uids in multiple edit
521     $uids = array_keys($this->memberUid);
522     if($this->multiple_support_active) {
523         $uids = array_merge($uids,  array_keys($this->memberUid_used_by_some));
524     }
525     
526     if ($this->config->get_cfg_value("core","ldapFilterNestingLimit") == "" ||
527         count($uids) < $this->config->get_cfg_value("core","ldapFilterNestingLimit")){
528       foreach ($uids as $value){
529         if(!isset($this->members[$value])){
530           $filter .= "(uid=".normalizeLdap($value).")";
531         }
532       }
533     }
535     if(!empty($filter)){    
536       $ldap->cd($this->config->current['BASE']);
537       $ldap->search("(&(objectClass=gosaAccount)(|".$filter."))",array("dn", "uid","sn","givenName"));
538       while($attrs = $ldap->fetch()){
539         $this->dnMapping[$attrs['uid'][0]] = $attrs['dn'];
540         $this->members[$attrs['uid'][0]] = $attrs;
541         $this->allusers[$attrs['uid'][0]]= $attrs;
542       } 
543     }
544   
545     /* check if all uids are resolved */
546     if ($this->config->get_cfg_value("core","ldapFilterNestingLimit") == "" ||
547         count($this->memberUid) < $this->config->get_cfg_value("core","ldapFilterNestingLimit")){
548       foreach ($this->memberUid as $value){
549         if(!isset($this->members[$value])){
550           $this->members[$value] = "";
551         }
552       }  
553     }else{
554       foreach ($this->memberUid as $value){
555         $this->members[$value] = "";
556       }  
557     }
558   }
561   /* Create display name, this was used so often that it is excluded into a seperate function */
562   function createResultName($attrs)
563   {
564     if (isset($attrs["givenName"][0]) && isset($attrs["sn"][0])){
565       $ret =  $attrs["sn"][0].", ".$attrs["givenName"][0]." [".$attrs["uid"][0]."]";
566     } else {
567       $ret= $attrs['uid'][0];
568     }
569     return($ret);
570   }
573   function remove_from_parent()
574   {
575     plugin::remove_from_parent();
577     $ldap= $this->config->get_ldap_link();
578     $ldap->rmdir($this->dn);
579     if (!$ldap->success()){
580       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
581     }
583     new log("remove","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
585     /* Delete references to object groups */
586     $ldap->cd ($this->config->current['BASE']);
587     $ldap->search ("(&(objectClass=gosaGroupOfNames)(member=".LDAP::prepare4filter($this->dn)."))", array("cn"));
588     while ($ldap->fetch()){
589       $og= new ogroup($this->config, $ldap->getDN());
590       unset($og->member[$this->dn]);
591       $og->save ();
592     }
594     /* Remove ACL dependencies too,
595      */
596     $ldap = $this->config->get_ldap_link();
597     $ldap->cd($this->config->current['BASE']);
598     $ldap->search("(&(objectClass=gosaAcl)(gosaAclEntry=*".base64_encode($this->dn)."*))",array("gosaAclEntry","dn"));
599     while($attrs = $ldap->fetch()){
600       $acl = new acl($this->config,$this->parent,$attrs['dn']);
601       foreach($acl->gosaAclEntry as $id => $entry){
602         foreach($entry['members'] as $m_id => $member){
603           if($m_id == "G:".$this->dn || $m_id == "U:".$this->dn){
604             unset($acl->gosaAclEntry[$id]['members'][$m_id]);
605             gosa_log("modify","groups/acl",$attrs['dn'],array(),sprintf("Removed acl for %s on object %s.",$this->dn,$attrs['dn']));
606           }
607         }
608       }
609       $acl->save();
610     }
612     /* Remove ACL dependencies, too */
613     acl::remove_acl_for($this->dn);
615     /* Send signal to the world that we've done */
616     $this->handle_post_events("remove");
617   }
620   /* Save data to object */
621   function save_object()
622   {
623     /* Save additional values for possible next step */
624     if (isset($_POST['groupedit'])){
626       /* Create a base backup and reset the 
627           base directly after calling plugin::save_object();  
628          Base will be set seperatly a few lines below */
629       $base_tmp = $this->base;
630       plugin::save_object();
631       $this->trustModeDialog->save_object();
632       $this->base = $base_tmp;
634       /* Refresh base */
635       if ($this->acl_is_moveable($this->base)){
636         if (!$this->baseSelector->update()) {
637           msg_dialog::display(_("Error"), msgPool::permMove(), ERROR_DIALOG);
638         }
639         if ($this->base != $this->baseSelector->getBase()) {
640           $this->base= $this->baseSelector->getBase();
641           $this->is_modified= TRUE;
642         }
643       }
645       $this->force_gid= 0;
647       /* Only reset sambagroup flag if we are able to write this flag */
648       if($this->acl_is_writeable("sambaGroupType")){
649         $this->smbgroup = 0;
650       }
652       foreach (array(
653             "force_gid"  => "gidNumber", 
654             "smbgroup"   => "sambaGroupType") as $val => $aclname) {
655         if ($this->acl_is_writeable($aclname)  && isset($_POST["$val"])){
656           $this->$val= $_POST["$val"];
657         }
658       }
660       /* Save sambaDomain attribute */
661       if ($this->acl_is_writeable("sambaDomainName") && isset ($_POST['sambaDomainName'])){
662         $this->sambaDomainName= $_POST['sambaDomainName'];
663         $this->groupType= $_POST['groupType'];
664       }
666       /* Save fon attribute */
667       if ($this->acl_is_writeable("fonGroup")){
668         if (isset ($_POST['fon_group'])){
669           $this->fon_group= TRUE;
670         } else {
671           $this->fon_group= FALSE;
672         }
673       }
674       if ($this->acl_is_writeable("nagiosGroup")){
675         if (isset ($_POST['nagios_group'])){
676           $this->nagios_group= TRUE;
677         } else {
678           $this->nagios_group= FALSE;
679         }
680       }
681     }
682   }
685   /* Save to LDAP */
686   function save()
687   {
689     /* ID handling */
690     if ($this->force_gid == 0){
691       if ($this->saved_gidNumber != ""){
692         $this->gidNumber= $this->saved_gidNumber;
693       } else {
694         /* Calculate new, lock uids */
695         $wait= 10;
696         while (get_lock("gidnumber") != ""){
697           sleep (1);
699           /* timed out? */
700           if ($wait-- == 0){
701             break;
702           }
703         }
704         add_lock ("gidnumber", "gosa");
705         $this->gidNumber= get_next_id("gidNumber", $this->dn);
706       }
707     }
708   
709     plugin::save(); 
711     /* Remove objectClass for samba/phone support */
712     $tmp= array();
713     for ($i= 0; $i<count($this->attrs["objectClass"]); $i++){
714       if ($this->attrs['objectClass'][$i] != 'sambaGroupMapping' &&
715           $this->attrs['objectClass'][$i] != 'sambaIdmapEntry' &&
716           $this->attrs['objectClass'][$i] != 'goFonPickupGroup' &&
717          $this->attrs['objectClass'][$i] != 'nagiosContactGroup'){
718         $tmp[]= $this->attrs['objectClass'][$i];
719       }
720     }
721     $this->attrs['objectClass']= $tmp;
722     $ldap= $this->config->get_ldap_link();
724     /* Add samba group functionality */
725     if ($this->smbgroup){
726   
727       /* Fixed undefined index ... 
728        */ 
729       $this->SID = $this->ridBase = "";
730       if(isset($this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['SID'])){
731         $this->SID    = $this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['SID'];
732       }else{
733         msg_dialog::display(_("Error"), sprintf(_("Cannot find any SID for '%s'!"), $this->sambaDomainName), ERROR_DIALOG);
734       }
735       if(isset($this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['RIDBASE'])){
736         $this->ridBase= $this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['RIDBASE']; 
737       }else{
738         msg_dialog::display(_("Error"), sprintf(_("Cannot find any RIDBASE for '%s'!"), $this->sambaDomainName), ERROR_DIALOG);
739       }
741       $this->attrs['objectClass'][]= 'sambaGroupMapping';
742       $this->attrs['sambaGroupType']= "2";
744       /* Check if we need to create a special entry */
745       if ($this->groupType == 0){
747         if ($this->sambaSID == "" || $this->oldgroupType != $this->groupType){
748           $sid = $this->getSambaSID();
749           $this->attrs['sambaSID']= $sid;
750           $this->sambaSID= $sid;
751         }
753       } else {
754         $this->attrs['sambaSID']=$this->SID."-".$this->groupType;
755       }
757       /* User wants me to fake the idMappings? This is useful for
758          making winbind resolve the group names in a reasonable amount
759          of time in combination with larger databases. */
760       if ($this->config->boolValueIsTrue("core","sambaIdMapping")){
761         $this->attrs['objectClass'][]= "sambaIdmapEntry";
762       }
764     }
766     /* Add phone functionality */
767     if ($this->fon_group){
768       $this->attrs['objectClass'][]= "goFonPickupGroup";
769     }
771     /* Add nagios functionality */
772     if ($this->nagios_group){
773       $this->attrs['objectClass'][]= "nagiosContactGroup";
774     }
776     /* Take members array */
777     if (count ($this->memberUid)){
778       $this->attrs['memberUid']= array_values(array_unique($this->memberUid));
779     }
781     /* New accounts need proper 'dn', propagate it to remaining objects */
782     if ($this->dn == 'new'){
783       $this->dn= 'cn='.$this->cn.','.get_groups_ou().$this->base;
784     }
786     /* Add member dn's for RFC2307bis Support */
787     if ($this->rfc2307bis){
788       $this->attrs['member'] = array();
789       if (count($this->memberUid)){
790         foreach($this->attrs['memberUid'] as $uid) {
792           if(isset($this->dnMapping[$uid])){
793             $this->attrs['member'][]= $this->dnMapping[$uid];
794           }
795         }
796       } else {
797         $this->attrs['member'][]= $this->dn;
798       }
799     }
801     /* Save data. Using 'modify' implies that the entry is already present, use 'add' for
802        new entries. So do a check first... */
803     $ldap->cat ($this->dn, array('dn'));
804     if ($ldap->fetch()){
805       /* Modify needs array() to remove values :-( */
806       if (!count ($this->memberUid)){
807         $this->attrs['memberUid']= array();
808       }
809       if (!$this->smbgroup){
810         $this->attrs['sambaGroupType']= array();
811         $this->attrs['sambaSID']= array();
812       }
813       
814       $mode= "modify";
815     } else {
816       $mode= "add";
817       $ldap->cd($this->config->current['BASE']);
818       $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
819     }
821     /* Check generated gidNumber, it may be used by another group. 
822      */
823     if($this->gidNumber != ""){
824       $ldap->cd($this->config->current['BASE']);
825       $ldap->search("(&(!(cn=".$this->orig_cn."))(objectClass=posixGroup)(gidNumber=".$this->gidNumber."))",array("cn"));
826       if($ldap->count()){
827         $cns = "";
828         while($attrs = $ldap->fetch()){
829           $cns .= $attrs['cn'][0].", ";
830         }
831         $cns = rtrim($cns,", ");
832         msg_dialog::display(_("Warning"),sprintf(_("The gidNumber '%s' is already in use by %s!"),$this->gidNumber,$cns) , WARNING_DIALOG );
833       }
834     }
836     /* Write back to ldap */
837     $ldap->cd($this->dn);
838     $this->cleanup();
839     $ldap->$mode($this->attrs);
841     /* Remove ACL dependencies too,
842      */
843     if($this->dn != $this->orig_dn && $this->orig_dn != "new"){
844       $tmp = new acl($this->config,$this->parent,$this->dn);
845       $tmp->update_acl_membership($this->orig_dn,$this->dn);
846     }
848     if($this->initially_was_account){
849       new log("modify","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
850     }else{
851       new log("create","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
852     }
854     $ret= 0;
855     if (!$ldap->success()){
856       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, 0, get_class()));
857       $ret= 1;
858     }
860     $this->trustModeDialog->dn = $this->dn;
861     $this->trustModeDialog->save();
863     /* Remove uid lock */
864     del_lock ("gidnumber");
866     /* Post that we've done*/
867     $this->handle_post_events($mode);
869     return ($ret);
870   }
872   function check()
873   {
874     /* Call common method to give check the hook */
875     $message= plugin::check();
877     /* Permissions for that base? */
878     if ($this->base != ""){
879       $new_dn= 'cn='.$this->cn.','.get_groups_ou().$this->base;
880     } else {
881       $new_dn= $this->dn;
882     }
884     /* must: cn */
885     if ($this->cn == "" && $this->acl_is_writeable("cn")){
886       $message[]= msgPool::required(_("Name"));
887     }
889     // Check if a wrong base was supplied
890     if(!$this->baseSelector->checkLastBaseUpdate()){
891       $message[]= msgPool::check_base();;
892     }
894     /* Check for valid input */
895     if (!tests::is_uid($this->cn)){
896       if (strict_uid_mode()){
897         $message[]= msgPool::invalid(_("Name"), $this->cn, "/[a-z0-9_-]/");
898       } else {
899         $message[]= msgPool::invalid(_("Name"), $this->cn, "/[a-z0-9_-]/i");
900       }
901     }
903     // Check if a wrong base was supplied
904     if(!$this->baseSelector->checkLastBaseUpdate()){
905       $message[]= msgPool::check_base();;
906     }
908     if($this->allowGroupsWithSameNameInOtherSubtrees == true){
910       /* Check for used 'cn' */
911       $ldap= $this->config->get_ldap_link();
912       if(($this->cn  != $this->orig_cn) || ($this->orig_dn == "new")){
913         $ldap->cd(get_groups_ou().$this->base);
914         $ldap->ls("(&(|(objectClass=gosaGroupOfNames)(objectClass=posixGroup))(cn=$this->cn))",get_groups_ou().$this->base,array("cn"));
915         if ($ldap->count() != 0){
916           $message[]= msgPool::duplicated(_("Name"));
917         }
918       }
920     }else{
922       /* Check for used 'cn' */
923       $ldap= $this->config->get_ldap_link();
924       $ldap->cd($this->config->current['BASE']);
925       $ldap->search("(&(|(objectClass=gosaGroupOfNames)(objectClass=posixGroup))(cn=$this->cn))",array("cn"));
926       if ($ldap->count() != 0){
928         /* New entry? */
929         if ($this->dn == 'new'){
930           $message[]= msgPool::duplicated(_("Name"));
931         }
933         /* Moved? */
934         elseif ($new_dn != $this->orig_dn){
935           $ldap->fetch();
936           if ($ldap->getDN() != $this->orig_dn){
937             $message[]= msgPool::duplicated(_("Name"));
938           }
939         }
940       }
941     }
942      
943     /* Check ID */
944     if ($this->force_gid == "1"){
945       if (!tests::is_id($this->gidNumber)){
946         $message[]= msgPool::invalid(_("GID"), $this->gidNumber, "/[0-9]/");
947       } else {
948         if ($this->gidNumber < $this->config->get_cfg_value("core","minId")){
949           $message[]= msgPool::toosmall(_("GID"), $this->config->get_cfg_value("core","minId"));
950         }
952       }
953     }
954     
955     /* Check if we are allowed to create or move this object 
956      */
957     if(!$this->orig_dn == "new" || 
958         $this->orig_base != $this->base || 
959         $this->cn != $this->orig_cn){
961       if($this->orig_dn == "new" && !$this->acl_is_createable($this->base)){
962         $message[] = msgPool::permCreate();
963       }elseif($this->orig_dn != "new" && !$this->acl_is_moveable($this->base)){
964         $message[] = msgPool::permMove();
965       }
966     }
968     return ($message);
969   }
972   function getCopyDialog()
973   {
974     $vars = array("cn");
975   
976     if($this ->force_gid){
977       $used = " checked ";
978       $dis  = "";
979     }else{
980       $used = "";
981       $dis  = " disabled ";
982     }
984     $smarty = get_smarty();
985     $smarty->assign("used",$used);
986     $smarty->assign("dis" ,$dis);
987     $smarty->assign("cn" ,$this->cn);
988     $smarty->assign("gidNumber",$this->gidNumber);
989     $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE));
990     $ret = array();
991     $ret['string'] = $str;
992     $ret['status'] = "";
993     return($ret);
994   }
996   function saveCopyDialog()
997   {
998     if(isset($_POST['cn'])){
999       $this->cn = $_POST['cn'];
1000     }
1001     if(isset($_POST['force_gid'])){
1002       $this->force_gid  = 1;
1003       $this->gidNumber= $_POST['gidNumber'];
1004     }else{
1005       $this->force_gid  = 0;
1006       $this->gidNumber  = false;
1007     }
1008   }
1010   
1011   /* Return plugin informations for acl handling  */ 
1012   static function plInfo()
1013   {
1014     return (array(  
1015           "plShortName" => _("Generic"),
1016           "plDescription" => _("Generic group settings"),
1017           "plSelfModify"  => FALSE,
1018           "plDepends"     => array(),
1019           "plPriority"    => 0,
1020           "plSection"     => array("administration"),
1021           "plCategory"    => array("groups" => array("objectClass" => "posixGroup", "description" => _("Groups"))),
1023           "plProperties" =>
1024           array(
1025               array(
1026                   "name"          => "ogroupRDN",
1027                   "type"          => "rdn",
1028                   "default"       => "ou=groups,",
1029                   "description"   => _("The 'ogroupRDN' statement defines the location where new accounts will be created. The default is 'ou=groups,'."),
1030                   "check"         => "gosaProperty::isRdn",
1031                   "migrate"       => "migrate_ogroupRDN",
1032                   "group"         => "plugin",
1033                   "mandatory"     => FALSE)),
1036           "plProvidedAcls"    => array(
1037             "cn"                => _("Name"),
1038             "description"       => _("Description"),
1039             "base"              => _("Base"),
1041             "gidNumber"         => _("GID"),
1043             "sambaGroupType"    => _("Samba group type"),
1044             "sambaDomainName"   => _("Samba domain name"),
1045             "accessTo"        => _("System trust"),
1046             "fonGroup"          => _("Phone pickup group"),
1047             "nagiosGroup"       => _("Nagios group"),
1049             "memberUid"         => _("Group member"))
1050         ));
1051   }
1054   function multiple_save_object()
1055   {
1056     if(isset($_POST['group_mulitple_edit'])){
1058       /* Create a base backup and reset the
1059          base directly after calling plugin::save_object();
1060          Base will be set seperatly a few lines below */
1061       $base_tmp = $this->base;
1062       plugin::multiple_save_object();
1063       plugin::save_object();
1064       $this->trustModeDialog->multiple_save_object();
1065       $this->base = $base_tmp;
1067       foreach(array("base","smbgroup","groupType","sambaDomainName","fon_group","nagios_group") as $attr){
1068         if(isset($_POST['use_'.$attr])){
1069           $this->multi_boxes[] = $attr;
1070         }
1071       }
1073       /* Refresh base */
1074       if ($this->acl_is_moveable($this->base)){
1075         if (!$this->baseSelector->update()) {
1076           msg_dialog::display(_("Error"), msgPool::permMove(), ERROR_DIALOG);
1077         }
1078         if ($this->base != $this->baseSelector->getBase()) {
1079           $this->base= $this->baseSelector->getBase();
1080           $this->is_modified= TRUE;
1081         }
1082       }
1084       foreach (array( "smbgroup"   => "sambaGroupType" ,"nagios_group" => "nagiosGroup") as $val => $aclname) {
1085         if ($this->acl_is_writeable($aclname)){
1086           if(isset($_POST["$val"])){
1087             $this->$val=  TRUE;
1088           }else{
1089             $this->$val=  FALSE;
1090           }
1091         }
1092       }
1094       /* Save sambaDomain attribute */
1095       if ($this->acl_is_writeable("sambaDomainName") && isset ($_POST['sambaDomainName'])){
1096         $this->sambaDomainName= $_POST['sambaDomainName'];
1097         $this->groupType= $_POST['groupType'];
1098       }
1100       /* Save fon attribute */
1101       if ($this->acl_is_writeable("fonGroup")){
1102         if (isset ($_POST['fon_group'])){
1103           $this->fon_group= TRUE;
1104         } else {
1105           $this->fon_group= FALSE;
1106         }
1107       }
1108     }
1109   }
1112   function get_multi_edit_values()
1113   {
1114     $ret = plugin::get_multi_edit_values();
1115     $ret = array_merge($ret,$this->trustModeDialog->get_multi_edit_values());
1117     foreach(array("base","smbgroup","groupType","sambaDomainName","fon_group","nagios_group") as $attr){    
1118       if(in_array($attr,$this->multi_boxes)){
1119         $ret[$attr] = $this->$attr;
1120       }
1121     }
1123     $ret['memberUid'] = $this->memberUid;
1124     $ret['memberUid_used_by_some'] = $this->memberUid_used_by_some;
1125     return($ret);
1126   }
1128   function multiple_execute()
1129   {
1130     return($this->execute());
1131   }
1134   /* Initialize plugin with given atribute arrays
1135    */
1136   function init_multiple_support($attrs,$all)
1137   {
1138     plugin::init_multiple_support($attrs,$all);
1139     $this->trustModeDialog->init_multiple_support($attrs,$all);
1141     $this->memberUid = array();
1142     $this->memberUid_used_by_some = array();
1143     if (isset($attrs['memberUid'])){
1144       for ($i= 0; $i<$attrs['memberUid']['count']; $i++){
1145         $this->memberUid[$attrs['memberUid'][$i]]= $attrs['memberUid'][$i];
1146       }
1147       ksort($this->memberUid);
1148     }
1150     if (isset($all['memberUid'])){
1151       for ($i= 0; $i<$all['memberUid']['count']; $i++){
1152         if(!in_array($all['memberUid'][$i],$this->memberUid)){
1153           $this->memberUid_used_by_some[$all['memberUid'][$i]]= $all['memberUid'][$i];
1154         }
1155       }
1156       ksort($this->memberUid_used_by_some);
1157     }
1159     $this->reload(TRUE);
1161     // We've two lists in mutliple support  
1162     //  - one which represents those users which are part of ALL groups.
1163     //  - ond one which represents those users which are only part of SOME groups.
1164     $this->commonList = new sortableListing();
1165     $this->commonList->setDeleteable(true);
1166     $this->commonList->setInstantDelete(true);
1167     $this->commonList->setEditable(false);
1168     $this->commonList->setWidth("100%");
1169     $this->commonList->setHeight("120px");
1170     $this->commonList->setHeader(array('~',_("Given name"),_("Surename"),_("Uid")));
1171     $this->commonList->setColspecs(array('20px','*','*','*','20px'));
1172     $this->commonList->setDefaultSortColumn(1);
1174     $this->partialList = new sortableListing();
1175     $this->partialList->setDeleteable(true);
1176     $this->partialList->setInstantDelete(true);
1177     $this->partialList->setEditable(false);
1178     $this->partialList->setWidth("100%");
1179     $this->partialList->setHeight("120px");
1180     $this->partialList->setHeader(array('~',_("Given name"),_("Surename"),_("Uid")));
1181     $this->partialList->setColspecs(array('20px','*','*','*','20px'));
1182     $this->partialList->setDefaultSortColumn(1);
1183   }
1186   function PrepareForCopyPaste($source)
1187   {
1188       plugin::PrepareForCopyPaste($source);
1190       $this->trustModeDialog->PrepareForCopyPaste($source);
1192       /* Get samba Domain in case of samba 3 */
1193       if ($this->sambaSID != ""){
1194           $this->SID= preg_replace ("/-[^-]+$/", "", $this->sambaSID);
1195           $ldap= $this->config->get_ldap_link();
1196           $ldap->cd($this->config->current['BASE']);
1197           $ldap->search ("(&(objectClass=sambaDomain)(sambaSID=$this->SID))",array("sambaAlgorithmicRidBase"));
1198           if ($ldap->count() != 0){
1199               $attrs= $ldap->fetch();
1200               if(isset($attrs['sambaAlgorithmicRidBase'])){
1201                   $this->ridBase= $attrs['sambaAlgorithmicRidBase'][0];
1202               } else {
1203                   $this->ridBase= $this->config->get_cfg_value("core","sambaRidBase");
1204               }
1206               /* Get domain name for SID */
1207               $this->sambaDomainName= "DEFAULT";
1208               foreach ($this->config->data['SERVERS']['SAMBA'] as $key => $val){
1209                   if ($val['SID'] == $this->SID){
1210                       $this->sambaDomainName= $key;
1211                       break;
1212                   }
1213               }
1214           } else {
1215               if ($this->config->get_cfg_value("core","sambaRidBase") != ""){
1216                   $this->sambaDomainName= "DEFAULT";
1217                   $this->ridBase= $this->config->get_cfg_value("core","sambaRidBase");
1218                   $this->SID= $this->config->get_cfg_value("core","sambaSID");
1219               } else {
1220                   msg_dialog::display(_("Configuration error"), _("Cannot find group SID in your configuration!"), ERROR_DIALOG);
1221               }
1222           }
1224           /* Get group type */
1225           $this->groupType= (int)substr(strrchr($this->sambaSID, "-"), 1);
1226           if ($this->groupType < 500 || $this->groupType > 553){
1227               $this->groupType= 0;
1228           }
1229           $this->oldgroupType= $this->groupType;
1230       }
1232       // Detect samba groups and adapt its values.
1233       $this->smbgroup = in_array('sambaGroupMapping', $source['objectClass']);
1234       if ($this->smbgroup) { 
1235           $this->sambaSID = $this->getSambaSID(); 
1236       } 
1238       $this->memberUid = array();
1239       if(isset($source['memberUid'])){
1240           for($i = 0 ; $i < $source['memberUid']['count']; $i ++){
1241               $this->memberUid[] = $source['memberUid'][$i];
1242           }
1243       }
1244   }
1247   function set_acl_base($base)
1248   {
1249     plugin::set_acl_base($base);
1250     $this->trustModeDialog->set_acl_base($base);
1251   }
1254   /*! \brief  Enables multiple support for this plugin
1255    */
1256   function enable_multiple_support()
1257   {
1258     plugin::enable_multiple_support();
1259     $this->trustModeDialog->enable_multiple_support();
1260   }
1263   function set_multi_edit_values($attrs)
1264   {
1265     $users = array();
1267     /* Update groupMembership, keep optinal group */
1268     foreach($attrs['memberUid_used_by_some'] as $uid){
1269       if(in_array($uid,$this->memberUid)){
1270         $users[$uid] = $uid;
1271       }
1272     }
1274     /* Update groupMembership, add forced groups */
1275     foreach($attrs['memberUid'] as $uid){
1276       $users[$uid] = $uid;
1277     }
1278     plugin::set_multi_edit_values($attrs);
1279     $this->trustModeDialog->set_multi_edit_values($attrs);
1280     $this->memberUid = $users;
1281   }
1284   /*! \brief Get a new SambaSID for a group */ 
1285   function getSambaSID() 
1286   { 
1287     $ldap = $this->config->get_ldap_link(); 
1288     $gidNumber= $this->gidNumber; 
1289     while(TRUE){ 
1290       $sid= $this->SID."-".($gidNumber*2 + $this->ridBase+1); 
1291       $ldap->cd($this->config->current['BASE']); 
1292       $ldap->search("(sambaSID=$sid)",array("sambaSID")); 
1293       if ($ldap->count() == 0){ 
1294         break; 
1295       } 
1296       $gidNumber++; 
1297     } 
1298   
1299     return $sid; 
1300   } 
1303 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1304 ?>