1 <?php
3 class aclrole extends acl
4 {
5 /* Definitions */
6 var $plHeadline= "Access control list templates";
7 var $plDescription= "This does something";
9 /* attribute list for save action */
10 var $attributes= array('gosaAclTemplate',"cn","description");
11 var $objectclasses= array('top','gosaRole');
13 /* Helpers */
14 var $dialogState= "head";
15 var $aclType= "";
16 var $aclObject= "";
17 var $aclContents= array();
18 var $target= "group";
19 var $aclTypes= array();
20 var $aclObjects= array();
21 var $recipients= array();
22 var $isContainer= TRUE;
23 var $currentIndex= 0;
24 var $wasNewEntry= FALSE;
25 var $ocMapping= array();
26 var $savedAclContents= array();
27 var $myAclObjects = array();
29 /* Role attributes */
30 var $gosaAclTemplate= "";
31 var $cn = "";
32 var $description = "";
33 var $orig_dn;
34 var $base ="";
36 function aclrole ($config, $dn= NULL)
37 {
38 /* Include config object */
39 plugin::plugin($config, $dn);
41 if($this->dn == "new"){
42 $this->base = $_SESSION['CurrentMainBase'];
43 }else{
44 $this->base = preg_replace("/^[^,]+,[^,]+,/","",$this->dn);
45 }
47 /* Load ACL's */
48 $this->gosaAclTemplate= array();
49 if (isset($this->attrs["gosaAclTemplate"])){
50 for ($i= 0; $i<$this->attrs["gosaAclTemplate"]['count']; $i++){
51 $acl= $this->attrs["gosaAclTemplate"][$i];
52 $this->gosaAclTemplate= array_merge($this->gosaAclTemplate, $this->explodeACL($acl));
53 }
54 }
55 ksort($this->gosaAclTemplate);
57 /* Extract available categories from plugin info list */
58 $tmp= get_global('plist');
59 $plist= $tmp->info;
60 $oc = array();
61 foreach ($plist as $class => $acls){
63 /* Only feed categories */
64 if (isset($acls['plCategory'])){
66 /* Walk through supplied list and feed only translated categories */
67 foreach($acls['plCategory'] as $idx => $data){
69 /* Non numeric index means -> base object containing more informations */
70 if (preg_match('/^[0-9]+$/', $idx)){
71 if (!isset($this->ocMapping[$data])){
72 $this->ocMapping[$data]= array();
73 $this->ocMapping[$data][]= '0';
74 }
75 $this->ocMapping[$data][]= $class;
76 } else {
77 if (!isset($this->ocMapping[$idx])){
78 $this->ocMapping[$idx]= array();
79 $this->ocMapping[$idx][]= '0';
80 }
81 $this->ocMapping[$idx][]= $class;
82 $this->aclObjects[$idx]= $data['description'];
84 /* Additionally filter the classes we're interested in in "self edit" mode */
85 if (is_array($data['objectClass'])){
86 foreach($data['objectClass'] as $objectClass){
87 if (in_array_ics($objectClass, $oc)){
88 $this->myAclObjects[$idx.'/'.$class]= $acls['plDescription'];
89 break;
90 }
91 }
92 } else {
93 if (in_array_ics($data['objectClass'], $oc)){
94 $this->myAclObjects[$idx.'/'.$class]= $acls['plDescription'];
95 }
96 }
97 }
99 }
100 }
101 }
102 $this->aclObjects['all']= '* '._("All categories");
103 $this->ocMapping['all']= array('0' => 'all');
105 /* Sort categories */
106 asort($this->aclObjects);
108 /* Fill acl types */
109 $this->aclTypes= array( "reset" => _("Reset ACLs"),
110 "one" => _("One level"),
111 "base" => _("Current object"),
112 "sub" => _("Complete subtree"),
113 "psub" => _("Complete subtree (permanent)"));
114 asort($this->aclTypes);
116 /* Finally - we want to get saved... */
117 $this->is_account= TRUE;
118 }
121 function execute()
122 {
123 /* Call parent execute */
124 plugin::execute();
126 /* Base select dialog */
127 $once = true;
128 foreach($_POST as $name => $value){
129 if((preg_match("/^chooseBase/",$name) && $once) && ($this->acl_is_moveable())){
130 $once = false;
131 $this->dialog = new baseSelectDialog($this->config,$this,$this->get_allowed_bases());
132 $this->dialog->setCurrentBase($this->base);
133 }
134 }
136 /* Dialog handling */
137 if(is_object($this->dialog)){
138 /* Must be called before save_object */
139 $this->dialog->save_object();
141 if($this->dialog->isClosed()){
142 $this->dialog = false;
143 }elseif($this->dialog->isSelected()){
145 /* Check if selected base is valid */
146 $tmp = $this->get_allowed_bases();
147 if(isset($tmp[$this->dialog->isSelected()])){
148 $this->base = $this->dialog->isSelected();
149 }
150 $this->dialog= false;
151 }else{
152 return($this->dialog->execute());
153 }
154 }
156 $tmp= get_global('plist');
157 $plist= $tmp->info;
159 /* Handle posts */
160 if (isset($_POST['new_acl'])){
161 $this->dialogState= 'create';
162 $this->dialog= TRUE;
163 $this->currentIndex= count($this->gosaAclTemplate);
164 $this->loadAclEntry(TRUE);
165 }
167 $new_acl= array();
168 $aclDialog= FALSE;
169 $firstedit= FALSE;
170 foreach($_POST as $name => $post){
172 /* Actions... */
173 if (preg_match('/^acl_edit_.*_x/', $name)){
174 $this->dialogState= 'create';
175 $firstedit= TRUE;
176 $this->dialog= TRUE;
177 $this->currentIndex= preg_replace('/^acl_edit_([0-9]+).*$/', '\1', $name);
178 $this->loadAclEntry();
179 continue;
180 }
181 if (preg_match('/^acl_del_.*_x/', $name)){
182 unset($this->gosaAclTemplate[preg_replace('/^acl_del_([0-9]+).*$/', '\1', $name)]);
183 continue;
184 }
186 if (preg_match('/^cat_edit_.*_x/', $name)){
187 $this->aclObject= preg_replace('/^cat_edit_([^_]+)_.*$/', '\1', $name);
188 $this->dialogState= 'edit';
189 foreach ($this->ocMapping[$this->aclObject] as $oc){
190 if (isset($this->aclContents[$oc])){
191 $this->savedAclContents[$oc]= $this->aclContents[$oc];
192 }
193 }
194 continue;
195 }
196 if (preg_match('/^cat_del_.*_x/', $name)){
197 $idx= preg_replace('/^cat_del_([^_]+)_.*$/', '\1', $name);
198 foreach ($this->ocMapping[$idx] as $key){
199 unset($this->aclContents["$idx/$key"]);
200 }
201 continue;
202 }
204 /* Sorting... */
205 if (preg_match('/^sortup_.*_x/', $name)){
206 $index= preg_replace('/^sortup_([0-9]+).*$/', '\1', $name);
207 if ($index > 0){
208 $tmp= $this->gosaAclTemplate[$index];
209 $this->gosaAclTemplate[$index]= $this->gosaAclTemplate[$index-1];
210 $this->gosaAclTemplate[$index-1]= $tmp;
211 }
212 continue;
213 }
214 if (preg_match('/^sortdown_.*_x/', $name)){
215 $index= preg_replace('/^sortdown_([0-9]+).*$/', '\1', $name);
216 if ($index < count($this->gosaAclTemplate)-1){
217 $tmp= $this->gosaAclTemplate[$index];
218 $this->gosaAclTemplate[$index]= $this->gosaAclTemplate[$index+1];
219 $this->gosaAclTemplate[$index+1]= $tmp;
220 }
221 continue;
222 }
224 /* ACL saving... */
225 if (preg_match('/^acl_.*_[^xy]$/', $name)){
226 $aclDialog= TRUE;
227 list($dummy, $object, $attribute, $value)= split('_', $name);
229 /* Skip for detection entry */
230 if ($object == 'dummy') {
231 continue;
232 }
234 /* Ordinary ACLs */
235 if (!isset($new_acl[$object])){
236 $new_acl[$object]= array();
237 }
238 if (isset($new_acl[$object][$attribute])){
239 $new_acl[$object][$attribute].= $value;
240 } else {
241 $new_acl[$object][$attribute]= $value;
242 }
243 }
244 }
246 /* Only be interested in new acl's, if we're in the right _POST place */
247 if ($aclDialog && $this->aclObject != "" && is_array($this->ocMapping[$this->aclObject])){
249 foreach ($this->ocMapping[$this->aclObject] as $oc){
250 unset($this->aclContents[$oc]);
251 unset($this->aclContents[$this->aclObject.'/'.$oc]);
252 if (isset($new_acl[$oc])){
253 $this->aclContents[$oc]= $new_acl[$oc];
254 }
255 if (isset($new_acl[$this->aclObject.'/'.$oc])){
256 $this->aclContents[$this->aclObject.'/'.$oc]= $new_acl[$this->aclObject.'/'.$oc];
257 }
258 }
259 }
261 /* Save new acl in case of base edit mode */
262 if (1 == 0 && $this->aclType == 'base' && !$firstedit){
263 $this->aclContents= $new_acl;
264 }
266 /* Cancel new acl? */
267 if (isset($_POST['cancel_new_acl'])){
268 $this->dialogState= 'head';
269 $this->dialog= FALSE;
270 if ($this->wasNewEntry){
271 unset ($this->gosaAclTemplate[$this->currentIndex]);
272 }
273 }
275 /* Store ACL in main object? */
276 if (isset($_POST['submit_new_acl'])){
277 $this->gosaAclTemplate[$this->currentIndex]['type']= $this->aclType;
278 $this->gosaAclTemplate[$this->currentIndex]['members']= $this->recipients;
279 $this->gosaAclTemplate[$this->currentIndex]['acl']= $this->aclContents;
280 $this->dialogState= 'head';
281 $this->dialog= FALSE;
282 }
284 /* Cancel edit acl? */
285 if (isset($_POST['cancel_edit_acl'])){
286 $this->dialogState= 'create';
287 foreach ($this->ocMapping[$this->aclObject] as $oc){
288 if (isset($this->savedAclContents[$oc])){
289 $this->aclContents[$oc]= $this->savedAclContents[$oc];
290 }
291 }
292 }
294 /* Save edit acl? */
295 if (isset($_POST['submit_edit_acl'])){
296 $this->dialogState= 'create';
297 }
299 /* Add acl? */
300 if (isset($_POST['add_acl']) && $_POST['aclObject'] != ""){
301 $this->dialogState= 'edit';
302 $this->savedAclContents= array();
303 foreach ($this->ocMapping[$this->aclObject] as $oc){
304 if (isset($this->aclContents[$oc])){
305 $this->savedAclContents[$oc]= $this->aclContents[$oc];
306 }
307 }
308 }
310 /* Save common values */
311 foreach (array("aclType", "aclObject", "target") as $key){
312 if (isset($_POST[$key])){
313 $this->$key= validate($_POST[$key]);
314 }
315 }
317 /* Create templating instance */
318 $smarty= get_smarty();
320 $smarty->assign("bases", $this->get_allowed_bases());
321 $smarty->assign("base_select", $this->base);
323 $tmp = $this->plInfo();
324 foreach($tmp['plProvidedAcls'] as $name => $translation){
325 $smarty->assign($name."ACL",$this->getacl($name));
326 }
328 if ($this->dialogState == 'head'){
329 /* Draw list */
330 $aclList= new DivSelectBox("aclList");
331 $aclList->SetHeight(350);
333 /* Fill in entries */
334 foreach ($this->gosaAclTemplate as $key => $entry){
335 $field1= array("string" => $this->aclTypes[$entry['type']], "attach" => "style='width:100px'");
336 $field2= array("string" => $this->assembleAclSummary($entry));
337 $action= "<input type='image' name='sortup_$key' alt='up' title='"._("Up")."' src='images/sort_up.png' align='top'>";
338 $action.= "<input type='image' name='sortdown_$key' alt='down' title='"._("Down")."' src='images/sort_down.png'>";
339 $action.= "<input class='center' type='image' src='images/edit.png' alt='"._("edit")."' name='acl_edit_$key' title='"._("Edit ACL")."'>";
340 $action.= "<input class='center' type='image' src='images/edittrash.png' alt='"._("delete")."' name='acl_del_$key' title='"._("Delete ACL")."'>";
342 $field3= array("string" => $action, "attach" => "style='border-right:0px;width:50px;text-align:right;'");
343 $aclList->AddEntry(array($field1, $field2, $field3));
344 }
346 $smarty->assign("aclList", $aclList->DrawList());
347 }
349 if ($this->dialogState == 'create'){
350 /* Draw list */
351 $aclList= new DivSelectBox("aclList");
352 $aclList->SetHeight(450);
354 /* Add settings for all categories to the (permanent) list */
355 foreach ($this->aclObjects as $section => $dsc){
356 $summary= "";
357 foreach($this->ocMapping[$section] as $oc){
358 if (isset($this->aclContents[$oc]) && count($this->aclContents[$oc]) && isset($this->aclContents[$oc][0]) &&
359 $this->aclContents[$oc][0] != ""){
361 $summary.= "$oc, ";
362 continue;
363 }
364 if (isset($this->aclContents["$section/$oc"]) && count($this->aclContents["$section/$oc"]) && isset($this->aclContents["$section/$oc"][0]) &&
365 $this->aclContents["$section/$oc"][0] != ""){
367 $summary.= "$oc, ";
368 continue;
369 }
370 if (isset($this->aclContents[$oc]) && !isset($this->aclContents[$oc][0]) && count($this->aclContents[$oc])){
371 $summary.= "$oc, ";
372 }
373 }
375 /* Set summary... */
376 if ($summary == ""){
377 $summary= '<i>'._("No ACL settings for this category").'</i>';
378 } else {
379 $summary= sprintf(_("Contains ACLs for these objects: %s"), preg_replace('/, $/', '', $summary));
380 }
382 $field1= array("string" => $dsc, "attach" => "style='width:140px'");
383 $field2= array("string" => $summary);
384 $action= "<input class='center' type='image' src='images/edit.png' alt='"._("edit")."' name='cat_edit_$section' title='"._("Edit categories ACLs")."'>";
385 $action.= "<input class='center' type='image' src='images/edittrash.png' alt='"._("delete")."' name='cat_del_$section' title='"._("Clear categories ACLs")."'>";
386 $field3= array("string" => $action, "attach" => "style='border-right:0px;width:50px'");
387 $aclList->AddEntry(array($field1, $field2, $field3));
388 }
390 $smarty->assign("aclList", $aclList->DrawList());
391 $smarty->assign("aclType", $this->aclType);
392 $smarty->assign("aclTypes", $this->aclTypes);
393 $smarty->assign("target", $this->target);
395 if ($this->aclType == 'base'){
396 $smarty->assign('aclSelector', $this->buildAclSelector($this->myAclObjects));
397 }
398 }
400 if ($this->dialogState == 'edit'){
401 $smarty->assign('headline', sprintf(_("Edit ACL for '%s', scope is '%s'"), $this->aclObjects[$this->aclObject], $this->aclTypes[$this->aclType]));
403 /* Collect objects for selected category */
404 foreach ($this->ocMapping[$this->aclObject] as $idx => $class){
405 if ($idx == 0){
406 continue;
407 }
408 $aclObjects[$this->aclObject.'/'.$class]= $plist[$class]['plDescription'];
409 }
410 if ($this->aclObject == 'all'){
411 $aclObjects['all']= _("All objects in current subtree");
412 }
413 $smarty->assign('aclSelector', $this->buildAclSelector($aclObjects));
414 }
416 /* Show main page */
417 $smarty->assign("dialogState", $this->dialogState);
419 /* Assign cn and decription if this is a role */
420 foreach(array("cn","description") as $name){
421 $smarty->assign($name,$this->$name);
422 }
423 return ($smarty->fetch (get_template_path('acl_role.tpl',dirname(__FILE__))));
424 }
426 function sort_by_priority($list)
427 {
428 $tmp= get_global('plist');
429 $plist= $tmp->info;
430 asort($plist);
431 $newSort = array();
433 foreach($list as $name => $translation){
434 $na = preg_replace("/^.*\//","",$name);
435 $prio= $plist[$na]['plPriority'] ;
437 $newSort[$name] = $prio;
438 }
440 asort($newSort);
442 $ret = array();
443 foreach($newSort as $name => $prio){
444 $ret[$name] = $list[$name];
445 }
446 return($ret);
447 }
449 function loadAclEntry($new= FALSE)
450 {
451 /* New entry gets presets... */
452 if ($new){
453 $this->aclType= 'sub';
454 $this->recipients= array();
455 $this->aclContents= array();
456 } else {
457 $acl= $this->gosaAclTemplate[$this->currentIndex];
458 $this->aclType= $acl['type'];
459 $this->recipients= $acl['members'];
460 $this->aclContents= $acl['acl'];
461 }
463 $this->wasNewEntry= $new;
464 }
467 function aclPostHandler()
468 {
469 if (isset($_POST['save_acl'])){
470 $this->save();
471 return TRUE;
472 }
474 return FALSE;
475 }
478 function save()
479 {
480 /* Assemble ACL's */
481 $tmp_acl= array();
482 foreach ($this->gosaAclTemplate as $prio => $entry){
483 $final= "";
484 $members= "";
485 if (isset($entry['members'])){
486 foreach ($entry['members'] as $key => $dummy){
487 $members.= base64_encode(preg_replace('/^.:/', '', $key)).',';
488 }
489 }
490 $final= $prio.":".$entry['type'].":".preg_replace('/,$/', '', $members);
492 /* ACL's if needed */
493 if ($entry['type'] != "reset" && $entry['type'] != "role"){
494 $acl= ":";
495 if (isset($entry['acl'])){
496 foreach ($entry['acl'] as $object => $contents){
498 /* Only save, if we've some contents in there... */
499 if (count($contents)){
500 $acl.= $object.";";
502 foreach($contents as $attr => $permission){
504 /* First entry? Its the one for global settings... */
505 if ($attr == '0'){
506 $acl.= $permission;
507 } else {
508 $acl.= '#'.$attr.';'.$permission;
509 }
511 }
512 $acl.= ',';
513 }
515 }
516 }
517 $final.= preg_replace('/,$/', '', $acl);
518 }
520 $tmp_acl[]= $final;
521 }
523 /* Call main method */
524 plugin::save();
526 /* Finally (re-)assign it... */
527 $this->attrs["gosaAclTemplate"]= $tmp_acl;
529 /* Remove acl from this entry if it is empty... */
530 if (!count($tmp_acl)){
531 /* Remove attribute */
532 if ($this->initially_was_account){
533 $this->attrs["gosaAclTempalte"]= array();
534 } else {
535 if (isset($this->attrs["gosaAclTemplate"])){
536 unset($this->attrs["gosaAclTemplate"]);
537 }
538 }
539 }
541 /* Do LDAP modifications */
542 $ldap= $this->config->get_ldap_link();
544 /* Check if object already exists */
545 $ldap->cat($this->dn);
546 if($ldap->count()){
547 $ldap->cd($this->dn);
548 $this->cleanup();
549 $ldap->modify ($this->attrs);
550 }else{
551 $ldap->cd($this->config->current['BASE']);
552 $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$this->dn));
553 $ldap->cd($this->dn);
554 $ldap->add($this->attrs);
555 }
557 show_ldap_error($ldap->get_error(), sprintf(_("Saving ACLs with dn '%s' failed."),$this->dn));
559 /* Refresh users ACLs */
560 $ui= get_userinfo();
561 $ui->loadACL();
562 $_SESSION['ui']= $ui;
563 }
566 function remove_from_parent()
567 {
568 $ldap = $this->config->get_ldap_link();
569 $serach_for = "*:role:".base64_encode($this->dn).":*";
570 $ldap->search ("(&(objectClass=gosaACL)(gosaAclEntry=".$serach_for."))",array('dn','cn','sn','givenName','uid'));
571 $all_names = "";
574 $cnt = 3;
575 while(($attrs = $ldap->fetch()) && $cnt){
576 $name = $attrs['dn'];
577 $name = preg_replace("/[ ]/"," ",$name);
578 $name = "<i>'".$name."'</i>";
579 $all_names .= $name.", ";
580 $cnt --;
581 }
583 if(!empty($all_names)){
584 $all_names = preg_replace("/, $/","",$all_names);
585 if(!$cnt){
586 $all_names .= ", ...";
587 }
588 $all_names = "<span style='text-align:left;'>".$all_names."</span>";
589 print_red(sprintf(_("This role can't be removed while it is in use. Follwing objects are using this role %s"),$all_names));
590 return;
591 }
594 $ldap->rmDir($this->dn);
595 show_ldap_error($ldap->get_error(), sprintf(_("Removing of aclRole with dn '%s' failed."),$this->dn));
597 /* Optionally execute a command after we're done */
598 $this->handle_post_events("remove");
600 /* Delete references to object groups */
601 $ldap->cd ($this->config->current['BASE']);
602 $ldap->search ("(&(objectClass=gosaGroupOfNames)(member=".$this->dn."))", array("cn"));
603 while ($ldap->fetch()){
604 $og= new ogroup($this->config, $ldap->getDN());
605 unset($og->member[$this->dn]);
606 $og->save ();
607 show_ldap_error($ldap->get_error(), sprintf(_("Removing aclRole from objectgroup '%s' failed"), $og->dn));
608 }
609 }
612 function save_object()
613 {
614 plugin::save_object();
615 if(isset($_POST['acl_role_posted'])){
617 /* Get base selection */
618 if(isset($_POST['base'])){
619 $tmp = $this->get_allowed_bases();
620 if(isset($tmp[$_POST['base']])){
621 $this->base = $_POST['base'];
622 }
623 }
624 }
625 }
627 /* Return plugin informations for acl handling */
628 function plInfo()
629 {
630 return (array(
631 "plShortName" => _("Role"),
632 "plDescription" => _("ACL roles"),
633 "plSelfModify" => FALSE,
634 "plDepends" => array(),
635 "plPriority" => 0,
636 "plSection" => array("admin"),
637 "plCategory" => array("aclroles" => array("objectClass" => "gosaRole", "description" => _("Acl roles"))),
639 "plProvidedAcls" => array(
640 "cn" => _("Name"),
641 "base" => _("Base"),
642 "description" => _("Description"))
643 ));
644 }
646 }
648 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
649 ?>