Code

Added LDAP_FILTER_NESTING_LIMIT to baort group member resolv if member count is above...
[gosa.git] / gosa-core / plugins / admin / groups / class_groupGeneric.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 $samba3= FALSE;
39   var $sambaSID= "";
40   var $sambaDomainName= "DEFAULT";
41   var $SID= "";
42   var $ridBase= 0;
43   var $members= array();
44   var $users= array();
45   var $member= array();
46   var $allusers= array();
47   var $saved_gidNumber= "";
48   var $oldgroupType= "";
49   var $orig_dn= "";
50   var $orig_cn= "";
51   var $orig_base= "";
52   var $has_mailAccount= FALSE;
53   var $group_dialog= FALSE;
54   var $nagios_group =FALSE;
55   var $sambaGroupType;
56   var $dialog;
57   var $rfc2307bis= FALSE;
58   var $OnlyShowFirstEntries =200;
59   var $dnMapping= array();
60   var $view_logged = FALSE;
61   var $allowGroupsWithSameNameInOtherSubtrees = true;
63   /* Trustmodel/AccessTo 
64    */
65   var $accessTo= array();
66   var $trustModel= "";
67   var $show_ws_dialog = FALSE;
69   /* attribute list for save action */
70   var $attributes= array("cn", "description", "gidNumber","memberUid","sambaGroupType","sambaSID","accessTo","trustModel");
71   var $objectclasses= array("top", "posixGroup");
73   var $CopyPasteVars  = array("force_gid","fon_group","smbgroup","groupType","sambaSID","sambaDomainName","SID","nagios_group","sambaGroupType");
75   var $multiple_support = TRUE;
77   function group (&$config, $dn= NULL)
78   {
79      /* Set rfc2307bis flag */
80      if (isset($config->current['RFC2307BIS']) && ($config->current['RFC2307BIS']== "true")){
81        $this->rfc2307bis= TRUE;
82        $this->attributes[]= "member";
83        $this->objectclasses[]= "groupOfNames";
84      }
86     plugin::plugin ($config, $dn);
88     /* Load attributes depending on the samba version */
89     $this->samba3= ($config->current['SAMBAVERSION'] == 3);
90     $this->orig_dn= $dn;
91     $this->orig_cn= $this->cn;
93     /* Get member list */
94     if (isset($this->attrs['memberUid'][0])){
95       $tmp= array();
96       for ($i= 0; $i<$this->attrs['memberUid']['count']; $i++){
97         $tmp[$this->attrs['memberUid'][$i]]= $this->attrs['memberUid'][$i];
98       }
99       $this->memberUid= $tmp;
100       ksort ($this->memberUid);
101     }
103     /* Save gidNumber for later use */
104     if (isset($this->attrs['gidNumber'])){
105       $this->saved_gidNumber= $this->attrs['gidNumber'][0];
106     }
108     /* Is a samba group? */
109     if (isset($this->attrs['objectClass'])){
110       if (array_search ('sambaGroupMapping', $this->attrs['objectClass']) == FALSE ){
111         $this->smbgroup= FALSE;
112       } else {
113         $this->smbgroup= TRUE;
114         if (isset($this->attrs['sambaSID'])){
115           $this->sambaSID= $this->attrs['sambaSID'][0];
116         }
117       }
118       if (array_search ('goFonPickupGroup', $this->attrs['objectClass']) == FALSE ){
119         $this->fon_group= FALSE;
120       } else {
121         $this->fon_group= TRUE;
122       }
123       if (array_search ('nagiosContactGroup', $this->attrs['objectClass']) == FALSE ){
124         $this->nagios_group= FALSE;
125       } else {
126         $this->nagios_group= TRUE;
127       }
128     }
130     /* Set mail flag */
131     if (isset($this->attrs['objectClass']) && in_array('gosaMailAccount', $this->attrs['objectClass'])){
132       $this->has_mailAccount= TRUE;
133     }
135     /* Get samba Domain in case of samba 3 */
136     if ($this->samba3 && $this->sambaSID != ""){
137       $this->SID= preg_replace ("/-[^-]+$/", "", $this->sambaSID);
138       $ldap= $this->config->get_ldap_link();
139       $ldap->cd($this->config->current['BASE']);
140       $ldap->search ("(&(objectClass=sambaDomain)(sambaSID=$this->SID))",array("sambaAlgorithmicRidBase"));
141       if ($ldap->count() != 0){
142         $attrs= $ldap->fetch();
143         if(isset($attrs['sambaAlgorithmicRidBase'])){  
144           $this->ridBase= $attrs['sambaAlgorithmicRidBase'][0];  
145         } else {  
146           $this->ridBase= $this->config->current['RIDBASE'];  
147         } 
149         /* Get domain name for SID */
150         $this->sambaDomainName= "DEFAULT";
151         foreach ($this->config->data['SERVERS']['SAMBA'] as $key => $val){
152           if ($val['SID'] == $this->SID){
153             $this->sambaDomainName= $key;
154             break;
155           }
156         }
157       } else {
158         if (isset($this->config->current['RIDBASE'])){
159           $this->sambaDomainName= "DEFAULT";
160           $this->ridBase= $this->config->current['RIDBASE'];
161           $this->SID= $this->config->current['SID'];
162         } else {
163           msg_dialog::display(_("Configuration error"), _("Cannot find group SID in your configuration!"), ERROR_DIALOG);
164         }
165       }
167       /* Get group type */
168       $this->groupType= (int)substr(strrchr($this->sambaSID, "-"), 1);
169       if ($this->groupType < 500 || $this->groupType > 553){
170         $this->groupType= 0;
171       }
172       $this->oldgroupType= $this->groupType;
173     }
175     /* Get global filter config */
176     if (!session::is_set("gufilter")){
177       $ui= get_userinfo();
178       $base= get_base_from_people($ui->dn);
179       $gufilter= array( "dselect"       => $base,
180           "regex"           => "*");
181       session::set("gufilter", $gufilter);
182     }
183     $gufilter= session::get('gufilter');
184     $gufilter['SubSearchGroup'] = false;
185     session::set('gufilter',$gufilter);
186   
187     if ($this->dn == "new"){
188       if(session::is_set('CurrentMainBase')){
189         $this->base = session::get('CurrentMainBase');
190       }else{
191         $ui= get_userinfo();
192         $this->base= dn2base($ui->dn);
193       }
194     } else {
196       /* Get object base */
197       $this->base =preg_replace ("/^[^,]+,".normalizePreg(get_groups_ou())."/","",$this->dn);
198     }
199     $this->orig_base = $this->base;
201     /* Is this account a trustAccount? */
202     if (isset($this->attrs['trustModel'])){
203       $this->trustModel= $this->attrs['trustModel'][0];
204       $this->was_trust_account= TRUE;
205     } else {
206       $this->was_trust_account= FALSE;
207       $this->trustModel= "";
208     }
210     $this->accessTo = array();
211     if (isset($this->attrs['accessTo'])){
212       for ($i= 0; $i<$this->attrs['accessTo']['count']; $i++){
213         $tmp= $this->attrs['accessTo'][$i];
214         $this->accessTo[$tmp]= $tmp;
215       }
216     }
218     /* This is always an account */
219     $this->is_account= TRUE;
220     $this->reload();
221   }
223   function execute()
224   {
225     /* Call parent execute */
226     plugin::execute();
228     /* Log view */
229     if($this->is_account && !$this->view_logged){
230       $this->view_logged = TRUE;
231       new log("view","groups/".get_class($this),$this->dn);
232     }
234     /* Do we represent a valid group? */
235     if (!$this->is_account && $this->parent === NULL){
236       $display= "<img alt=\"\" src=\"images/small-error.png\" align=\"middle\">&nbsp;<b>".msgPool::noValidExtension()."</b>";
237       return ($display);
238     }
240     /* Delete user from group */
241     if (isset($_POST['del_users']) && isset($_POST['members'])){
242       foreach ($_POST['members'] as $value){
243         unset ($this->members["$value"]);
244         $this->removeUser($value);
245       }
246       $this->reload();
247     }
249     /* Add objects? */
250     if (isset($_POST["edit_membership"])){
251       $this->group_dialog= TRUE;
252       $this->dialog= TRUE;
253     }
255     /* Add objects finished? */
256     if (isset($_POST["add_users_finish"]) || isset($_POST["add_users_cancel"])){
257       $this->group_dialog= FALSE;
258       $this->dialog= FALSE;
259     }
261     /* Add user to group */
262     if (isset($_POST['add_users_finish']) && isset($_POST['users'])){
263       foreach ($_POST['users'] as $value){
264         $this->members["$value"]= $this->allusers[$value];
265         asort($this->members);
266         $this->addUser($value);
267       }
268       $this->reload();
269     }
271     /* Base select dialog */
272     $once = true;
273     foreach($_POST as $name => $value){
274       if((preg_match("/^chooseBase/",$name) && $once) && ($this->acl_is_moveable())){
275           
276         $once = false;
277         $this->dialog = new baseSelectDialog($this->config,$this,$this->get_allowed_bases());
278         $this->dialog->setCurrentBase($this->base);
279       }
280     }
282     /* Dialog handling */
283     if(is_object($this->dialog)){
284       /* Must be called before save_object */
285       $this->dialog->save_object();
287       if($this->dialog->isClosed()){
288         $this->dialog = false;
289       }elseif($this->dialog->isSelected()){
291         /* Check if selected base is valid */
292         $tmp = $this->get_allowed_bases();
293         if(isset($tmp[$this->dialog->isSelected()])){
294           $this->base = $this->dialog->isSelected();
295         }
296         $this->dialog= false;
297       }else{
298         return($this->dialog->execute());
299       }
300     }
303     /* Add user workstation? */
304     if (isset($_POST["add_ws"])){
305       $this->show_ws_dialog= TRUE;
306       $this->dialog= TRUE;
307     }
309     /* Add user workstation? */
310     if (isset($_POST["add_ws_finish"]) && isset($_POST['wslist'])){
311       foreach($_POST['wslist'] as $ws){
312         $this->accessTo[$ws]= $ws;
313       }
314       ksort($this->accessTo);
315       $this->is_modified= TRUE;
316     }
318     /* Remove user workstations? */
319     if (isset($_POST["delete_ws"]) && isset($_POST['workstation_list'])){
320       foreach($_POST['workstation_list'] as $name){
321         unset ($this->accessTo[$name]);
322       }
323       $this->is_modified= TRUE;
324     }
326     /* Add user workstation finished? */
327     if (isset($_POST["add_ws_finish"]) || isset($_POST["add_ws_cancel"])){
328       $this->show_ws_dialog= FALSE;
329       $this->dialog= FALSE;
330     }
332     $smarty= get_smarty();
334     /* Show ws dialog */
335     if ($this->show_ws_dialog){
337       /* Save data */
338       $sysfilter= session::get("sysfilter");
339       foreach( array("depselect", "regex") as $type){
340         if (isset($_POST[$type])){
341           $sysfilter[$type]= $_POST[$type];
342         }
343       }
344       if (isset($_GET['search'])){
345         $s= mb_substr($_GET['search'], 0, 1, "UTF8")."*";
346         if ($s == "**"){
347           $s= "*";
348         }
349         $sysfilter['regex']= $s;
350       }
351       session::set("sysfilter", $sysfilter);
353       /* Get workstation list */
354       $exclude= "";
355       foreach($this->accessTo as $ws){
356         $exclude.= "(cn=$ws)";
357       }
358       if ($exclude != ""){
359         $exclude= "(!(|$exclude))";
360       }
361       $regex= $sysfilter['regex'];
362       $filter= "(&(|(objectClass=goServer)(objectClass=gotoWorkstation)(objectClass=gotoTerminal))$exclude(cn=*)(cn=$regex))";
364       $deps_a = array(get_ou("serverou"),
365                       get_ou("terminalou"),
366                       get_ou("workstationou"));
368       $res= get_sub_list($filter, array("terminal","server","workstation"), $deps_a, get_ou("systemsou").$sysfilter['depselect'],         array("cn"), GL_SUBSEARCH | GL_SIZELIMIT);
369       $wslist= array();
370       foreach ($res as $attrs){
371         $wslist[]= preg_replace('/\$/', '', $attrs['cn'][0]);
372       }
373       asort($wslist);
374       $smarty->assign("search_image", get_template_path('images/lists/search.png'));
375       $smarty->assign("launchimage", get_template_path('images/lists/action.png'));
376       $smarty->assign("tree_image", get_template_path('images/lists/search-subtree.png'));
377       $smarty->assign("deplist", $this->config->idepartments);
378       $smarty->assign("alphabet", generate_alphabet());
379       foreach( array("depselect", "regex") as $type){
380         $smarty->assign("$type", $sysfilter[$type]);
381       }
382       $smarty->assign("hint", print_sizelimit_warning());
383       $smarty->assign("wslist", $wslist);
384       $smarty->assign("apply", apply_filter());
385       $display= $smarty->fetch (get_template_path('trust_machines.tpl', TRUE, dirname(__FILE__)));
386       return ($display);
387     }
389     /* Assign templating stuff */
390     if ($this->samba3){
391       $smarty->assign("samba3", "true");
392     } else {
393       $smarty->assign("samba3", "");
394     }
396     if($this->config->search("nagiosaccount", "CLASS",array('menu'))){
397       $smarty->assign("nagios",true);
398     }else{
399       $smarty->assign("nagios",false);
400     }
401     
402     if($this->config->search("phoneAccount", "CLASS",array('menu'))){
403       $smarty->assign("pickupGroup",true);
404     }else{
405       $smarty->assign("pickupGroup",false);
406     }
408     /* Manage object add dialog */
409     if ($this->group_dialog){
411       /* Save data */
412       $gufilter= session::get("gufilter");
413       foreach( array("dselect", "regex") as $type){
414         if (isset($_POST[$type])){
415           $gufilter[$type]= $_POST[$type];
416         }
417       }
418       if(isset($_POST['regex'])){
419         if(isset($_POST['SubSearchGroup'])){
420           $gufilter['SubSearchGroup'] = true;
421         }else{
422           $gufilter['SubSearchGroup'] = false;
423         }
424       }
426       if (isset($_GET['search'])){
427         $s= mb_substr($_GET['search'], 0, 1, "UTF8")."*";
428         if ($s == "**"){
429           $s= "*";
430         }
431         $gufilter['regex']= $s;
432       }
433       session::set("gufilter", $gufilter);
434       $this->reload();
436       /* Show dialog */
437       $smarty->assign("search_image", get_template_path('images/lists/search.png'));
438       $smarty->assign("launchimage", get_template_path('images/lists/action.png'));
439       $smarty->assign("tree_image", get_template_path('images/lists/search-subtree.png'));
441       $smarty->assign("deplist", $this->get_allowed_bases("users/user"));
442       $smarty->assign("alphabet", generate_alphabet());
443       foreach( array("dselect", "regex","SubSearchGroup") as $type){
444         $smarty->assign("$type", $gufilter[$type]);
445       }
446       $smarty->assign("hint", print_sizelimit_warning());
447       $smarty->assign("users", $this->displayUsers);
448       $smarty->assign("apply", apply_filter());
449       $display= $smarty->fetch (get_template_path('group_objects.tpl', TRUE, dirname(__FILE__)));
450       return ($display);
451     }
453     $smarty->assign("bases", $this->get_allowed_bases());
454     $smarty->assign("base_select", $this->base);
456     if ($this->samba3){
457       $domains= array();
458       foreach($this->config->data['SERVERS']['SAMBA'] as $name => $content){
459         $domains[$name]= $name;
460       }
461       $smarty->assign("sambaDomains", $domains);
462       $smarty->assign("sambaDomainName", $this->sambaDomainName);
463       $groupTypes= array(0 => _("Samba group"), 512 => _("Domain admins"), 513 => _("Domain users"),
464           514 => _("Domain guests"));
466       /* Don't loose special groups! If not key'ed above, add it to
467          the combo box... */    
468       if ($this->groupType >= 500 && $this->groupType <= 553 && !isset($groupTypes[$this->groupType])){
469         $groupTypes[$this->groupType]= sprintf(_("Special group (%d)"), $this->groupType);
470       }
472       $smarty->assign("groupTypes", $groupTypes);
473       $smarty->assign("groupType", $this->groupType);
474     }
476     /* Members and users */
477     $smarty->assign("members", $this->members);
479     /* Work on trust modes */
480     $smarty->assign("trusthide", " disabled ");
481     $smarty->assign("trustmodeACL",  $this->getacl("trustModel"));
482     if ($this->trustModel == "fullaccess"){
483       $trustmode= 1;
484       // pervent double disable tag in html code, this will disturb our clean w3c html
485       $smarty->assign("trustmode",  $this->getacl("trustModel"));
487     } elseif ($this->trustModel == "byhost"){
488       $trustmode= 2;
489       $smarty->assign("trusthide", "");
490     } else {
491       // pervent double disable tag in html code, this will disturb our clean w3c html
492       $smarty->assign("trustmode",  $this->getacl("trustModel"));
493       $trustmode= 0;
494     }
495     $smarty->assign("trustmode", $trustmode);
496     $smarty->assign("trustmodes", array( 0 => _("disabled"), 1 => _("full access"),
497           2 => _("allow access to these hosts")));
499     if((count($this->accessTo))==0){
500       $smarty->assign("emptyArrAccess",true);
501     } else{
502       $smarty->assign("emptyArrAccess",false);
504     }
506     $smarty->assign("workstations", $this->accessTo);
510     /* Checkboxes */
511     foreach (array("force_gid", "smbgroup") as $val){
512       if ($this->$val == "1"){
513         $smarty->assign("$val", "checked");
514       } else {
515         $smarty->assign("$val", "");
516       }
517     }
518     if ($this->force_gid != "1"){
519       $smarty->assign("forceMode", "disabled");
520     }else{
521       $smarty->assign("forceMode", "");
522     }
523     if ($this->fon_group){
524       $smarty->assign("fon_group", "checked");
525     } else {
526       $smarty->assign("fon_group", "");
527     }
529     if ($this->nagios_group){
530       $smarty->assign("nagios_group", "checked");
531     } else {
532       $smarty->assign("nagios_group", "");
533     }
535     /* Fields */
536     foreach (array("cn", "description", "gidNumber") as $val){
537       $smarty->assign("$val", $this->$val);
538     }
540     $tmp = $this->plInfo();
541     foreach($tmp['plProvidedAcls'] as $name => $translation){
542       $smarty->assign($name."ACL",$this->getacl($name));
543     }
544     
545     if($this->acl_is_writeable("base")){
546       $smarty->assign("baseSelect",true);
547     }else{
548       $smarty->assign("baseSelect",false);
549     }
551     /* Show main page */
552     $smarty->assign("alphabet", generate_alphabet(10));
553     $smarty->assign("search_image", get_template_path('images/lists/search.png'));
554     $smarty->assign("launchimage", get_template_path('images/lists/action.png'));
555     $smarty->assign("tree_image", get_template_path('images/lists/search-subtree.png'));
556     $smarty->assign("deplist", $this->config->idepartments);
558     /* Multiple edit handling */
559     $smarty->assign("multiple_support",$this->multiple_support_active);
561     $smarty->assign("memberUid_All",$this->memberUid);
562     $smarty->assign("memberUid_Some",$this->memberUid_used_by_some);
564     foreach($this->attributes as $val){
565       if(in_array($val,$this->multi_boxes)){
566         $smarty->assign("use_".$val,TRUE);
567       }else{
568         $smarty->assign("use_".$val,FALSE);
569       }
570     }
571     foreach(array("base","smbgroup","groupType","sambaDomainName","fon_group") as $val){
572       if(in_array($val,$this->multi_boxes)){
573         $smarty->assign("use_".$val,TRUE);
574       }else{
575         $smarty->assign("use_".$val,FALSE);
576       }
577     }
579     return($smarty->fetch (get_template_path('generic.tpl', TRUE)));
580   }
582   function addUser($uid)
583   {
584     /* In mutliple edit we have to handle two arrays.
585      *  memberUid               : Containing users used in all groups
586      *  memberUid_used_by_some  : Those which are not used in all groups
587      * So we have to remove the given $uid from the ..used_by_some array first.
588      */
589     if($this->multiple_support_active){
590       if(isset($this->memberUid_used_by_some[$uid])){
591         unset($this->memberUid_used_by_some[$uid]);
592       }
593     }  
595     $this->memberUid[$uid]= $uid;
596   }
599   function removeUser($uid)
600   {
601     $temp= array();
602     if(isset($this->memberUid[$uid])){
603       unset($this->memberUid[$uid]);
604     }
606     /* We have two array contianing group members in multiple edit.
607      *  this->memberUid             : Groups used by all currently edited groups 
608      *  this->memberUid_used_by_some: Used by some 
609      * So we have to remove the specified uid from both arrays.
610      */
611     if($this->multiple_support_active){
612       if(isset($this->memberUid_used_by_some[$uid])){
613         unset($this->memberUid_used_by_some[$uid]);
614       }
615     }
616   }
618   /* Reload data */
619   function reload()
620   {
621     /* Fix regex string */
622     $gufilter = session::get("gufilter");
623     $regex    = normalizeLdap($gufilter['regex']);
624     $MaxUser  = $this->OnlyShowFirstEntries;
626     /* Prepare ldap link */
627     $ldap= $this->config->get_ldap_link();
628     $ldap->cd($gufilter['dselect']);
631     /* Resolve still unresolved memberuids to fill the list with sn/giveName attributes 
632         (Store gathered sn/givenName informations in $this->allusers too, 
633          to be prepared when adding/deleting users)
634      */    
635     $filter = "";
636     if(!isset($this->config->current['LDAP_FILTER_NESTING_LIMIT']) || 
637         count($this->memberUid) < $this->config->current['LDAP_FILTER_NESTING_LIMIT']){
638       foreach ($this->memberUid as $value){
639         if(!isset($this->members[$value])){
640           $filter .= "(uid=".normalizeLdap($value).")";
641         }
642       }
643     }
645     if(!empty($filter)){    
646       $ldap->cd($this->config->current['BASE']);
647       $ldap->search("(&(objectClass=gosaAccount)(!(objectClass=gosaUserTemplate))(|".$filter."))",array("dn", "uid","sn","givenName"));
648       while($attrs = $ldap->fetch()){
649         $this->dnMapping[$attrs['uid'][0]] = $attrs['dn'];
650         $this->members[$attrs['uid'][0]] = $this->createResultName($attrs);
651         $this->allusers[$attrs['uid'][0]]= $this->createResultName($attrs);
652       } 
653     }
654   
655     /* check if all uids are resolved */
656     if(!isset($this->config->current['LDAP_FILTER_NESTING_LIMIT']) || 
657         count($this->memberUid) < $this->config->current['LDAP_FILTER_NESTING_LIMIT']){
658       foreach ($this->memberUid as $value){
659         if(!isset($this->members[$value])){
660           $this->members[$value] =  _("! unknown id")." [".$value."]"; 
661         }
662       }  
663     }else{
664       foreach ($this->memberUid as $value){
665         $this->members[$value] = $value; 
666       }  
667     }
669     /* Create display list of users matching regex & filter 
670      */
671     $this->displayUsers = array();
672     $filter = "(&(objectClass=gosaAccount)(!(objectClass=gosaUserTemplate))(!(uid=*$))(|(uid=".$regex.")(sn=".$regex.")(givenName=".$regex.")))";
674     /* Search in current tree or within subtrees depending on the checkbox from filter section */
675     if($gufilter['SubSearchGroup']){
676       $flag = GL_SIZELIMIT | GL_SUBSEARCH;
677       $base = $gufilter['dselect'];
678     }else{
679       $flag = GL_SIZELIMIT ;
680       $base = get_people_ou().$gufilter['dselect'];
681     }
682     $i = 0;
683   
685     $res = get_list($filter,"users",$base,array("dn", "uid", "sn", "givenName"),$flag);
687     /* Fetch all users and skip already used users */
688     foreach($res as $attrs){
689       if(in_array($attrs['uid'][0], $this->memberUid)) {
690         continue;
691       }
692       $i ++;
693       if($i > $MaxUser) {
694         break;
695       }
696       $this->dnMapping[$attrs['uid'][0]]= $attrs["dn"];
697       $this->allusers[$attrs['uid'][0]]     = $this->createResultName($attrs);
698       $this->displayUsers[$attrs['uid'][0]] = $this->createResultName($attrs);
699     }
700   
701     /* If more than max users are found, display a message to warn the user */
702     if($i == $MaxUser){
703       msg_dialog::display(_("Configuration error"), sprintf(_("Search returned too many results. Not displaying more than %s entries!"), $MaxUser), ERROR_DIALOG);
704     }
705     
706     /* Sort lists */
707     natcasesort($this->members);
708     reset($this->members);
709     natcasesort ($this->displayUsers);
710     reset ($this->displayUsers);
711   }
714   /* Create display name, this was used so often that it is excluded into a seperate function */
715   function createResultName($attrs)
716   {
717     if (isset($attrs["givenName"][0]) && isset($attrs["sn"][0])){
718       $ret =  $attrs["sn"][0].", ".$attrs["givenName"][0]." [".$attrs["uid"][0]."]";
719     } else {
720       $ret= $attrs['uid'][0];
721     }
722     return($ret);
723   }
726   function remove_from_parent()
727   {
728     plugin::remove_from_parent();
730     $ldap= $this->config->get_ldap_link();
731     $ldap->rmdir($this->dn);
732     if (!$ldap->success()){
733       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
734     }
736     new log("remove","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
738     /* Delete references to object groups */
739     $ldap->cd ($this->config->current['BASE']);
740     $ldap->search ("(&(objectClass=gosaGroupOfNames)(member=".LDAP::prepare4filter($this->dn)."))", array("cn"));
741     while ($ldap->fetch()){
742       $og= new ogroup($this->config, $ldap->getDN());
743       unset($og->member[$this->dn]);
744       $og->save ();
745     }
747     /* Remove ACL dependencies too,
748      */
749     $ldap = $this->config->get_ldap_link();
750     $ldap->cd($this->config->current['BASE']);
751     $ldap->search("(&(objectClass=gosaAcl)(gosaAclEntry=*".base64_encode($this->dn)."*))",array("gosaAclEntry","dn"));
752     while($attrs = $ldap->fetch()){
753       $acl = new acl($this->config,$this->parent,$attrs['dn']);
754       foreach($acl->gosaAclEntry as $id => $entry){
755         foreach($entry['members'] as $m_id => $member){
756           if($m_id == "G:".$this->dn || $m_id == "U:".$this->dn){
757             unset($acl->gosaAclEntry[$id]['members'][$m_id]);
758             gosa_log("modify","groups/acl",$attrs['dn'],array(),sprintf("Removed acl for %s on object %s.",$this->dn,$attrs['dn']));
759           }
760         }
761       }
762       $acl->save();
763     }
765     /* Remove ACL dependencies too,
766      */
767     $tmp = new acl($this->config,$this->parent,$this->dn);
768     $tmp->remove_acl();
770     /* Send signal to the world that we've done */
771     $this->handle_post_events("remove");
772   }
775   /* Save data to object */
776   function save_object()
777   {
778     /* Save additional values for possible next step */
779     if (isset($_POST['groupedit'])){
781       /* Create a base backup and reset the 
782           base directly after calling plugin::save_object();  
783          Base will be set seperatly a few lines below */
784       $base_tmp = $this->base;
785       plugin::save_object();
786       $this->base = $base_tmp;
788       $this->force_gid= 0;
790       /* Only reset sambagroup flag if we are able to write this flag */
791       if($this->acl_is_writeable("sambaGroupType")){
792         $this->smbgroup = 0;
793       }
795       /* Get base selection */
796       if(isset($_POST['base'])){
797         $tmp = $this->get_allowed_bases();
798         if(isset($tmp[$_POST['base']])){
799           $this->base = $_POST['base'];
800         }
801       }
803       foreach (array(
804             "force_gid"  => "gidNumber", 
805             "smbgroup"   => "sambaGroupType") as $val => $aclname) {
806         if ($this->acl_is_writeable($aclname)  && isset($_POST["$val"])){
807           $this->$val= $_POST["$val"];
808         }
809       }
811       /* Save sambaDomain attribute */
812       if ($this->acl_is_writeable("sambaDomainName") && $this->samba3 && isset ($_POST['sambaDomainName'])){
813         $this->sambaDomainName= $_POST['sambaDomainName'];
814         $this->groupType= $_POST['groupType'];
815       }
817       /* Save fon attribute */
818       if ($this->acl_is_writeable("fon_group")){
819         if (isset ($_POST['fon_group'])){
820           $this->fon_group= TRUE;
821         } else {
822           $this->fon_group= FALSE;
823         }
824       }
825       if ($this->acl_is_writeable("nagios_group")){
826         if (isset ($_POST['nagios_group'])){
827           $this->nagios_group= TRUE;
828         } else {
829           $this->nagios_group= FALSE;
830         }
831       }
832     }
834     /* Trust mode - special handling */
835     if($this->acl_is_writeable("trustModel")){
836       if (isset($_POST['trustmode'])){
837         $saved= $this->trustModel;
838         if ($_POST['trustmode'] == "1"){
839           $this->trustModel= "fullaccess";
840         } elseif ($_POST['trustmode'] == "2"){
841           $this->trustModel= "byhost";
842         } else {
843           $this->trustModel= "";
844         }
845         if ($this->trustModel != $saved){
846           $this->is_modified= TRUE;
847         }
848       }
849     }
851   }
854   /* Save to LDAP */
855   function save()
856   {
858     /* ID handling */
859     if ($this->force_gid == 0){
860       if ($this->saved_gidNumber != ""){
861         $this->gidNumber= $this->saved_gidNumber;
862       } else {
863         /* Calculate new, lock uids */
864         $wait= 10;
865         while (get_lock("uidnumber") != ""){
866           sleep (1);
868           /* timed out? */
869           if ($wait-- == 0){
870             break;
871           }
872         }
873         add_lock ("uidnumber", "gosa");
874         $this->gidNumber= $this->get_next_id("gidNumber", $this->dn);
875       }
876     }
877   
878     plugin::save(); 
880  /* Trust accounts */
881     $objectclasses= array();
882     foreach ($this->attrs['objectClass'] as $key => $class){
883       if (preg_match('/trustAccount/i', $class)){
884         continue;
885       }
886       $objectclasses[]= $this->attrs['objectClass'][$key];
887     }
888     $this->attrs['objectClass']= $objectclasses;
889     if ($this->trustModel != ""){
890       $this->attrs['objectClass'][]= "trustAccount";
891       $this->attrs['trustModel']= $this->trustModel;
892       $this->attrs['accessTo']= array();
893       if ($this->trustModel == "byhost"){
894         foreach ($this->accessTo as $host){
895           $this->attrs['accessTo'][]= $host;
896         }
897       }
898     } else {
899       if ($this->was_trust_account){
900         $this->attrs['accessTo']= array();
901         $this->attrs['trustModel']= array();
902       }
903     }
907     /* Remove objectClass for samba/phone support */
908     $tmp= array();
909     for ($i= 0; $i<count($this->attrs["objectClass"]); $i++){
910       if ($this->attrs['objectClass'][$i] != 'sambaGroupMapping' &&
911           $this->attrs['objectClass'][$i] != 'sambaIdmapEntry' &&
912           $this->attrs['objectClass'][$i] != 'goFonPickupGroup' &&
913          $this->attrs['objectClass'][$i] != 'nagiosContactGroup'){
914         $tmp[]= $this->attrs['objectClass'][$i];
915       }
916     }
917     $this->attrs['objectClass']= $tmp;
918     $ldap= $this->config->get_ldap_link();
920     /* Add samba group functionality */
921     if ($this->samba3 && $this->smbgroup){
922   
923       /* Fixed undefined index ... 
924        */ 
925       $this->SID = $this->ridBase = "";
926       if(isset($this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['SID'])){
927         $this->SID    = $this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['SID'];
928       }else{
929         msg_dialog::display(_("Error"), sprintf(_("Cannot find any SID for '%s'!"), $this->sambaDomainName), ERROR_DIALOG);
930       }
931       if(isset($this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['RIDBASE'])){
932         $this->ridBase= $this->config->data['SERVERS']['SAMBA'][$this->sambaDomainName]['RIDBASE']; 
933       }else{
934         msg_dialog::display(_("Error"), sprintf(_("Cannot find any RIDBASE for '%s'!"), $this->sambaDomainName), ERROR_DIALOG);
935       }
937       $this->attrs['objectClass'][]= 'sambaGroupMapping';
938       $this->attrs['sambaGroupType']= "2";
940       /* Check if we need to create a special entry */
941       if ($this->groupType == 0){
943         if ($this->sambaSID == "" || $this->oldgroupType != $this->groupType){
944           $gidNumber= $this->gidNumber;
945           while(TRUE){
946             $sid= $this->SID."-".($gidNumber*2 + $this->ridBase+1);
947             $ldap->cd($this->config->current['BASE']);
948             $ldap->search("(sambaSID=$sid)",array("sambaSID"));
949             if ($ldap->count() == 0){
950               break;
951             }
952             $gidNumber++;
953           }
954           $this->attrs['sambaSID']= $sid;
955           $this->sambaSID= $sid;
956         }
958       } else {
959         $this->attrs['sambaSID']=$this->SID."-".$this->groupType;
960       }
962       /* User wants me to fake the idMappings? This is useful for
963          making winbind resolve the group names in a reasonable amount
964          of time in combination with larger databases. */
965       if (isset($this->config->current['SAMBAIDMAPPING']) &&
966           preg_match('/true/i', $this->config->current['SAMBAIDMAPPING'])){
967         $this->attrs['objectClass'][]= "sambaIdmapEntry";
968       }
970     }
972     /* Add phone functionality */
973     if ($this->fon_group){
974       $this->attrs['objectClass'][]= "goFonPickupGroup";
975     }
977     /* Add nagios functionality */
978     if ($this->nagios_group){
979       $this->attrs['objectClass'][]= "nagiosContactGroup";
980     }
982     /* Take members array */
983     if (count ($this->memberUid)){
984       $this->attrs['memberUid']= array_values(array_unique($this->memberUid));
985     }
987     /* New accounts need proper 'dn', propagate it to remaining objects */
988     if ($this->dn == 'new'){
989       $this->dn= 'cn='.$this->cn.','.get_groups_ou().$this->base;
990     }
992     /* Add member dn's for RFC2307bis Support */
993     if ($this->rfc2307bis){
994       $this->attrs['member'] = array();
995       if (count($this->memberUid)){
996         foreach($this->attrs['memberUid'] as $uid) {
997           $this->attrs['member'][]= $this->dnMapping[$uid];
998         }
999       } else {
1000         $this->attrs['member'][]= $this->dn;
1001       }
1002     }
1004     /* Save data. Using 'modify' implies that the entry is already present, use 'add' for
1005        new entries. So do a check first... */
1006     $ldap->cat ($this->dn, array('dn'));
1007     if ($ldap->fetch()){
1008       /* Modify needs array() to remove values :-( */
1009       if (!count ($this->memberUid)){
1010         $this->attrs['memberUid']= array();
1011       }
1012       if ($this->samba3){
1013         if (!$this->smbgroup){
1014           $this->attrs['sambaGroupType']= array();
1015           $this->attrs['sambaSID']= array();
1016         }
1017       }
1018       $mode= "modify";
1019     } else {
1020       $mode= "add";
1021       $ldap->cd($this->config->current['BASE']);
1022       $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
1023     }
1025     /* Write back to ldap */
1026     $ldap->cd($this->dn);
1027     $this->cleanup();
1028     $ldap->$mode($this->attrs);
1030     /* Remove ACL dependencies too,
1031      */
1032     if($this->dn != $this->orig_dn && $this->orig_dn != "new"){
1033       $tmp = new acl($this->config,$this->parent,$this->dn);
1034       $tmp->update_acl_membership($this->orig_dn,$this->dn);
1035     }
1037     if($this->initially_was_account){
1038       new log("modify","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1039     }else{
1040       new log("create","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1041     }
1043     $ret= 0;
1044     if (!$ldap->success()){
1045       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, 0, get_class()));
1046       $ret= 1;
1047     }
1049     /* Remove uid lock */
1050     del_lock ("uidnumber");
1052     /* Post that we've done*/
1053     $this->handle_post_events($mode);
1055     return ($ret);
1056   }
1058   function check()
1059   {
1060     /* Call common method to give check the hook */
1061     $message= plugin::check();
1063     /* Permissions for that base? */
1064     if ($this->base != ""){
1065       $new_dn= 'cn='.$this->cn.','.get_groups_ou().$this->base;
1066     } else {
1067       $new_dn= $this->dn;
1068     }
1070     /* must: cn */
1071     if ($this->cn == "" && $this->acl_is_writeable("cn")){
1072       $message[]= msgPool::required(_("Name"));
1073     }
1075     /* Check for valid input */
1076     if (!tests::is_uid($this->cn)){
1077       if (strict_uid_mode()){
1078         $message[]= msgPool::invalid(_("Name"), $this->cn, "/[a-z0-9_-]/");
1079       } else {
1080         $message[]= msgPool::invalid(_("Name"), $this->cn, "/[a-z0-9_-]/i");
1081       }
1082     }
1084     if($this->allowGroupsWithSameNameInOtherSubtrees == true){
1086       /* Check for used 'cn' */
1087       $ldap= $this->config->get_ldap_link();
1088       if(($this->cn  != $this->orig_cn) || ($this->orig_dn == "new")){
1089         $ldap->cd(get_groups_ou().$this->base);
1090         $ldap->ls("(&(|(objectClass=gosaGroupOfNames)(objectClass=posixGroup))(cn=$this->cn))",get_groups_ou().$this->base,array("cn"));
1091         if ($ldap->count() != 0){
1092           $message[]= msgPool::duplicated(_("Name"));
1093         }
1094       }
1096     }else{
1098       /* Check for used 'cn' */
1099       $ldap= $this->config->get_ldap_link();
1100       $ldap->cd($this->config->current['BASE']);
1101       $ldap->search("(&(|(objectClass=gosaGroupOfNames)(objectClass=posixGroup))(cn=$this->cn))",array("cn"));
1102       if ($ldap->count() != 0){
1104         /* New entry? */
1105         if ($this->dn == 'new'){
1106           $message[]= msgPool::duplicated(_("Name"));
1107         }
1109         /* Moved? */
1110         elseif ($new_dn != $this->orig_dn){
1111           $ldap->fetch();
1112           if ($ldap->getDN() != $this->orig_dn){
1113             $message[]= msgPool::duplicated(_("Name"));
1114           }
1115         }
1116       }
1117     }
1118      
1119     /* Check ID */
1120     if ($this->force_gid == "1"){
1121       if (!tests::is_id($this->gidNumber)){
1122         $message[]= msgPool::invalid(_("GID"), $this->gidNumber, "/[0-9]/");
1123       } else {
1124         if ($this->gidNumber < $this->config->current['MINID']){
1125           $message[]= msgPool::toosmall(_("GID"), $this->config->current['MINID']);
1126         }
1128       }
1129     }
1131     /* Check if we are allowed to create or move this object 
1132      */
1133     if($this->orig_dn == "new" && !$this->acl_is_createable($this->base)){
1134       $message[] = msgPool::permCreate();
1135     }elseif($this->orig_dn != "new" && $this->orig_base && !$this->acl_is_moveable($this->base)){
1136       $message[] = msgPool::permMove();
1137     }
1139     return ($message);
1140   }
1142   function get_next_id($attrib, $dn)
1143   {
1144     $ids= array();
1145     $ldap= $this->config->get_ldap_link();
1147     $ldap->cd ($this->config->current['BASE']);
1148     if (preg_match('/gidNumber/i', $attrib)){
1149       $oc= "posixGroup";
1150     } else {
1151       $oc= "posixAccount";
1152     }
1153     $ldap->search ("(&(objectClass=$oc)($attrib=*))", array("$attrib"));
1155     /* Get list of ids */
1156     while ($attrs= $ldap->fetch()){
1157       $ids[]= (int)$attrs["$attrib"][0];
1158     }
1160     /* Find out next free id near to UID_BASE */
1161     if (!isset($this->config->current['BASE_HOOK'])){
1162       $base= $this->config->current['UIDBASE'];
1163     } else {
1164       /* Call base hook */
1165       $base= get_base_from_hook($dn, $attrib);
1166     }
1167     for ($id= $base; $id++; $id < pow(2,32)){
1168       if (!in_array($id, $ids)){
1169         return ($id);
1170       }
1171     }
1173     /* Check if id reached maximum */
1174     if ($id >= pow(2,32)){
1175       msg_dialog::display(_("Error"), _("Cannot allocate a free ID!"), ERROR_DIALOG);
1176       exit;
1177     }
1178   }
1180   function getCopyDialog()
1181   {
1182     $vars = array("cn");
1183   
1184     if($this ->force_gid){
1185       $used = " checked ";
1186       $dis  = "";
1187     }else{
1188       $used = "";
1189       $dis  = " disabled ";
1190     }
1192     $smarty = get_smarty();
1193     $smarty->assign("used",$used);
1194     $smarty->assign("dis" ,$dis);
1195     $smarty->assign("cn" ,$this->cn);
1196     $smarty->assign("gidNumber",$this->gidNumber);
1197     $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE));
1198     $ret = array();
1199     $ret['string'] = $str;
1200     $ret['status'] = "";
1201     return($ret);
1202   }
1204   function saveCopyDialog()
1205   {
1206     if(isset($_POST['cn'])){
1207       $this->cn = $_POST['cn'];
1208     }
1209     if(isset($_POST['force_gid'])){
1210       $this->force_gid  = 1;
1211       $this->gidNumber= $_POST['gidNumber'];
1212     }else{
1213       $this->force_gid  = 0;
1214       $this->gidNumber  = false;
1215     }
1216   }
1218   
1219   /* Return plugin informations for acl handling  */ 
1220   static function plInfo()
1221   {
1222     return (array(  
1223           "plShortName" => _("Generic"),
1224           "plDescription" => _("Generic group settings"),
1225           "plSelfModify"  => FALSE,
1226           "plDepends"     => array(),
1227           "plPriority"    => 0,
1228           "plSection"     => array("admin"),
1229           "plCategory"    => array("groups" => array("objectClass" => "posixGroup", "description" => _("Groups"))),
1231           "plProvidedAcls"    => array(
1232             "cn"                => _("Name"),
1233             "base"              => _("Base"),
1234             "description"       => _("Description"),
1236             "fonGroup"          => _("Phone pickup group"),
1237             "nagiosGroup"       => _("Nagios group"),
1239             "gidNumber"         => _("GID"),
1240             "memberUid"         => _("Group member"),
1241             "sambaGroupType"    => _("Samba group type"),
1242             "sambaDomainName"   => _("Samba domain name"),
1243             "sambaSID"          => _("Samba SID"))
1244         ));
1245   }
1248   function multiple_save_object()
1249   {
1250     if(isset($_POST['group_mulitple_edit'])){
1252       /* Create a base backup and reset the
1253          base directly after calling plugin::save_object();
1254          Base will be set seperatly a few lines below */
1255       $base_tmp = $this->base;
1256       plugin::multiple_save_object();
1257       plugin::save_object();
1258       $this->base = $base_tmp;
1260       foreach(array("base","smbgroup","groupType","sambaDomainName","fon_group") as $attr){
1261         if(isset($_POST['use_'.$attr])){
1262           $this->multi_boxes[] = $attr;
1263         }
1264       }
1266       /* Get base selection */
1267       if(isset($_POST['base'])){
1268         $tmp = $this->get_allowed_bases();
1269         if(isset($tmp[$_POST['base']])){
1270           $this->base = $_POST['base'];
1271         }
1272       }
1274       foreach (array( "smbgroup"   => "sambaGroupType") as $val => $aclname) {
1275         if ($this->acl_is_writeable($aclname)){
1276           if(isset($_POST["$val"])){
1277             $this->$val=  TRUE;
1278           }else{
1279             $this->$val=  FALSE;
1280           }
1281         }
1282       }
1284       /* Save sambaDomain attribute */
1285       if ($this->acl_is_writeable("sambaDomainName") && $this->samba3 && isset ($_POST['sambaDomainName'])){
1286         $this->sambaDomainName= $_POST['sambaDomainName'];
1287         $this->groupType= $_POST['groupType'];
1288       }
1290       /* Save fon attribute */
1291       if ($this->acl_is_writeable("fon_group")){
1292         if (isset ($_POST['fon_group'])){
1293           $this->fon_group= TRUE;
1294         } else {
1295           $this->fon_group= FALSE;
1296         }
1297       }
1298     }
1299   }
1302   function get_multi_edit_values()
1303   {
1304     $ret = plugin::get_multi_edit_values();
1306     foreach(array("base","smbgroup","groupType","sambaDomainName","fon_group") as $attr){    
1307       if(in_array($attr,$this->multi_boxes)){
1308         $ret[$attr] = $this->$attr;
1309       }
1310     }
1311     $ret['memberUid'] = $this->memberUid;
1312     $ret['memberUid_used_by_some'] = $this->memberUid_used_by_some;
1313     return($ret);
1314   }
1316   function multiple_execute()
1317   {
1318     return($this->execute());
1319   }
1322   /* Initialize plugin with given atribute arrays
1323    */
1324   function init_multiple_support($attrs,$all)
1325   {
1326     plugin::init_multiple_support($attrs,$all);
1328     $this->memberUid = array();
1329     $this->memberUid_used_by_some = array();
1330     if (isset($attrs['memberUid'])){
1331       for ($i= 0; $i<$attrs['memberUid']['count']; $i++){
1332         $this->memberUid[$attrs['memberUid'][$i]]= $attrs['memberUid'][$i];
1333       }
1334       ksort($this->memberUid);
1335     }
1337     if (isset($all['memberUid'])){
1338       for ($i= 0; $i<$all['memberUid']['count']; $i++){
1339         if(!in_array($all['memberUid'][$i],$this->memberUid)){
1340           $this->memberUid_used_by_some[$all['memberUid'][$i]]= $all['memberUid'][$i];
1341         }
1342       }
1343       ksort($this->memberUid_used_by_some);
1344     }
1345   }
1348   function PrepareForCopyPaste($source)
1349   {
1350     plugin::PrepareForCopyPaste($source);
1352     $this->memberUid = array();
1353     if(isset($source['memberUid'])){
1354       for($i = 0 ; $i < $source['memberUid']['count']; $i ++){
1355         $this->memberUid[] = $source['memberUid'][$i];
1356       }
1357     }
1358   }
1361   function set_multi_edit_values($attrs)
1362   {
1363     $users = array();
1365     /* Update groupMembership, keep optinal group */
1366     foreach($attrs['memberUid_used_by_some'] as $uid){
1367       if(in_array($uid,$this->memberUid)){
1368         $users[$uid] = $uid;
1369       }
1370     }
1372     /* Update groupMembership, add forced groups */
1373     foreach($attrs['memberUid'] as $uid){
1374       $users[$uid] = $uid;
1375     }
1376     plugin::set_multi_edit_values($attrs);
1377     $this->memberUid = $users;
1378   }
1380 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1381 ?>