01581ab9bb67b4ed5619f3c9b15bcd99ed31b9f6
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::get('CurrentMainBase');
43 }else{
44 $this->base = preg_replace("/^[^,]+,[^,]+,/","",$this->dn);
45 new log("view","aclroles/".get_class($this),$this->dn);
46 }
48 /* Load ACL's */
49 $this->gosaAclTemplate= array();
50 if (isset($this->attrs["gosaAclTemplate"])){
51 for ($i= 0; $i<$this->attrs["gosaAclTemplate"]['count']; $i++){
52 $acl= $this->attrs["gosaAclTemplate"][$i];
53 $this->gosaAclTemplate= array_merge($this->gosaAclTemplate, $this->explodeACL($acl));
54 }
55 }
56 ksort($this->gosaAclTemplate);
58 /* Extract available categories from plugin info list */
59 $tmp= session::get('plist');
60 $plist= $tmp->info;
61 $oc = array();
62 foreach ($plist as $class => $acls){
64 /* Only feed categories */
65 if (isset($acls['plCategory'])){
67 /* Walk through supplied list and feed only translated categories */
68 foreach($acls['plCategory'] as $idx => $data){
70 /* Non numeric index means -> base object containing more informations */
71 if (preg_match('/^[0-9]+$/', $idx)){
72 if (!isset($this->ocMapping[$data])){
73 $this->ocMapping[$data]= array();
74 $this->ocMapping[$data][]= '0';
75 }
76 $this->ocMapping[$data][]= $class;
77 } else {
78 if (!isset($this->ocMapping[$idx])){
79 $this->ocMapping[$idx]= array();
80 $this->ocMapping[$idx][]= '0';
81 }
82 $this->ocMapping[$idx][]= $class;
83 $this->aclObjects[$idx]= $data['description'];
85 /* Additionally filter the classes we're interested in in "self edit" mode */
86 if (is_array($data['objectClass'])){
87 foreach($data['objectClass'] as $objectClass){
88 if (in_array_ics($objectClass, $oc)){
89 $this->myAclObjects[$idx.'/'.$class]= $acls['plDescription'];
90 break;
91 }
92 }
93 } else {
94 if (in_array_ics($data['objectClass'], $oc)){
95 $this->myAclObjects[$idx.'/'.$class]= $acls['plDescription'];
96 }
97 }
98 }
100 }
101 }
102 }
103 $this->aclObjects['all']= '* '._("All categories");
104 $this->ocMapping['all']= array('0' => 'all');
106 /* Sort categories */
107 asort($this->aclObjects);
109 /* Fill acl types */
110 $this->aclTypes= array( "reset" => _("Reset ACLs"),
111 "one" => _("One level"),
112 "base" => _("Current object"),
113 "sub" => _("Complete subtree"),
114 "psub" => _("Complete subtree (permanent)"));
115 asort($this->aclTypes);
117 /* Finally - we want to get saved... */
118 $this->is_account= TRUE;
119 }
122 function execute()
123 {
124 /* Call parent execute */
125 plugin::execute();
127 /* Base select dialog */
128 $once = true;
129 foreach($_POST as $name => $value){
130 if((preg_match("/^chooseBase/",$name) && $once) && ($this->acl_is_moveable())){
131 $once = false;
132 $this->dialog = new baseSelectDialog($this->config,$this,$this->get_allowed_bases());
133 $this->dialog->setCurrentBase($this->base);
134 }
135 }
137 /* Dialog handling */
138 if(is_object($this->dialog)){
139 /* Must be called before save_object */
140 $this->dialog->save_object();
142 if($this->dialog->isClosed()){
143 $this->dialog = false;
144 }elseif($this->dialog->isSelected()){
146 /* Check if selected base is valid */
147 $tmp = $this->get_allowed_bases();
148 if(isset($tmp[$this->dialog->isSelected()])){
149 $this->base = $this->dialog->isSelected();
150 }
151 $this->dialog= false;
152 }else{
153 return($this->dialog->execute());
154 }
155 }
157 $tmp= session::get('plist');
158 $plist= $tmp->info;
160 /* Handle posts */
161 if (isset($_POST['new_acl'])){
162 $this->dialogState= 'create';
163 $this->dialog= TRUE;
164 $this->currentIndex= count($this->gosaAclTemplate);
165 $this->loadAclEntry(TRUE);
166 }
168 $new_acl= array();
169 $aclDialog= FALSE;
170 $firstedit= FALSE;
171 foreach($_POST as $name => $post){
173 /* Actions... */
174 if (preg_match('/^acl_edit_.*_x/', $name)){
175 $this->dialogState= 'create';
176 $firstedit= TRUE;
177 $this->dialog= TRUE;
178 $this->currentIndex= preg_replace('/^acl_edit_([0-9]+).*$/', '\1', $name);
179 $this->loadAclEntry();
180 continue;
181 }
182 if (preg_match('/^acl_del_.*_x/', $name)){
183 unset($this->gosaAclTemplate[preg_replace('/^acl_del_([0-9]+).*$/', '\1', $name)]);
184 continue;
185 }
187 if (preg_match('/^cat_edit_.*_x/', $name)){
188 $this->aclObject= preg_replace('/^cat_edit_([^_]+)_.*$/', '\1', $name);
189 $this->dialogState= 'edit';
190 foreach ($this->ocMapping[$this->aclObject] as $oc){
191 if (isset($this->aclContents[$oc])){
192 $this->savedAclContents[$oc]= $this->aclContents[$oc];
193 }
194 }
195 continue;
196 }
197 if (preg_match('/^cat_del_.*_x/', $name)){
198 $idx= preg_replace('/^cat_del_([^_]+)_.*$/', '\1', $name);
199 foreach ($this->ocMapping[$idx] as $key){
200 unset($this->aclContents["$idx/$key"]);
201 }
202 continue;
203 }
205 /* Sorting... */
206 if (preg_match('/^sortup_.*_x/', $name)){
207 $index= preg_replace('/^sortup_([0-9]+).*$/', '\1', $name);
208 if ($index > 0){
209 $tmp= $this->gosaAclTemplate[$index];
210 $this->gosaAclTemplate[$index]= $this->gosaAclTemplate[$index-1];
211 $this->gosaAclTemplate[$index-1]= $tmp;
212 }
213 continue;
214 }
215 if (preg_match('/^sortdown_.*_x/', $name)){
216 $index= preg_replace('/^sortdown_([0-9]+).*$/', '\1', $name);
217 if ($index < count($this->gosaAclTemplate)-1){
218 $tmp= $this->gosaAclTemplate[$index];
219 $this->gosaAclTemplate[$index]= $this->gosaAclTemplate[$index+1];
220 $this->gosaAclTemplate[$index+1]= $tmp;
221 }
222 continue;
223 }
225 /* ACL saving... */
226 if (preg_match('/^acl_.*_[^xy]$/', $name)){
227 $aclDialog= TRUE;
228 list($dummy, $object, $attribute, $value)= split('_', $name);
230 /* Skip for detection entry */
231 if ($object == 'dummy') {
232 continue;
233 }
235 /* Ordinary ACLs */
236 if (!isset($new_acl[$object])){
237 $new_acl[$object]= array();
238 }
239 if (isset($new_acl[$object][$attribute])){
240 $new_acl[$object][$attribute].= $value;
241 } else {
242 $new_acl[$object][$attribute]= $value;
243 }
244 }
245 }
247 /* Only be interested in new acl's, if we're in the right _POST place */
248 if ($aclDialog && $this->aclObject != "" && is_array($this->ocMapping[$this->aclObject])){
250 foreach ($this->ocMapping[$this->aclObject] as $oc){
251 unset($this->aclContents[$oc]);
252 unset($this->aclContents[$this->aclObject.'/'.$oc]);
253 if (isset($new_acl[$oc])){
254 $this->aclContents[$oc]= $new_acl[$oc];
255 }
256 if (isset($new_acl[$this->aclObject.'/'.$oc])){
257 $this->aclContents[$this->aclObject.'/'.$oc]= $new_acl[$this->aclObject.'/'.$oc];
258 }
259 }
260 }
262 /* Save new acl in case of base edit mode */
263 if (1 == 0 && $this->aclType == 'base' && !$firstedit){
264 $this->aclContents= $new_acl;
265 }
267 /* Cancel new acl? */
268 if (isset($_POST['cancel_new_acl'])){
269 $this->dialogState= 'head';
270 $this->dialog= FALSE;
271 if ($this->wasNewEntry){
272 unset ($this->gosaAclTemplate[$this->currentIndex]);
273 }
274 }
276 /* Store ACL in main object? */
277 if (isset($_POST['submit_new_acl'])){
278 $this->gosaAclTemplate[$this->currentIndex]['type']= $this->aclType;
279 $this->gosaAclTemplate[$this->currentIndex]['members']= $this->recipients;
280 $this->gosaAclTemplate[$this->currentIndex]['acl']= $this->aclContents;
281 $this->dialogState= 'head';
282 $this->dialog= FALSE;
283 }
285 /* Cancel edit acl? */
286 if (isset($_POST['cancel_edit_acl'])){
287 $this->dialogState= 'create';
288 foreach ($this->ocMapping[$this->aclObject] as $oc){
289 if (isset($this->savedAclContents[$oc])){
290 $this->aclContents[$oc]= $this->savedAclContents[$oc];
291 }
292 }
293 }
295 /* Save edit acl? */
296 if (isset($_POST['submit_edit_acl'])){
297 $this->dialogState= 'create';
298 }
300 /* Add acl? */
301 if (isset($_POST['add_acl']) && $_POST['aclObject'] != ""){
302 $this->dialogState= 'edit';
303 $this->savedAclContents= array();
304 foreach ($this->ocMapping[$this->aclObject] as $oc){
305 if (isset($this->aclContents[$oc])){
306 $this->savedAclContents[$oc]= $this->aclContents[$oc];
307 }
308 }
309 }
311 /* Save common values */
312 foreach (array("aclType", "aclObject", "target") as $key){
313 if (isset($_POST[$key])){
314 $this->$key= validate($_POST[$key]);
315 }
316 }
318 /* Create templating instance */
319 $smarty= get_smarty();
321 $smarty->assign("bases", $this->get_allowed_bases());
322 $smarty->assign("base_select", $this->base);
324 $tmp = $this->plInfo();
325 foreach($tmp['plProvidedAcls'] as $name => $translation){
326 $smarty->assign($name."ACL",$this->getacl($name));
327 }
329 if ($this->dialogState == 'head'){
330 /* Draw list */
331 $aclList= new divSelectBox("aclList");
332 $aclList->SetHeight(350);
334 /* Fill in entries */
335 foreach ($this->gosaAclTemplate as $key => $entry){
336 $field1= array("string" => $this->aclTypes[$entry['type']], "attach" => "style='width:100px'");
337 $field2= array("string" => $this->assembleAclSummary($entry));
338 $action= "<input type='image' name='sortup_$key' alt='up' title='"._("Up")."' src='images/sort_up.png' align='top'>";
339 $action.= "<input type='image' name='sortdown_$key' alt='down' title='"._("Down")."' src='images/sort_down.png'>";
340 $action.= "<input class='center' type='image' src='images/edit.png' alt='"._("edit")."' name='acl_edit_$key' title='"._("Edit ACL")."'>";
341 $action.= "<input class='center' type='image' src='images/edittrash.png' alt='"._("delete")."' name='acl_del_$key' title='"._("Delete ACL")."'>";
343 $field3= array("string" => $action, "attach" => "style='border-right:0px;width:50px;text-align:right;'");
344 $aclList->AddEntry(array($field1, $field2, $field3));
345 }
347 $smarty->assign("aclList", $aclList->DrawList());
348 }
350 if ($this->dialogState == 'create'){
351 /* Draw list */
352 $aclList= new divSelectBox("aclList");
353 $aclList->SetHeight(450);
355 /* Add settings for all categories to the (permanent) list */
356 foreach ($this->aclObjects as $section => $dsc){
357 $summary= "";
358 foreach($this->ocMapping[$section] as $oc){
359 if (isset($this->aclContents[$oc]) && count($this->aclContents[$oc]) && isset($this->aclContents[$oc][0]) &&
360 $this->aclContents[$oc][0] != ""){
362 $summary.= "$oc, ";
363 continue;
364 }
365 if (isset($this->aclContents["$section/$oc"]) && count($this->aclContents["$section/$oc"]) && isset($this->aclContents["$section/$oc"][0]) &&
366 $this->aclContents["$section/$oc"][0] != ""){
368 $summary.= "$oc, ";
369 continue;
370 }
371 if (isset($this->aclContents[$oc]) && !isset($this->aclContents[$oc][0]) && count($this->aclContents[$oc])){
372 $summary.= "$oc, ";
373 }
374 }
376 /* Set summary... */
377 if ($summary == ""){
378 $summary= '<i>'._("No ACL settings for this category").'</i>';
379 } else {
380 $summary= sprintf(_("Contains ACLs for these objects: %s"), preg_replace('/, $/', '', $summary));
381 }
383 $field1= array("string" => $dsc, "attach" => "style='width:140px'");
384 $field2= array("string" => $summary);
385 $action= "<input class='center' type='image' src='images/edit.png' alt='"._("edit")."' name='cat_edit_$section' title='"._("Edit categories ACLs")."'>";
386 $action.= "<input class='center' type='image' src='images/edittrash.png' alt='"._("delete")."' name='cat_del_$section' title='"._("Clear categories ACLs")."'>";
387 $field3= array("string" => $action, "attach" => "style='border-right:0px;width:50px'");
388 $aclList->AddEntry(array($field1, $field2, $field3));
389 }
391 $smarty->assign("aclList", $aclList->DrawList());
392 $smarty->assign("aclType", $this->aclType);
393 $smarty->assign("aclTypes", $this->aclTypes);
394 $smarty->assign("target", $this->target);
396 if ($this->aclType == 'base'){
397 $smarty->assign('aclSelector', $this->buildAclSelector($this->myAclObjects));
398 }
399 }
401 if ($this->dialogState == 'edit'){
402 $smarty->assign('headline', sprintf(_("Edit ACL for '%s', scope is '%s'"), $this->aclObjects[$this->aclObject], $this->aclTypes[$this->aclType]));
404 /* Collect objects for selected category */
405 foreach ($this->ocMapping[$this->aclObject] as $idx => $class){
406 if ($idx == 0){
407 continue;
408 }
409 $aclObjects[$this->aclObject.'/'.$class]= $plist[$class]['plDescription'];
410 }
411 if ($this->aclObject == 'all'){
412 $aclObjects['all']= _("All objects in current subtree");
413 }
414 $smarty->assign('aclSelector', $this->buildAclSelector($aclObjects));
415 }
417 /* Show main page */
418 $smarty->assign("dialogState", $this->dialogState);
420 /* Assign cn and decription if this is a role */
421 foreach(array("cn","description") as $name){
422 $smarty->assign($name,$this->$name);
423 }
424 return ($smarty->fetch (get_template_path('acl_role.tpl',dirname(__FILE__))));
425 }
427 function sort_by_priority($list)
428 {
429 $tmp= session::get('plist');
430 $plist= $tmp->info;
431 asort($plist);
432 $newSort = array();
434 foreach($list as $name => $translation){
435 $na = preg_replace("/^.*\//","",$name);
436 if (!isset($plist[$na]['plPriority'])){
437 $prio= 0;
438 } else {
439 $prio= $plist[$na]['plPriority'] ;
440 }
442 $newSort[$name] = $prio;
443 }
445 asort($newSort);
447 $ret = array();
448 foreach($newSort as $name => $prio){
449 $ret[$name] = $list[$name];
450 }
451 return($ret);
452 }
454 function loadAclEntry($new= FALSE)
455 {
456 /* New entry gets presets... */
457 if ($new){
458 $this->aclType= 'sub';
459 $this->recipients= array();
460 $this->aclContents= array();
461 } else {
462 $acl= $this->gosaAclTemplate[$this->currentIndex];
463 $this->aclType= $acl['type'];
464 $this->recipients= $acl['members'];
465 $this->aclContents= $acl['acl'];
466 }
468 $this->wasNewEntry= $new;
469 }
472 function aclPostHandler()
473 {
474 if (isset($_POST['save_acl'])){
475 $this->save();
476 return TRUE;
477 }
479 return FALSE;
480 }
483 function save()
484 {
485 /* Assemble ACL's */
486 $tmp_acl= array();
487 foreach ($this->gosaAclTemplate as $prio => $entry){
488 $final= "";
489 $members= "";
490 if (isset($entry['members'])){
491 foreach ($entry['members'] as $key => $dummy){
492 $members.= base64_encode(preg_replace('/^.:/', '', $key)).',';
493 }
494 }
495 $final= $prio.":".$entry['type'].":".preg_replace('/,$/', '', $members);
497 /* ACL's if needed */
498 if ($entry['type'] != "reset" && $entry['type'] != "role"){
499 $acl= ":";
500 if (isset($entry['acl'])){
501 foreach ($entry['acl'] as $object => $contents){
503 /* Only save, if we've some contents in there... */
504 if (count($contents)){
505 $acl.= $object.";";
507 foreach($contents as $attr => $permission){
509 /* First entry? Its the one for global settings... */
510 if ($attr == '0'){
511 $acl.= $permission;
512 } else {
513 $acl.= '#'.$attr.';'.$permission;
514 }
516 }
517 $acl.= ',';
518 }
520 }
521 }
522 $final.= preg_replace('/,$/', '', $acl);
523 }
525 $tmp_acl[]= $final;
526 }
528 /* Call main method */
529 plugin::save();
531 /* Finally (re-)assign it... */
532 $this->attrs["gosaAclTemplate"]= $tmp_acl;
534 /* Remove acl from this entry if it is empty... */
535 if (!count($tmp_acl)){
536 /* Remove attribute */
537 if ($this->initially_was_account){
538 $this->attrs["gosaAclTempalte"]= array();
539 } else {
540 if (isset($this->attrs["gosaAclTemplate"])){
541 unset($this->attrs["gosaAclTemplate"]);
542 }
543 }
544 }
546 /* Do LDAP modifications */
547 $ldap= $this->config->get_ldap_link();
549 /* Check if object already exists */
550 $ldap->cat($this->dn);
551 if($ldap->count()){
552 $ldap->cd($this->dn);
553 $this->cleanup();
554 $ldap->modify ($this->attrs);
555 new log("modify","aclroles/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
556 }else{
557 $ldap->cd($this->config->current['BASE']);
558 $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$this->dn));
559 $ldap->cd($this->dn);
560 $ldap->add($this->attrs);
561 new log("create","aclroles/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
562 }
564 show_ldap_error($ldap->get_error(), sprintf(_("Saving ACLs with dn '%s' failed."),$this->dn));
566 /* Refresh users ACLs */
567 $ui= get_userinfo();
568 $ui->loadACL();
569 session::set('ui',$ui);
570 }
573 function remove_from_parent()
574 {
575 $ldap = $this->config->get_ldap_link();
576 $serach_for = "*:role:".base64_encode($this->dn).":*";
577 $ldap->search ("(&(objectClass=gosaACL)(gosaAclEntry=".$serach_for."))",array('dn','cn','sn','givenName','uid'));
578 $all_names = "";
581 $cnt = 3;
582 while(($attrs = $ldap->fetch()) && $cnt){
583 $name = $attrs['dn'];
584 $name = preg_replace("/[ ]/"," ",$name);
585 $name = "<i>'".$name."'</i>";
586 $all_names .= $name.", ";
587 $cnt --;
588 }
590 if(!empty($all_names)){
591 $all_names = preg_replace("/, $/","",$all_names);
592 if(!$cnt){
593 $all_names .= ", ...";
594 }
595 $all_names = "<span style='text-align:left;'>".$all_names."</span>";
596 print_red(sprintf(_("This role can't be removed while it is in use. Follwing objects are using this role %s"),$all_names));
597 return;
598 }
600 $ldap->rmDir($this->dn);
601 new log("remove","aclroles/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
602 show_ldap_error($ldap->get_error(), sprintf(_("Removing of aclRole with dn '%s' failed."),$this->dn));
604 /* Optionally execute a command after we're done */
605 $this->handle_post_events("remove");
607 /* Delete references to object groups */
608 $ldap->cd ($this->config->current['BASE']);
609 $ldap->search ("(&(objectClass=gosaGroupOfNames)(member=".LDAP::prepare4filter($this->dn)."))", array("cn"));
610 while ($ldap->fetch()){
611 $og= new ogroup($this->config, $ldap->getDN());
612 unset($og->member[$this->dn]);
613 $og->save ();
614 show_ldap_error($ldap->get_error(), sprintf(_("Removing aclRole from objectgroup '%s' failed"), $og->dn));
615 }
616 }
619 function save_object()
620 {
621 plugin::save_object();
622 if(isset($_POST['acl_role_posted'])){
624 /* Get base selection */
625 if(isset($_POST['base'])){
626 $tmp = $this->get_allowed_bases();
627 if(isset($tmp[$_POST['base']])){
628 $this->base = $_POST['base'];
629 }
630 }
631 }
632 }
635 function saveCopyDialog()
636 {
637 if(isset($_POST['cn'])){
638 $this->cn = $_POST['cn'];
639 }
640 }
643 function getCopyDialog()
644 {
645 $smarty = get_smarty();
646 $smarty->assign("cn",$this->cn);
647 $str = $smarty->fetch(get_template_path("paste_role.tpl",TRUE,dirname(__FILE__)));
648 $ret = array();
649 $ret['string'] = $str;
650 $ret['status'] = "";
651 return($ret);
652 }
655 function PrepareForCopyPaste($source)
656 {
657 plugin::PrepareForCopyPaste($source);
659 $source_o = new aclrole($this->config,$source['dn']);
660 $this->gosaAclTemplate = $source_o->gosaAclTemplate;
661 }
664 /* Return plugin informations for acl handling */
665 static function plInfo()
666 {
667 return (array(
668 "plShortName" => _("Role"),
669 "plDescription" => _("ACL roles"),
670 "plSelfModify" => FALSE,
671 "plDepends" => array(),
672 "plPriority" => 0,
673 "plSection" => array("admin"),
674 "plCategory" => array("aclroles" => array("objectClass" => "gosaRole", "description" => _("Acl roles"))),
676 "plProvidedAcls" => array(
677 "cn" => _("Name"),
678 "base" => _("Base"),
679 "description" => _("Description"))
680 ));
681 }
683 }
685 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
686 ?>