1 <?php
4 /* Sort multidimensional arrays for key 'text' */
5 function sort_list($val1, $val2)
6 {
7 $v1= strtolower($val1['text']);
8 $v2= strtolower($val2['text']);
9 if ($v1 > $v2){
10 return 1;
11 }
12 if ($v1 < $v2){
13 return -1;
14 }
15 return 0;
16 }
19 class ogroup extends plugin
20 {
21 /* Variables */
22 var $cn= "";
23 var $description= "";
24 var $base= "";
25 var $gosaGroupObjects= "";
26 var $department= "";
27 var $objects= array();
28 var $objcache= array();
29 var $memberList= array();
30 var $member= array();
31 var $orig_dn= "";
32 var $group_dialog= FALSE;
33 var $view_logged = FALSE;
35 /* attribute list for save action */
36 var $attributes= array("cn", "description", "gosaGroupObjects","member");
37 var $objectclasses= array("top", "gosaGroupOfNames");
39 function ogroup (&$config, $dn= NULL)
40 {
41 plugin::plugin ($config, $dn);
42 $this->orig_dn= $dn;
44 $this->member = array();
46 /* Load member objects */
47 if (isset($this->attrs['member'])){
48 foreach ($this->attrs['member'] as $key => $value){
49 if ("$key" != "count"){
50 $value= @LDAP::convert($value);
51 $this->member["$value"]= "$value";
52 }
53 }
54 }
55 $this->is_account= TRUE;
57 /* Get global filter config */
58 if (!session::is_set("ogfilter")){
59 $ui= get_userinfo();
60 $base= get_base_from_people($ui->dn);
61 $ogfilter= array( "dselect" => $base,
62 "regex" => "*");
63 session::set("ogfilter", $ogfilter);
64 }
65 $ogfilter= session::get('ogfilter');
67 /* Adjust flags */
68 foreach( array( "U" => "accounts",
69 "G" => "groups",
70 "A" => "applications",
71 "D" => "departments",
72 "S" => "servers",
73 "W" => "workstations",
74 "O" => "winstations",
75 "T" => "terminals",
76 "F" => "phones",
77 "_" => "subtrees",
78 "P" => "printers") as $key => $val){
80 if (preg_match("/$key/", $this->gosaGroupObjects)){
81 $ogfilter[$val]= "checked";
82 } else {
83 $ogfilter[$val]= "";
84 }
85 }
86 session::set("ogfilter", $ogfilter);
88 if(session::is_set('CurrentMainBase')){
89 $this->base = session::get('CurrentMainBase');
90 }
92 /* Set base */
93 if ($this->dn == "new"){
94 $this->base = session::get('CurrentMainBase');
95 } else {
96 $this->base= preg_replace("/^[^,]+,".get_groups_ou()."/","",$this->dn);
97 }
99 /* Load member data */
100 $this->reload();
101 }
103 function AddDelMembership($NewMember = false){
105 if($NewMember){
107 /* Add member and force reload */
108 $this->member[$NewMember]= $NewMember;
109 $this->reload();
111 $this->memberList[$NewMember]= $this->objcache[$NewMember];
112 unset ($this->objects[$NewMember]);
113 uasort ($this->memberList, 'sort_list');
114 reset ($this->memberList);
115 }else{
116 /* Delete objects from group */
117 if (isset($_POST['delete_membership']) && isset($_POST['members'])){
118 foreach ($_POST['members'] as $value){
119 $this->objects["$value"]= $this->memberList[$value];
120 unset ($this->memberList["$value"]);
121 unset ($this->member["$value"]);
122 uasort ($this->objects, 'sort_list');
123 reset ($this->objects);
124 }
125 $this->reload();
126 }
128 /* Add objects to group */
129 if (isset($_POST['add_object_finish']) && isset($_POST['objects'])){
130 foreach ($_POST['objects'] as $value){
131 $this->memberList["$value"]= $this->objects[$value];
132 $this->member["$value"]= $value;
133 unset ($this->objects[$value]);
134 uasort ($this->memberList, 'sort_list');
135 reset ($this->memberList);
136 }
137 $this->reload();
138 }
139 }
140 }
142 function execute()
143 {
144 /* Call parent execute */
145 plugin::execute();
147 if(!$this->view_logged){
148 $this->view_logged = TRUE;
149 new log("view","ogroups/".get_class($this),$this->dn);
150 }
153 /* Do we represent a valid group? */
154 if (!$this->is_account){
155 $display= "<img alt=\"\" src=\"images/stop.png\" align=\"middle\"> <b>".
156 _("This 'dn' is no object group.")."</b>";
157 return ($display);
158 }
160 /* Delete objects from group */
161 if (isset($_POST['delete_membership']) && isset($_POST['members'])){
162 foreach ($_POST['members'] as $value){
163 if(isset($this->memberList[$value])){
164 $this->objects["$value"]= $this->memberList[$value];
165 unset ($this->memberList["$value"]);
166 unset ($this->member["$value"]);
167 uasort ($this->objects, 'sort_list');
168 reset ($this->objects);
169 }
170 }
171 $this->reload();
172 }
174 /* Add objects to group */
175 if (isset($_POST['add_object_finish']) && isset($_POST['objects'])){
176 foreach ($_POST['objects'] as $value){
177 if(isset($this->objects[$value])){
178 $this->memberList["$value"]= $this->objects[$value];
179 $this->member["$value"]= $value;
180 unset ($this->objects[$value]);
181 uasort ($this->memberList, 'sort_list');
182 reset ($this->memberList);
183 }
184 }
185 $this->reload();
186 }
188 /* Load templating engine */
189 $smarty= get_smarty();
191 $tmp = $this->plInfo();
192 foreach($tmp['plProvidedAcls'] as $name => $translation){
193 $smarty->assign($name."ACL",$this->getacl($name));
194 }
196 /* Base select dialog */
197 $once = true;
198 foreach($_POST as $name => $value){
199 if(preg_match("/^chooseBase/",$name) && $once && $this->acl_is_moveable()){
200 $once = false;
201 $this->dialog = new baseSelectDialog($this->config,$this,$this->get_allowed_bases());
202 $this->dialog->setCurrentBase($this->base);
203 }
204 }
206 /* Dialog handling */
207 if(is_object($this->dialog) && $this->acl_is_moveable()){
208 /* Must be called before save_object */
209 $this->dialog->save_object();
211 if($this->dialog->isClosed()){
212 $this->dialog = false;
213 }elseif($this->dialog->isSelected()){
215 /* A new base was selected, check if it is a valid one */
216 $tmp = $this->get_allowed_bases();
217 if(isset($tmp[$this->dialog->isSelected()])){
218 $this->base = $this->dialog->isSelected();
219 }
220 $this->dialog= false;
221 }else{
222 return($this->dialog->execute());
223 }
224 }
226 /* Add objects? */
227 if (isset($_POST["edit_membership"])){
228 $this->group_dialog= TRUE;
229 $this->dialog= TRUE;
230 }
232 /* Add objects finished? */
233 if (isset($_POST["add_object_finish"]) || isset($_POST["add_object_cancel"])){
234 $this->group_dialog= FALSE;
235 $this->dialog= FALSE;
236 }
238 /* Manage object add dialog */
239 if ($this->group_dialog){
241 /* Save data */
242 $ogfilter= session::get("ogfilter");
243 foreach( array("dselect", "regex") as $type){
244 if (isset($_POST[$type])){
245 $ogfilter[$type]= $_POST[$type];
246 }
247 }
248 if (isset($_POST['dselect'])){
249 foreach( array("accounts", "groups", "applications", "departments",
250 "servers", "workstations", "winstations", "terminals", "printers","subtrees",
251 "phones") as $type){
253 if (isset($_POST[$type])) {
254 $ogfilter[$type]= "checked";
255 } else {
256 $ogfilter[$type]= "";
257 }
258 }
259 }
260 if (isset($_GET['search'])){
261 $s= mb_substr($_GET['search'], 0, 1, "UTF8")."*";
262 if ($s == "**"){
263 $s= "*";
264 }
265 $ogfilter['regex']= $s;
266 }
267 session::set("ogfilter", $ogfilter);
268 $this->reload();
270 /* Calculate actual groups */
271 $smarty->assign("objects", $this->convert_list($this->objects));
273 /* Show dialog */
274 $smarty->assign("search_image", get_template_path('images/search.png'));
275 $smarty->assign("launchimage", get_template_path('images/small_filter.png'));
276 $smarty->assign("tree_image", get_template_path('images/tree.png'));
277 $smarty->assign("deplist", $this->config->idepartments);
278 $smarty->assign("alphabet", generate_alphabet());
279 foreach( array("dselect", "regex", "accounts", "groups", "applications",
280 "departments", "servers", "workstations", "winstations", "terminals","subtrees",
281 "printers", "phones") as $type){
282 $smarty->assign("$type", $ogfilter[$type]);
283 }
284 $smarty->assign("hint", print_sizelimit_warning());
285 $smarty->assign("apply", apply_filter());
287 $display= $smarty->fetch (get_template_path('ogroup_objects.tpl', TRUE, dirname(__FILE__)));
288 return ($display);
289 }
291 /* Bases / Departments */
292 if ((isset($_POST['base'])) && ($this->acl_is_moveable())){
293 $this->base= $_POST['base'];
294 }
296 /* Assemble combine string */
297 if ($this->gosaGroupObjects == "[]"){
298 $smarty->assign("combinedObjects", _("none"));
299 } elseif (strlen($this->gosaGroupObjects) > 4){
300 $smarty->assign("combinedObjects", "<font color=red>"._("too many different objects!")."</font>");
301 } else {
302 $conv= array( "U" => _("users"),
303 "G" => _("groups"),
304 "A" => _("applications"),
305 "D" => _("departments"),
306 "S" => _("servers"),
307 "W" => _("workstations"),
308 "O" => _("winstations"),
309 "T" => _("terminals"),
310 "F" => _("phones"),
311 "P" => _("printers"));
313 $type= preg_replace('/[\[\]]/', '', $this->gosaGroupObjects);
314 $p1= $conv[$type[0]];
315 error_reporting(0);
316 if (isset($type[1]) && preg_match('/[UGADSFOWTP]/', $type[1])){
317 $p2= $conv[$type[1]];
318 $smarty->assign("combinedObjects", "$p1 "._("and")." $p2");
319 } else {
320 $smarty->assign("combinedObjects", "$p1");
321 }
322 error_reporting(E_ALL | E_STRICT);
323 }
325 /* Assign variables */
326 $smarty->assign("bases", $this->get_allowed_bases());
327 $smarty->assign("base_select", $this->base);
328 $smarty->assign("department", $this->department);
329 $smarty->assign("members", $this->convert_list($this->memberList));
331 /* Objects have to be tuned... */
332 $smarty->assign("objects", $this->convert_list($this->objects));
334 /* Fields */
335 foreach ($this->attributes as $val){
336 $smarty->assign("$val", $this->$val);
337 }
339 return ($smarty->fetch (get_template_path('generic.tpl', TRUE)));
340 }
343 /* Save data to object */
344 function save_object()
345 {
346 /* Save additional values for possible next step */
347 if (isset($_POST['ogroupedit'])){
349 /* Create a base backup and reset the
350 base directly after calling plugin::save_object();
351 Base will be set seperatly a few lines below */
352 $base_tmp = $this->base;
353 plugin::save_object();
354 $this->base = $base_tmp;
356 /* Save base, since this is no LDAP attribute */
357 $tmp = $this->get_allowed_bases();
358 if(isset($_POST['base'])){
359 if(isset($tmp[$_POST['base']])){
360 $this->base= $_POST['base'];
361 }
362 }
363 }
364 }
367 /* (Re-)Load objects */
368 function reload()
369 {
370 /*###########
371 Variable initialisation
372 ###########*/
374 $this->objects = array();
375 $this->ui = get_userinfo();
376 $filter = "";
377 $objectClasses = array();
379 $ogfilter = session::get("ogfilter");
380 $regex = $ogfilter['regex'];
382 $ldap= $this->config->get_ldap_link();
383 $ldap->cd ($ogfilter['dselect']);
386 /*###########
387 Generate Filter
388 ###########*/
390 $p_f= array("accounts" => array("CLASS"=>"gosaAccount" ,"DN"=> get_people_ou() ,"ACL" => "users"),
391 "groups" => array("CLASS"=>"posixGroup" ,"DN"=> get_groups_ou() ,"ACL" => "groups"),
392 "applications" => array("CLASS"=>"gosaApplication","DN"=> get_ou('applicationou') ,"ACL" => "application"),
393 "departments" => array("CLASS"=>"gosaDepartment" ,"DN"=> "" ,"ACL" => "department"),
394 "servers" => array("CLASS"=>"goServer" ,"DN"=> get_ou('serverou') ,"ACL" => "server"),
395 "workstations" => array("CLASS"=>"gotoWorkstation","DN"=> get_ou('workstationou') ,"ACL" => "workstation"),
396 "winstations" => array("CLASS"=>"opsiClient", "DN"=> get_ou('WINSTATIONS') ,"ACL" => "winstation"),
397 "terminals" => array("CLASS"=>"gotoTerminal" ,"DN"=> get_ou('terminalou') ,"ACL" => "terminal"),
398 "printers" => array("CLASS"=>"gotoPrinter" ,"DN"=> get_ou('printerou') ,"ACL" => "printer"),
399 "phones" => array("CLASS"=>"goFonHardware" ,"DN"=> get_ou('phoneou') ,"ACL" => "phone"));
402 /*###########
403 Perform search for selected objectClasses & regex to fill list with objects
404 ###########*/
406 $Get_list_flags = 0;
407 if($ogfilter['subtrees'] == "checked"){
408 $Get_list_flags |= GL_SUBSEARCH;
409 }
411 foreach($p_f as $post_name => $data){
413 if($ogfilter[$post_name] == "checked"){
415 if($ogfilter['subtrees']){
416 $base = $ogfilter['dselect'];
417 }else{
418 $base = $data['DN'].$ogfilter['dselect'];
419 }
421 $filter = "(&(objectClass=".$data['CLASS'].")(|(uid=$regex)(cn=$regex)(ou=$regex)))";
422 $res = get_list($filter, $data['ACL'] , $base,
423 array("description", "objectClass", "sn", "givenName", "uid","ou","cn"),$Get_list_flags);
425 /* fetch results and append them to the list */
426 foreach($res as $attrs){
428 $type= $this->getObjectType($attrs);
429 $name= $this->getObjectName($attrs);
431 /* Fill array */
432 if (isset($attrs["description"][0])){
433 $this->objects[$attrs["dn"]]= array("text" => "$name [".$attrs["description"][0]."]", "type" => "$type");
434 } elseif (isset($attrs["uid"][0])) {
435 $this->objects[$attrs["dn"]]= array("text" => "$name [".$attrs["uid"][0]."]", "type" => "$type");
436 } else {
437 $this->objects[$attrs["dn"]]= array("text" => "$name", "type" => "$type");
438 }
439 }
440 }
441 }
442 uasort ($this->objects, 'sort_list');
443 reset ($this->objects);
446 /*###########
447 Build member list and try to detect obsolete entries
448 ###########*/
450 $this->memberList = array();
452 /* Walk through all single member entry */
453 foreach($this->member as $dn){
455 /* The dn for the current member can't be resolved
456 it seams that this entry was removed
457 */
458 /* Try to resolv the entry again, if it still fails, display error msg */
459 $ldap->cat($dn, array("cn", "sn", "givenName", "ou", "description", "objectClass"));
461 /* It has failed, add entry with type flag I (Invalid)*/
462 if ($ldap->error != "Success"){
463 $this->memberList[$dn]= array('text' => _("Non existing dn:")." ".@LDAP::fix($dn),"type" => "I");
465 } else {
467 /* Append this entry to our all object list */
469 /* Fetch object */
470 $attrs= $ldap->fetch();
472 $type= $this->getObjectType($attrs);
473 $name= $this->getObjectName($attrs);
475 if (isset($attrs["description"][0])){
476 $this->objcache[$attrs["dn"]]= array("text" => "$name [".$attrs["description"][0]."]", "type" => "$type");
477 } elseif (isset($attrs["uid"][0])) {
478 $this->objcache[$attrs["dn"]]= array("text" => "$name [".$attrs["uid"][0]."]", "type" => "$type");
479 } else {
480 $this->objcache[$attrs["dn"]]= array("text" => "$name", "type" => "$type");
481 }
482 $this->objcache[$attrs["dn"]]['objectClass'] = $attrs['objectClass'];
483 if(isset($attrs['uid'])){
484 $this->objcache[$attrs["dn"]]['uid'] = $attrs['uid'];
485 }
487 /* Fill array */
488 if (isset($attrs["description"][0])){
489 $this->objects[$attrs["dn"]]= array("text" => "$name [".$attrs["description"][0]."]", "type" => "$type");
490 } else {
491 $this->objects[$attrs["dn"]]= array("text" => "$name", "type" => "$type");
492 }
494 $this->memberList[$dn]= $this->objects[$attrs["dn"]];
495 }
496 }
497 uasort ($this->memberList, 'sort_list');
498 reset ($this->memberList);
500 /* Assemble types of currently combined objects */
501 $objectTypes= "";
502 foreach ($this->memberList as $dn => $desc){
504 /* Invalid object? */
505 if ($desc['type'] == 'I'){
506 continue;
507 }
509 /* Fine. Add to list. */
510 if (!preg_match('/'.$desc['type'].'/', $objectTypes)){
511 $objectTypes.= $desc['type'];
512 }
513 }
514 $this->gosaGroupObjects= "[$objectTypes]";
515 }
518 function convert_list($input)
519 {
520 $temp= "";
521 $conv= array( "U" => "select_user.png",
522 "G" => "select_groups.png",
523 "A" => "select_application.png",
524 "D" => "select_department.png",
525 "S" => "select_server.png",
526 "W" => "select_workstation.png",
527 "O" => "select_winstation.png",
528 "T" => "select_terminal.png",
529 "F" => "select_phone.png",
530 "I" => "flag.png",
531 "P" => "select_printer.png");
533 foreach ($input as $key => $value){
534 /* Generate output */
535 $temp.= "<option title='".addslashes( $key)."' value=\"$key\" class=\"select\" style=\"background-image:url('".get_template_path("images/".$conv[$value['type']])."');\">".$value['text']."</option>\n";
536 }
538 return ($temp);
539 }
542 function getObjectType($attrs)
543 {
544 $type= "I";
546 foreach(array( "U" => "gosaAccount",
547 "G" => "posixGroup",
548 "A" => "gosaApplication",
549 "D" => "gosaDepartment",
550 "S" => "goServer",
551 "W" => "gotoWorkstation",
552 "O" => "opsiClient",
553 "T" => "gotoTerminal",
554 "F" => "goFonHardware",
555 "P" => "gotoPrinter") as $index => $class){
556 if (in_array($class, $attrs['objectClass'])){
557 $type= $index;
558 break;
559 }
560 }
562 return ($type);
563 }
566 function getObjectName($attrs)
567 {
568 /* Person? */
569 $name ="";
570 if (in_array('gosaAccount', $attrs['objectClass'])){
571 if(isset($attrs['sn']) && isset($attrs['givenName'])){
572 $name= $attrs['sn'][0].", ".$attrs['givenName'][0];
573 } else {
574 $name= $attrs['uid'][0];
575 }
576 } else {
577 if(isset($attrs["cn"][0])) {
578 $name= $attrs['cn'][0];
579 } else {
580 $name= $attrs['ou'][0];
581 }
582 }
584 return ($name);
585 }
588 function check()
589 {
590 /* Call common method to give check the hook */
591 $message= plugin::check();
593 /* Permissions for that base? */
594 if ($this->base != ""){
595 $new_dn= 'cn='.$this->cn.','.get_groups_ou().$this->base;
596 } else {
597 $new_dn= $this->dn;
598 }
601 $ldap = $this->config->get_ldap_link();
602 if($this->dn != $new_dn){
603 $ldap->cat ($new_dn, array('dn'));
604 }
606 if($ldap->count() !=0){
607 $message[]= _("There is already an object with this cn.");
608 }
610 /* Set new acl base */
611 if($this->dn == "new") {
612 $this->set_acl_base($this->base);
613 }
615 /* must: cn */
616 if ($this->cn == ""){
617 $message[]= "The required field 'Name' is not set.";
618 }
620 /* To many different object types? */
621 if (strlen($this->gosaGroupObjects) > 4){
622 $message[]= _("You can combine two different object types at maximum only!");
623 }
625 return ($message);
626 }
629 /* Save to LDAP */
630 function save()
631 {
632 plugin::save();
634 /* Move members to target array */
635 $this->attrs['member'] =array();
636 foreach ($this->member as $key => $desc){
637 $this->attrs['member'][]= @LDAP::fix($key);
638 }
640 $ldap= $this->config->get_ldap_link();
642 /* New accounts need proper 'dn', propagate it to remaining objects */
643 if ($this->dn == 'new'){
644 $this->dn= 'cn='.$this->cn.','.get_groups_ou().$this->base;
645 }
647 /* Save data. Using 'modify' implies that the entry is already present, use 'add' for
648 new entries. So do a check first... */
649 $ldap->cat ($this->dn, array('dn'));
650 if ($ldap->fetch()){
651 /* Modify needs array() to remove values :-( */
652 if (!count ($this->member)){
653 $this->attrs['member']= array();
654 }
655 $mode= "modify";
657 } else {
658 $mode= "add";
659 $ldap->cd($this->config->current['BASE']);
660 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
661 }
663 /* Write back to ldap */
664 $ldap->cd($this->dn);
665 $this->cleanup();
666 $ldap->$mode($this->attrs);
668 if($mode == "add"){
669 new log("create","ogroups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
670 }else{
671 new log("modify","ogroups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
672 }
674 /* Trigger post signal */
675 $this->handle_post_events($mode);
677 $ret= 0;
678 if (show_ldap_error($ldap->get_error(), sprintf(_("Saving of object group/generic with dn '%s' failed."),$this->dn))){
679 $ret= 1;
680 }
682 return ($ret);
683 }
685 function remove_from_parent()
686 {
687 plugin::remove_from_parent();
689 $ldap= $this->config->get_ldap_link();
690 $ldap->rmdir($this->dn);
691 show_ldap_error($ldap->get_error(), sprintf(_("Removing of object group/generic with dn '%s' failed."),$this->dn));
693 new log("remove","ogroups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
695 /* Trigger remove signal */
696 $this->handle_post_events("remove");
697 }
700 function PrepareForCopyPaste($source)
701 {
702 /* Update available object types */
703 if(isset($source['gosaGroupObjects'][0])){
704 $this->gosaGroupObjects = $source['gosaGroupObjects'][0];
705 }
707 /* Reload tabs */
708 $this->parent->reload($this->gosaGroupObjects );
710 /* Reload plugins */
711 foreach($this->parent->by_object as $name => $class ){
712 if(get_class($this) != $name) {
713 $this->parent->by_object[$name]->PrepareForCopyPaste($source);
714 }
715 }
717 /* Load member objects */
718 if (isset($source['member'])){
719 foreach ($source['member'] as $key => $value){
720 if ("$key" != "count"){
721 $value= @LDAP::convert($value);
722 $this->member["$value"]= "$value";
723 }
724 }
725 }
727 }
730 function getCopyDialog()
731 {
732 $smarty = get_smarty();
733 $smarty->assign("cn", $this->cn);
734 $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE,dirname(__FILE__)));
735 $ret = array();
736 $ret['string'] = $str;
737 $ret['status'] = "";
738 return($ret);
739 }
741 function saveCopyDialog()
742 {
743 if(isset($_POST['cn'])){
744 $this->cn = $_POST['cn'];
745 }
746 }
749 static function plInfo()
750 {
751 return (array(
752 "plShortName" => _("Generic"),
753 "plDescription" => _("Object group generic"),
754 "plSelfModify" => FALSE,
755 "plDepends" => array(),
756 "plPriority" => 1,
757 "plSection" => array("administration"),
758 "plCategory" => array("ogroups" => array("description" => _("Object groups"),
759 "objectClass" => "gosaGroupOfNames")),
760 "plProvidedAcls"=> array(
761 "cn" => _("Name"),
762 "base" => _("Base"),
763 "description" => _("Description"),
764 "member" => _("Member"))
765 ));
766 }
767 }
769 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
770 ?>