Code

Updated group handling.
[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(false);
207         $this->memberList->setEditable(false);
208         $this->memberList->setWidth("100%");
209         $this->memberList->setHeight("300px");
210         $this->memberList->setHeader(array('~',_("Given name"),_("Surname"),_("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){
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();
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") && class_available("nagiosAccount"));
293         $smarty->assign("pickupGroup", $this->config->pluginEnabled("phoneAccount") && class_available("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",     set_post($domains));
309         $smarty->assign("sambaDomainName",  set_post($this->sambaDomainName));
310         $groupTypes= array(0 => _("Samba group"), 512 => _("Domain administrators"), 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", set_post($groupTypes));
320         $smarty->assign("groupType",  set_post($this->groupType));
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']) && isset($member['sn'][0])) $sn = $member['sn'][0];
331                 if(isset($member['givenName']) && 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             $bool = $this->isRestrictedByDynGroup();
340             $this->memberList->setDeleteable(!$bool);
341             $this->memberList->update();
342             $smarty->assign("memberList", $this->memberList->render());
343         }else{
345             $this->commonList->setAcl($this->getacl("memberUid"));
346             $this->partialList->setAcl($this->getacl("memberUid"));
348             $data = $lData = array();
349             foreach($this->memberUid as $uid => $member){
350                 $member = $this->members[$member];
351                 $data[$uid] = $member;
352                 $givenName = $sn = _("Unknown");
353                 if(isset($member['sn'][0])) $sn = $member['sn'][0];
354                 if(isset($member['givenName'][0])) $givenName = $member['givenName'][0];
355                 $image = image('images/false.png');
356                 if(isset($member['sn'])){
357                     $image = image('plugins/users/images/select_user.png');
358                 }
359                 $lData[$uid] = array('data' => array($image,$sn, $givenName, $uid));
360             }
361             $this->commonList->setListData($data,$lData);
362             $this->commonList->update();
363             $smarty->assign("commonList", $this->commonList->render());
365             $data = $lData = array();
366             foreach($this->memberUid_used_by_some as $uid => $member){
367                 $member = (isset($this->members[$member])) ? $this->members[$member] : NULL;
368                 $data[$uid] = $member;
369                 $givenName = $sn = _("Unknown");
370                 if(isset($member['sn']) && isset($member['sn'][0])) $sn = $member['sn'][0];
371                 if(isset($member['givenName'][0]) && isset($member['givenName'][0])) $givenName = $member['givenName'][0];
372                 $image = image('images/false.png');
373                 if(isset($member['sn'])){
374                     $image = image('plugins/users/images/select_user.png');
375                 }
376                 $lData[$uid] = array('data' => array($image,$sn, $givenName, $uid));
377             }
378             $this->partialList->setListData($data,$lData);
379             $this->partialList->update();
380             $smarty->assign("partialList", $this->partialList->render());
381         }
383         /* Checkboxes */
384         foreach (array("force_gid", "smbgroup") as $val){
385             if ($this->$val == "1"){
386                 $smarty->assign("$val", "checked");
387             } else {
388                 $smarty->assign("$val", "");
389             }
390         }
391         if ($this->force_gid != "1"){
392             $smarty->assign("forceMode", "disabled");
393         }else{
394             $smarty->assign("forceMode", "");
395         }
396         if ($this->fon_group){
397             $smarty->assign("fon_group", "checked");
398         } else {
399             $smarty->assign("fon_group", "");
400         }
402         if ($this->nagios_group){
403             $smarty->assign("nagios_group", "checked");
404         } else {
405             $smarty->assign("nagios_group", "");
406         }
408         /* Fields */
409         foreach (array("cn", "description", "gidNumber") as $val){
410             $smarty->assign("$val", set_post($this->$val));
411         }
413         $tmp = $this->plInfo();
414         foreach($tmp['plProvidedAcls'] as $name => $translation){
415             $smarty->assign($name."ACL",$this->getacl($name));
416         }
418         if($this->acl_is_writeable("base")){
419             $smarty->assign("baseSelect",true);
420         }else{
421             $smarty->assign("baseSelect",false);
422         }
424         /* Multiple edit handling */
425         $smarty->assign("multiple_support",$this->multiple_support_active);
427         foreach($this->attributes as $val){
428             if(in_array($val,$this->multi_boxes)){
429                 $smarty->assign("use_".$val,TRUE);
430             }else{
431                 $smarty->assign("use_".$val,FALSE);
432             }
433         }
434         foreach(array("base","smbgroup","groupType","sambaDomainName","fon_group","nagios_group") as $val){
435             if(in_array($val,$this->multi_boxes)){
436                 $smarty->assign("use_".$val,TRUE);
437             }else{
438                 $smarty->assign("use_".$val,FALSE);
439             }
440         }
442         $bool = $this->isRestrictedByDynGroup();
443         $smarty->assign("restrictedByDynGroup", $bool);
444         if($bool){
445             $smarty->assign("memberUidACL", preg_replace("/[^r]/","",$this->getacl('memberUid')));
446              
447         }
448         return($smarty->fetch (get_template_path('generic.tpl', TRUE)));
449     }
452     function isRestrictedByDynGroup()
453     {
454         $bool = FALSE;
455         if(isset($this->parent->by_object['DynamicLdapGroup'])){
456             $bool = $this->parent->by_object['DynamicLdapGroup']->isAttributeDynamic('memberUid') ||
457                 $this->parent->by_object['DynamicLdapGroup']->isAttributeDynamic('member');
458         }
459         return($bool);
460     }
462     function addUser($uid)
463     {
464         /* In mutliple edit we have to handle two arrays.
465          *  memberUid               : Containing users used in all groups
466          *  memberUid_used_by_some  : Those which are not used in all groups
467          * So we have to remove the given $uid from the ..used_by_some array first.
468          */
469         if($this->multiple_support_active){
470             if(isset($this->memberUid_used_by_some[$uid])){
471                 unset($this->memberUid_used_by_some[$uid]);
472             }
473         }  
475         /* Ensure that the requested object is known to the group class 
476          */
477         if(!isset($this->dnMapping[$uid])){
478             $ldap = $this->config->get_ldap_link();
479             $ldap->cd($this->config->current['BASE']);
480             $ldap->search("(&(objectClass=gosaAccount)(uid=".$uid."))",array("dn", "uid","sn","givenName"));
481             if($ldap->count() == 0 ){
482                 msg_dialog::display(_("Error"), 
483                         sprintf(_("Adding UID '%s' to group '%s' failed: cannot find user object!"), 
484                             $uid,$this->cn), 
485                         ERROR_DIALOG);
486                 return;
487             }elseif($ldap->count() >= 2){
488                 msg_dialog::display(_("Error"), 
489                         sprintf(_("Add UID '%s' to group '%s' failed: UID is used more than once!"),
490                             $uid,$this->cn), 
491                         ERROR_DIALOG);
492                 return;
493             }else{
494                 while($attrs = $ldap->fetch()){
495                     $this->dnMapping[$attrs['uid'][0]] = $attrs['dn'];
496                     $this->members[$attrs['uid'][0]] = $attrs;
497                     $this->allusers[$attrs['uid'][0]]= $attrs;
498                 }
499             }
500         }
501         
502         $this->memberUid[$uid]= $uid;
503         $this->reload();
504     }
507     function removeUser($uid)
508     {
509         $temp= array();
510         if(isset($this->memberUid[$uid])){
511             unset($this->memberUid[$uid]);
512         }
514         /* We have two array contianing group members in multiple edit.
515          *  this->memberUid             : Groups used by all currently edited groups 
516          *  this->memberUid_used_by_some: Used by some 
517          * So we have to remove the specified uid from both arrays.
518          */
519         if($this->multiple_support_active){
520             if(isset($this->memberUid_used_by_some[$uid])){
521                 unset($this->memberUid_used_by_some[$uid]);
522             }
523         }
524     }
526     /* Reload data */
527     function reload($silent = FALSE)
528     {
529         /* Prepare ldap link */
530         $ldap= $this->config->get_ldap_link();
531         $ldap->cd($this->config->current['BASE']);
534         /* Resolve still unresolved memberuids to fill the list with sn/giveName attributes 
535            (Store gathered sn/givenName informations in $this->allusers too, 
536            to be prepared when adding/deleting users)
537          */    
538         $filter = "";
540     
542         // Merge in partial uids in multiple edit
543         $allUids = array_keys($this->memberUid);
544         if($this->multiple_support_active) {
545             $allUids = array_merge($allUids,  array_keys($this->memberUid_used_by_some));
546         }
548         // Do not request data for users we've already fetched before.
549         foreach($allUids as $key => $uid){
550             if(isset($this->dnMapping[$uid])) unset($allUids[$key]);
551         }
552         $allUids = array_values($allUids);
554         // To resolve the usernames out of the 'uid' we've to perform ldap queries. 
555         // To keep the amount of queries as short as possible, we combine the query 
556         //  for 'sn','givenName','..' for serveral users in one single query:
557         //      (|(uid=hans)(uid=peter)(uid=hubert)(..))
558         // 
559         // Unfortunately there is a filter length limit which causes the query to be invalid,
560         //  we've to split these huge query again into shorter query strings. 
561         // 
562         // maxPerRound specifies the amount of queries we can combine into a 
563         //  single query.
564         $maxPerRound = $this->config->get_cfg_value("core","ldapFilterNestingLimit");
565         if( $maxPerRound == "" ) {
566             $maxPerRound = count($allUids);
567         }
569         for ( $added = 0; $added < count($allUids); $added += $maxPerRound ) {
571             // First build the query....
572             $start = $added;
573             $end = $added + $maxPerRound;
574             $filter = "";
575             for ( $done = $start; $done < $end; $done++ ) {
576                 if(!isset($allUids[$done])) break;
577                 $value = $allUids[$done];
578                 $filter .= "(uid=".normalizeLdap($value).")";
579             }
581             // Retrieve the data to LDAP
582             $ldap->cd($this->config->current['BASE']);
583             $ldap->search("(&(objectClass=gosaAccount)(|".$filter."))",array("dn", "uid","sn","givenName"));
584             while( $attrs = $ldap->fetch() ) {
585                 $this->dnMapping[$attrs['uid'][0]] = $attrs['dn'];
586                 $this->members[$attrs['uid'][0]] = $attrs;
587                 $this->allusers[$attrs['uid'][0]]= $attrs;
588             }
589         }
591         /* check if all uids are resolved */
592         foreach ($this->memberUid as $value){
593             if(!isset($this->members[$value])){
594                 $this->members[$value] = "";
595             }
596         }  
597     }
600     /* Create display name, this was used so often that it is excluded into a seperate function */
601     function createResultName($attrs)
602     {
603         if (isset($attrs["givenName"][0]) && isset($attrs["sn"][0])){
604             $ret =  $attrs["sn"][0].", ".$attrs["givenName"][0]." [".$attrs["uid"][0]."]";
605         } else {
606             $ret= $attrs['uid'][0];
607         }
608         return($ret);
609     }
612     function remove_from_parent()
613     {
614         plugin::remove_from_parent();
616         $ldap= $this->config->get_ldap_link();
617         $ldap->rmdir($this->dn);
618         if (!$ldap->success()){
619             msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
620         }
622         new log("remove","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
624         /* Delete references to object groups */
625         $ldap->cd ($this->config->current['BASE']);
626         $ldap->search ("(&(objectClass=gosaGroupOfNames)(member=".LDAP::prepare4filter($this->dn)."))", array("cn"));
627         while ($ldap->fetch()){
628             $og= new ogroup($this->config, $ldap->getDN());
629             unset($og->member[$this->dn]);
630             $og->save ();
631         }
633         /* Remove ACL dependencies too,
634          */
635         $ldap = $this->config->get_ldap_link();
636         $ldap->cd($this->config->current['BASE']);
637         $ldap->search("(&(objectClass=gosaAcl)(gosaAclEntry=*".base64_encode($this->dn)."*))",array("gosaAclEntry","dn"));
638         while($attrs = $ldap->fetch()){
639             $acl = new acl($this->config,$this->parent,$attrs['dn']);
640             foreach($acl->gosaAclEntry as $id => $entry){
641                 foreach($entry['members'] as $m_id => $member){
642                     if($m_id == "G:".$this->dn || $m_id == "U:".$this->dn){
643                         unset($acl->gosaAclEntry[$id]['members'][$m_id]);
644                         gosa_log("modify","groups/acl",$attrs['dn'],array(),sprintf("Removed acl for %s on object %s.",$this->dn,$attrs['dn']));
645                     }
646                 }
647             }
648             $acl->save();
649         }
651         /* Remove ACL dependencies, too */
652         acl::remove_acl_for($this->dn);
654         /* Send signal to the world that we've done */
655         $this->handle_post_events("remove");
656     }
659     /* Save data to object */
660     function save_object()
661     {
662         /* Save additional values for possible next step */
663         if (isset($_POST['groupedit'])){
665             /* Create a base backup and reset the 
666                base directly after calling plugin::save_object();  
667                Base will be set seperatly a few lines below */
668             $base_tmp = $this->base;
669             plugin::save_object();
670             $this->trustModeDialog->save_object();
671             $this->base = $base_tmp;
673             /* Refresh base */
674             if ($this->acl_is_moveable($this->base)){
675                 if (!$this->baseSelector->update()) {
676                     msg_dialog::display(_("Error"), msgPool::permMove(), ERROR_DIALOG);
677                 }
678                 if ($this->base != $this->baseSelector->getBase()) {
679                     $this->base= $this->baseSelector->getBase();
680                     $this->is_modified= TRUE;
681                 }
682             }
684             $this->force_gid= 0;
686             /* Only reset sambagroup flag if we are able to write this flag */
687             if($this->acl_is_writeable("sambaGroupType")){
688                 $this->smbgroup = 0;
689             }
691             foreach (array(
692                         "force_gid"  => "gidNumber", 
693                         "smbgroup"   => "sambaGroupType") as $val => $aclname) {
694                 if ($this->acl_is_writeable($aclname)  && isset($_POST["$val"])){
695                     $this->$val= get_post($val);
696                 }
697             }
699             /* Save sambaDomain attribute */
700             if ($this->acl_is_writeable("sambaDomainName") && isset ($_POST['sambaDomainName'])){
701                 $this->sambaDomainName= get_post('sambaDomainName');
702                 $this->groupType= get_post('groupType');
703             }
705             /* Save fon attribute */
706             if ($this->acl_is_writeable("fonGroup")){
707                 if (isset ($_POST['fon_group'])){
708                     $this->fon_group= TRUE;
709                 } else {
710                     $this->fon_group= FALSE;
711                 }
712             }
713             if ($this->acl_is_writeable("nagiosGroup")){
714                 if (isset ($_POST['nagios_group'])){
715                     $this->nagios_group= TRUE;
716                 } else {
717                     $this->nagios_group= FALSE;
718                 }
719             }
720         }
721     }
724     /* Save to LDAP */
725     function save()
726     {
728         /* ID handling */
729         if ($this->force_gid == 0){
730             if ($this->saved_gidNumber != ""){
731                 $this->gidNumber= $this->saved_gidNumber;
732             } else {
733                 /* Calculate new, lock uids */
734                 $wait= 10;
735                 while (get_lock("gidnumber") != ""){
736                     sleep (1);
738                     /* timed out? */
739                     if ($wait-- == 0){
740                         break;
741                     }
742                 }
743                 add_lock ("gidnumber", "gosa");
744                 $this->gidNumber= get_next_id("gidNumber", $this->dn);
745             }
746         }
748         plugin::save(); 
750         /* Remove objectClass for samba/phone support */
751         $tmp= array();
752         for ($i= 0; $i<count($this->attrs["objectClass"]); $i++){
753             if ($this->attrs['objectClass'][$i] != 'sambaGroupMapping' &&
754                     $this->attrs['objectClass'][$i] != 'sambaIdmapEntry' &&
755                     $this->attrs['objectClass'][$i] != 'goFonPickupGroup' &&
756                     $this->attrs['objectClass'][$i] != 'nagiosContactGroup'){
757                 $tmp[]= $this->attrs['objectClass'][$i];
758             }
759         }
760         $this->attrs['objectClass']= $tmp;
761         $ldap= $this->config->get_ldap_link();
763         /* Add samba group functionality */
764         if ($this->smbgroup){
766             /* Fixed undefined index ... 
767              */ 
768             $this->SID = $this->ridBase = "";
769             if(isset($this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['SID'])){
770                 $this->SID    = $this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['SID'];
771             }else{
772                 msg_dialog::display(_("Error"), sprintf(_("Cannot find any SID for '%s'!"), $this->sambaDomainName), ERROR_DIALOG);
773             }
774             if(isset($this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['RIDBASE'])){
775                 $this->ridBase= $this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['RIDBASE']; 
776             }else{
777                 msg_dialog::display(_("Error"), sprintf(_("Cannot find any RIDBASE for '%s'!"), $this->sambaDomainName), ERROR_DIALOG);
778             }
780             $this->attrs['objectClass'][]= 'sambaGroupMapping';
781             $this->attrs['sambaGroupType']= "2";
783             /* Check if we need to create a special entry */
784             if ($this->groupType == 0){
786                 if ($this->sambaSID == "" || $this->oldgroupType != $this->groupType){
787                     $sid = $this->getSambaSID();
788                     $this->attrs['sambaSID']= $sid;
789                     $this->sambaSID= $sid;
790                 }
792             } else {
793                 $this->attrs['sambaSID']=$this->SID."-".$this->groupType;
794             }
796             /* User wants me to fake the idMappings? This is useful for
797                making winbind resolve the group names in a reasonable amount
798                of time in combination with larger databases. */
799             if ($this->config->boolValueIsTrue("core","sambaIdMapping")){
800                 $this->attrs['objectClass'][]= "sambaIdmapEntry";
801             }
803         }
805         /* Add phone functionality */
806         if ($this->fon_group){
807             $this->attrs['objectClass'][]= "goFonPickupGroup";
808         }
810         /* Add nagios functionality */
811         if ($this->nagios_group){
812             $this->attrs['objectClass'][]= "nagiosContactGroup";
813         }
815         /* Take members array */
816         
817         if (!$this->isRestrictedByDynGroup() && count ($this->memberUid)){
818             $this->attrs['memberUid']= array_values(array_unique($this->memberUid));
819         }
821         /* New accounts need proper 'dn', propagate it to remaining objects */
822         if ($this->dn == 'new'){
823             $this->dn= 'cn='.$this->cn.','.get_groups_ou().$this->base;
824         }
826         /* Add member dn's for RFC2307bis Support */
827         if ($this->rfc2307bis){
828             $this->attrs['member'] = array();
829             if (count($this->memberUid)){
830                 foreach($this->attrs['memberUid'] as $uid) {
831                     if(isset($this->dnMapping[$uid])){
832                         $this->attrs['member'][]= $this->dnMapping[$uid];
833                     }
834                 }
835             } else {
836                 $this->attrs['member'][]= $this->dn;
837             }
838         }
840         /* Save data. Using 'modify' implies that the entry is already present, use 'add' for
841            new entries. So do a check first... */
842         $ldap->cat ($this->dn, array('dn'));
843         if ($ldap->fetch()){
844             /* Modify needs array() to remove values :-( */
845             if (!count ($this->memberUid)){
846                 $this->attrs['memberUid']= array();
847             }
848             if (!$this->smbgroup){
849                 $this->attrs['sambaGroupType']= array();
850                 $this->attrs['sambaSID']= array();
851             }
853             $mode= "modify";
854         } else {
855             $mode= "add";
856             $ldap->cd($this->config->current['BASE']);
857             $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
858         }
860         /* Check generated gidNumber, it may be used by another group. 
861          */
862         if($this->gidNumber != ""){
863             $ldap->cd($this->config->current['BASE']);
864             $ldap->search("(&(!(cn=".$this->orig_cn."))(objectClass=posixGroup)(gidNumber=".$this->gidNumber."))",array("cn"));
865             if($ldap->count()){
866                 $cns = "";
867                 while($attrs = $ldap->fetch()){
868                     $cns .= $attrs['cn'][0].", ";
869                 }
870                 $cns = rtrim($cns,", ");
871                 msg_dialog::display(_("Warning"),sprintf(_("The gidNumber '%s' is already in use by %s!"),$this->gidNumber,$cns) , WARNING_DIALOG );
872             }
873         }
875         /* Write back to ldap */
876         $ldap->cd($this->dn);
877         $this->cleanup();
878         $ldap->$mode($this->attrs);
880         /* Remove ACL dependencies too,
881          */
882         if($this->dn != $this->orig_dn && $this->orig_dn != "new"){
883             $tmp = new acl($this->config,$this->parent,$this->dn);
884             $tmp->update_acl_membership($this->orig_dn,$this->dn);
885         }
887         if($this->initially_was_account){
888             new log("modify","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
889         }else{
890             new log("create","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
891         }
893         $ret= 0;
894         if (!$ldap->success()){
895             msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, 0, get_class()));
896             $ret= 1;
897         }
899         $this->trustModeDialog->dn = $this->dn;
900         $this->trustModeDialog->save();
902         /* Remove uid lock */
903         del_lock ("gidnumber");
905         /* Post that we've done*/
906         $this->handle_post_events($mode);
908         return ($ret);
909     }
911     function check()
912     {
913         /* Call common method to give check the hook */
914         $message= plugin::check();
916         /* Permissions for that base? */
917         if ($this->base != ""){
918             $new_dn= 'cn='.$this->cn.','.get_groups_ou().$this->base;
919         } else {
920             $new_dn= $this->dn;
921         }
923         /* must: cn */
924         if ($this->cn == "" && $this->acl_is_writeable("cn")){
925             $message[]= msgPool::required(_("Name"));
926         }
928         // Check if a wrong base was supplied
929         if(!$this->baseSelector->checkLastBaseUpdate()){
930             $message[]= msgPool::check_base();;
931         }
933         /* Check for valid input */
934         if (!tests::is_uid($this->cn)){
935             if (strict_uid_mode()){
936                 $message[]= msgPool::invalid(_("Name"), $this->cn, "/[a-z0-9_-]/");
937             } else {
938                 $message[]= msgPool::invalid(_("Name"), $this->cn, "/[a-z0-9 _.-]/i");
939             }
940         }
942         // Check if a wrong base was supplied
943         if(!$this->baseSelector->checkLastBaseUpdate()){
944             $message[]= msgPool::check_base();;
945         }
947         if($this->allowGroupsWithSameNameInOtherSubtrees == true){
949             /* Check for used 'cn' */
950             $ldap= $this->config->get_ldap_link();
951             if(($this->cn  != $this->orig_cn) || ($this->orig_dn == "new")){
952                 $ldap->cd(get_groups_ou().$this->base);
953                 $ldap->ls("(&(|(objectClass=gosaGroupOfNames)(objectClass=posixGroup))(cn=$this->cn))",get_groups_ou().$this->base,array("cn"));
954                 if ($ldap->count() != 0){
955                     $message[]= msgPool::duplicated(_("Name"));
956                 }
957             }
959         }else{
961             /* Check for used 'cn' */
962             $ldap= $this->config->get_ldap_link();
963             $ldap->cd($this->config->current['BASE']);
964             $ldap->search("(&(|(objectClass=gosaGroupOfNames)(objectClass=posixGroup))(cn=$this->cn))",array("cn"));
965             if ($ldap->count() != 0){
967                 /* New entry? */
968                 if ($this->dn == 'new'){
969                     $message[]= msgPool::duplicated(_("Name"));
970                 }
972                 /* Moved? */
973                 elseif ($new_dn != $this->orig_dn){
974                     $ldap->fetch();
975                     if ($ldap->getDN() != $this->orig_dn){
976                         $message[]= msgPool::duplicated(_("Name"));
977                     }
978                 }
979             }
980         }
982         /* Check ID */
983         if ($this->force_gid == "1"){
984             if (!tests::is_id($this->gidNumber)){
985                 $message[]= msgPool::invalid(_("GID"), $this->gidNumber, "/[0-9]/");
986             } else {
987                 if ($this->gidNumber < $this->config->get_cfg_value("core","minId")){
988                     $message[]= msgPool::toosmall(_("GID"), $this->config->get_cfg_value("core","minId"));
989                 }
991             }
992         }
994         /* Check if we are allowed to create or move this object 
995          */
996         if(!$this->orig_dn == "new" || 
997                 $this->orig_base != $this->base || 
998                 $this->cn != $this->orig_cn){
1000             if($this->orig_dn == "new" && !$this->acl_is_createable($this->base)){
1001                 $message[] = msgPool::permCreate();
1002             }elseif($this->orig_dn != "new" && !$this->acl_is_moveable($this->base)){
1003                 $message[] = msgPool::permMove();
1004             }
1005         }
1007         return ($message);
1008     }
1011     function getCopyDialog()
1012     {
1013         $vars = array("cn");
1015         if($this ->force_gid){
1016             $used = " checked ";
1017             $dis  = "";
1018         }else{
1019             $used = "";
1020             $dis  = " disabled ";
1021         }
1023         $smarty = get_smarty();
1024         $smarty->assign("used",     set_post($used));
1025         $smarty->assign("dis" ,     set_post($dis));
1026         $smarty->assign("cn" ,      set_post($this->cn));
1027         $smarty->assign("gidNumber",set_post($this->gidNumber));
1028         $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE));
1029         $ret = array();
1030         $ret['string'] = $str;
1031         $ret['status'] = "";
1032         return($ret);
1033     }
1035     function saveCopyDialog()
1036     {
1037         if(isset($_POST['cn'])){
1038             $this->cn = get_post('cn');
1039         }
1040         if(isset($_POST['force_gid'])){
1041             $this->force_gid  = 1;
1042             $this->gidNumber= get_post('gidNumber');
1043         }else{
1044             $this->force_gid  = 0;
1045             $this->gidNumber  = false;
1046         }
1047     }
1050     /* Return plugin informations for acl handling  */ 
1051     static function plInfo()
1052     {
1053         return (array(  
1054                     "plShortName" => _("Generic"),
1055                     "plDescription" => _("Generic group settings"),
1056                     "plSelfModify"  => FALSE,
1057                     "plDepends"     => array(),
1058                     "plPriority"    => 0,
1059                     "plSection"     => array("administration"),
1060                     "plCategory"    => array("groups" => array("objectClass" => "posixGroup", "description" => _("Groups"))),
1062                     "plProperties" =>
1063                     array(
1064                         array(
1065                             "name"          => "ogroupRDN",
1066                             "type"          => "rdn",
1067                             "default"       => "ou=groups,",
1068                             "description"   => _("RDN for object group storage."),
1069                             "check"         => "gosaProperty::isRdn",
1070                             "migrate"       => "migrate_ogroupRDN",
1071                             "group"         => "plugin",
1072                             "mandatory"     => FALSE)),
1075             "plProvidedAcls"    => array(
1076                     "cn"                => _("Name"),
1077                     "description"       => _("Description"),
1078                     "base"              => _("Base"),
1080                     "gidNumber"         => _("GID"),
1082                     "sambaGroupType"    => _("Samba group type"),
1083                     "sambaDomainName"   => _("Samba domain name"),
1084                     "accessTo"        => _("System trust"),
1085                     "fonGroup"          => _("Phone pickup group"),
1086                     "nagiosGroup"       => _("Nagios group"),
1088                     "memberUid"         => _("Group member"))
1089                 ));
1090     }
1093     function multiple_save_object()
1094     {
1095         if(isset($_POST['group_mulitple_edit'])){
1097             /* Create a base backup and reset the
1098                base directly after calling plugin::save_object();
1099                Base will be set seperatly a few lines below */
1100             $base_tmp = $this->base;
1101             plugin::multiple_save_object();
1102             plugin::save_object();
1103             $this->trustModeDialog->multiple_save_object();
1104             $this->base = $base_tmp;
1106             foreach(array("base","smbgroup","groupType","sambaDomainName","fon_group","nagios_group") as $attr){
1107                 if(isset($_POST['use_'.$attr])){
1108                     $this->multi_boxes[] = $attr;
1109                 }
1110             }
1112             /* Refresh base */
1113             if ($this->acl_is_moveable($this->base)){
1114                 if (!$this->baseSelector->update()) {
1115                     msg_dialog::display(_("Error"), msgPool::permMove(), ERROR_DIALOG);
1116                 }
1117                 if ($this->base != $this->baseSelector->getBase()) {
1118                     $this->base= $this->baseSelector->getBase();
1119                     $this->is_modified= TRUE;
1120                 }
1121             }
1123             foreach (array( "smbgroup"   => "sambaGroupType" ,"nagios_group" => "nagiosGroup") as $val => $aclname) {
1124                 if ($this->acl_is_writeable($aclname)){
1125                     if(isset($_POST["$val"])){
1126                         $this->$val=  TRUE;
1127                     }else{
1128                         $this->$val=  FALSE;
1129                     }
1130                 }
1131             }
1133             /* Save sambaDomain attribute */
1134             if ($this->acl_is_writeable("sambaDomainName") && isset ($_POST['sambaDomainName'])){
1135                 $this->sambaDomainName= get_post('sambaDomainName');
1136                 $this->groupType= get_post('groupType');
1137             }
1139             /* Save fon attribute */
1140             if ($this->acl_is_writeable("fonGroup")){
1141                 if (isset ($_POST['fon_group'])){
1142                     $this->fon_group= TRUE;
1143                 } else {
1144                     $this->fon_group= FALSE;
1145                 }
1146             }
1147         }
1148     }
1151     function get_multi_edit_values()
1152     {
1153         $ret = plugin::get_multi_edit_values();
1154         $ret = array_merge($ret,$this->trustModeDialog->get_multi_edit_values());
1156         foreach(array("base","smbgroup","groupType","sambaDomainName","fon_group","nagios_group") as $attr){    
1157             if(in_array($attr,$this->multi_boxes)){
1158                 $ret[$attr] = $this->$attr;
1159             }
1160         }
1162         $ret['memberUid'] = $this->memberUid;
1163         $ret['memberUid_used_by_some'] = $this->memberUid_used_by_some;
1164         return($ret);
1165     }
1167     function multiple_execute()
1168     {
1169         return($this->execute());
1170     }
1173     /* Initialize plugin with given atribute arrays
1174      */
1175     function init_multiple_support($attrs,$all)
1176     {
1177         plugin::init_multiple_support($attrs,$all);
1178         $this->trustModeDialog->init_multiple_support($attrs,$all);
1180         $this->memberUid = array();
1181         $this->memberUid_used_by_some = array();
1182         if (isset($attrs['memberUid'])){
1183             for ($i= 0; $i<$attrs['memberUid']['count']; $i++){
1184                 $this->memberUid[$attrs['memberUid'][$i]]= $attrs['memberUid'][$i];
1185             }
1186             ksort($this->memberUid);
1187         }
1189         if (isset($all['memberUid'])){
1190             for ($i= 0; $i<$all['memberUid']['count']; $i++){
1191                 if(!in_array($all['memberUid'][$i],$this->memberUid)){
1192                     $this->memberUid_used_by_some[$all['memberUid'][$i]]= $all['memberUid'][$i];
1193                 }
1194             }
1195             ksort($this->memberUid_used_by_some);
1196         }
1198         $this->reload(TRUE);
1200         // We've two lists in mutliple support  
1201         //  - one which represents those users which are part of ALL groups.
1202         //  - ond one which represents those users which are only part of SOME groups.
1203         $this->commonList = new sortableListing();
1204         $this->commonList->setDeleteable(true);
1205         $this->commonList->setInstantDelete(false);
1206         $this->commonList->setEditable(false);
1207         $this->commonList->setWidth("100%");
1208         $this->commonList->setHeight("120px");
1209         $this->commonList->setHeader(array('~',_("Given name"),_("Surname"),_("UID")));
1210         $this->commonList->setColspecs(array('20px','*','*','*','20px'));
1211         $this->commonList->setDefaultSortColumn(1);
1213         $this->partialList = new sortableListing();
1214         $this->partialList->setDeleteable(true);
1215         $this->partialList->setInstantDelete(false);
1216         $this->partialList->setEditable(false);
1217         $this->partialList->setWidth("100%");
1218         $this->partialList->setHeight("120px");
1219         $this->partialList->setHeader(array('~',_("Given name"),_("Surname"),_("UID")));
1220         $this->partialList->setColspecs(array('20px','*','*','*','20px'));
1221         $this->partialList->setDefaultSortColumn(1);
1222     }
1225     function PrepareForCopyPaste($source)
1226     {
1227         plugin::PrepareForCopyPaste($source);
1229         $this->trustModeDialog->PrepareForCopyPaste($source);
1231         /* Get samba Domain in case of samba 3 */
1232         if ($this->sambaSID != ""){
1233             $this->SID= preg_replace ("/-[^-]+$/", "", $this->sambaSID);
1234             $ldap= $this->config->get_ldap_link();
1235             $ldap->cd($this->config->current['BASE']);
1236             $ldap->search ("(&(objectClass=sambaDomain)(sambaSID=$this->SID))",array("sambaAlgorithmicRidBase"));
1237             if ($ldap->count() != 0){
1238                 $attrs= $ldap->fetch();
1239                 if(isset($attrs['sambaAlgorithmicRidBase'])){
1240                     $this->ridBase= $attrs['sambaAlgorithmicRidBase'][0];
1241                 } else {
1242                     $this->ridBase= $this->config->get_cfg_value("core","sambaRidBase");
1243                 }
1245                 /* Get domain name for SID */
1246                 $this->sambaDomainName= "DEFAULT";
1247                 foreach ($this->config->data['SERVERS']['SAMBA'] as $key => $val){
1248                     if ($val['SID'] == $this->SID){
1249                         $this->sambaDomainName= $key;
1250                         break;
1251                     }
1252                 }
1253             } else {
1254                 if ($this->config->get_cfg_value("core","sambaRidBase") != ""){
1255                     $this->sambaDomainName= "DEFAULT";
1256                     $this->ridBase= $this->config->get_cfg_value("core","sambaRidBase");
1257                     $this->SID= $this->config->get_cfg_value("core","sambaSID");
1258                 } else {
1259                     msg_dialog::display(_("Configuration error"), _("Cannot find group SID in your configuration!"), ERROR_DIALOG);
1260                 }
1261             }
1263             /* Get group type */
1264             $this->groupType= (int)substr(strrchr($this->sambaSID, "-"), 1);
1265             if ($this->groupType < 500 || $this->groupType > 553){
1266                 $this->groupType= 0;
1267             }
1268             $this->oldgroupType= $this->groupType;
1269         }
1271         // Detect samba groups and adapt its values.
1272         $this->smbgroup = in_array('sambaGroupMapping', $source['objectClass']);
1273         if ($this->smbgroup) { 
1274             $this->sambaSID = $this->getSambaSID(); 
1275         } 
1277         $this->memberUid = array();
1278         if(isset($source['memberUid'])){
1279             for($i = 0 ; $i < $source['memberUid']['count']; $i ++){
1280                 $this->memberUid[] = $source['memberUid'][$i];
1281             }
1282         }
1283     }
1286     function set_acl_base($base)
1287     {
1288         plugin::set_acl_base($base);
1289         $this->trustModeDialog->set_acl_base($base);
1290     }
1293     /*! \brief  Enables multiple support for this plugin
1294      */
1295     function enable_multiple_support()
1296     {
1297         plugin::enable_multiple_support();
1298         $this->trustModeDialog->enable_multiple_support();
1299     }
1302     function set_multi_edit_values($attrs)
1303     {
1304         $users = array();
1306         /* Update groupMembership, keep optinal group */
1307         foreach($attrs['memberUid_used_by_some'] as $uid){
1308             if(in_array($uid,$this->memberUid)){
1309                 $users[$uid] = $uid;
1310             }
1311         }
1313         /* Update groupMembership, add forced groups */
1314         foreach($attrs['memberUid'] as $uid){
1315             $users[$uid] = $uid;
1316         }
1317         plugin::set_multi_edit_values($attrs);
1318         $this->trustModeDialog->set_multi_edit_values($attrs);
1319         $this->memberUid = $users;
1320     }
1323     /*! \brief Get a new SambaSID for a group */ 
1324     function getSambaSID() 
1325     { 
1326         $ldap = $this->config->get_ldap_link(); 
1327         $gidNumber= $this->gidNumber; 
1328         while(TRUE){ 
1329             $sid= $this->SID."-".($gidNumber*2 + $this->ridBase+1); 
1330             $ldap->cd($this->config->current['BASE']); 
1331             $ldap->search("(sambaSID=$sid)",array("sambaSID")); 
1332             if ($ldap->count() == 0){ 
1333                 break; 
1334             } 
1335             $gidNumber++; 
1336         } 
1338         return $sid; 
1339     } 
1342 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1343 ?>