Code

f025a200c4b8137dfeea5035a87004707498d8c5
[gosa.git] / gosa-core / include / class_listing.inc
1 <?php
3 class listing {
5   var $xmlData;
6   var $entries;
7   var $departments= array();
8   var $departmentBrowser= false;
9   var $departmentRootVisible= false;
10   var $multiSelect= false;
11   var $template;
12   var $headline;
13   var $module;
14   var $base;
15   var $baseMode= false;
16   var $bases= array();
17   var $header= array();
18   var $colprops= array();
19   var $filters= array();
20   var $pid;
21   var $objectTypes;
22   var $objectTypeCount= array();
25   function listing($filename)
26   {
27     global $config;
29     if (!$this->load($filename)) {
30       die("Cannot parse $filename!");
31     }
33     // Set base for filter
34     $this->base= session::global_get("CurrentMainBase");
35     if ($this->base == null) {
36       $this->base= $config->current['BASE'];
37     }
38     $this->refreshBasesList();
40     // Move footer information
41     $this->showFooter= ($config->get_cfg_value("listSummary") == "true");
43     // Register build in filters
44     $this->registerElementFilter("objectType", "listing::filterObjectType");
45     $this->registerElementFilter("link", "listing::filterLink");
46     $this->registerElementFilter("actions", "listing::filterActions");
48     // Initialize pid
49     $this->pid= preg_replace("/[^0-9]/", "", microtime(TRUE));
50   }
53   function registerElementFilter($name, $call)
54   {
55     if (!isset($this->filters[$name])) {
56       $this->filters[$name]= $call;
57       return true;
58     }
60     return false;
61   }
64   function load($filename)
65   {
66     $contents = file_get_contents($filename);
67     $this->xmlData= xml::xml2array($contents, 1);
69     if (!isset($this->xmlData['list'])) {
70       return false;
71     }
73     $this->xmlData= $this->xmlData["list"];
75     // Load some definition values
76     foreach (array("departmentBrowser", "departmentRootVisible", "multiSelect", "baseMode") as $token) {
77       if (isset($this->xmlData['definition'][$token]) &&
78           $this->xmlData['definition'][$token] == "true"){
79         $this->$token= true;
80       }
81     }
83     // Fill objectTypes
84     if (isset($this->xmlData['definition']['objectType'])) {
85       foreach ($this->xmlData['definition']['objectType'] as $index => $otype) {
86         $this->objectTypes[]= $this->xmlData['definition']['objectType'][$index];
87       }
88     }
90     // Parse layout per column
91     $this->colprops= $this->parseLayout($this->xmlData['table']['layout']);
93     // Prepare table headers
94     $this->header= array();
95     if (isset($this->xmlData['table']['column'])){
96       foreach ($this->xmlData['table']['column'] as $index => $config) {
97         if (isset($config['label'])) {
98           $this->header[$index]= "<td class='listheader' ".$this->colprops[$index].">"._($config['label'])."</td>";
99         } else {
100           $this->header[$index]= "<td class='listheader' ".$this->colprops[$index].">&nbsp;</td>";
101         }
102       }
103     }
105     // Assign headline/module
106     $this->headline= _($this->xmlData['definition']['label']);
107     $this->module= $this->xmlData['definition']['module'];
109     return true;  
110   }
113   function render()
114   {
115 echo "sorting, department browsing, copypaste handler, snapshot handler, daemon handler<br>";
117     // Initialize list
118     $result= "<input type='hidden' value='$this->pid' name='PID'>";
119     $result.= "<div class='contentboxb' id='listing_container' style='border-top:1px solid #B0B0B0;'>";
120     $result.= "<table summary='$this->headline' style='width:600px;height:450px;' cellspacing='0' id='t_scrolltable'>
121 <tr><td class='scrollhead'><table summary='' style='width:100%;' cellspacing='0' id='t_scrollhead'>";
122     $num_cols= count($this->colprops) + ($this->multiSelect?1:0);
124     // Build list header
125     $result.= "<tr>";
126     if ($this->multiSelect) {
127       $result.= "<td class='listheader' style='width:20px;'><input type='checkbox' id='select_all' name='select_all' title='"._("Select all")."' onClick='toggle_all_(\"listing_selected_[0-9]*$\",\"select_all\");' ></td>";
128     }
129     foreach ($this->header as $header) {
130       $result.= $header;
131     }
133     // Add 13px for scroller
134     $result.= "<td class='listheader' style='width:13px;border-right:0px;'>&nbsp;</td></table></td></tr>";
136     // New table for the real list contents
137     $result.= "<tr><td colspan='$num_cols' class='scrollbody'><div style='width:600px;height:430px;' id='d_scrollbody' class='scrollbody'><table summary='' style='height:100%;width:581px;' cellspacing='0' id='t_scrollbody'>";
139     // No results? Just take an empty colspanned row
140     if (count($this->entries) + count($this->departments) == 0) {
141       $result.= "<tr class='rowxp0'><td class='list1nohighlight' colspan='$num_cols' style='height:100%;border-right:0px;width:100%;'>&nbsp;</td></tr>";
142     }
144     // Fill with department browser if configured this way
145 ###############
147     // Fill with contents
148     foreach ($this->entries as $row => $entry){
149       $result.="<tr class='rowxp".($row&1)."'>";
151       // Render multi select if needed
152       if ($this->multiSelect) {
153         $result.="<td style='text-align:center;width:20px;' class='list0'><input type='checkbox' id='listing_selected_$row' name='listing_selected_$row'></td>";
154       }
156       foreach ($this->xmlData['table']['column'] as $index => $config) {
157         $result.="<td ".$this->colprops[$index]." class='list0'>".$this->renderCell($config['value'], $entry, $row)."</td>";
158       }
159       $result.="</tr>";
160     }
162     // Need to fill the list if it's not full (nobody knows why this is 22 ;-))
163     $emptyListStyle= (count($this->entries) == 0)?"border:0;":"";
164     if (count($this->entries) < 22) {
165       $result.= "<tr>";
166       for ($i= 0; $i<$num_cols; $i++) {
167         if ($i == 0) {
168           $result.= "<td class='list1nohighlight' style='$emptyListStyle height:100%;'>&nbsp;</td>";
169           continue;
170         }
171         if ($i != $num_cols-1) {
172           $result.= "<td class='list1nohighlight' style='$emptyListStyle'>&nbsp;</td>";
173         } else {
174           $result.= "<td class='list1nohighlight' style='border-right:1px solid #AAA;$emptyListStyle'>&nbsp;</td>";
175         }
176       }
177       $result.= "</tr>";
178     }
180     $result.= "</table></div></td></tr>";
182     // Add the footer if requested
183     if ($this->showFooter) {
184       $result.= "<tr><td class='scrollhead'><table summary='' style='width:100%' cellspacing='0' id='t_scrollfoot'><tr><td class='listfooter' style='border-bottom:0px;'>";
186       foreach ($this->objectTypes as $objectType) {
187         if (isset($this->objectTypeCount[$objectType['label']])) {
188           $label= _($objectType['label']);
189           $result.= "<img class='center' src='".$objectType['image']."' title='$label' alt='$label'>&nbsp;".$this->objectTypeCount[$objectType['label']]."&nbsp;&nbsp;&nbsp;&nbsp;";
190         }
191       }
193       $result.= "<td class='listfooter' style='width:13px;border-right:0px;'>&nbsp;</td></table></td></tr>";
194     }
196     $result.= "</table></div>";
198     $smarty= get_smarty();
199     $smarty->assign("FILTER", $this->filter->render());
200     $smarty->assign("LIST", $result);
202     // Assign navigation elements
203     $nav= $this->renderNavigation();
204     foreach ($nav as $key => $html) {
205       $smarty->assign($key, $html);
206     }
208     // Assign action menu / base
209     $smarty->assign("ACTIONS", $this->renderActionMenu());
210     $smarty->assign("BASE", $this->renderBase());
212     // Assign separator
213     $smarty->assign("SEPARATOR", "<img src='images/lists/seperator.png' alt='-' align='middle' height='16' width='1' class='center'>");
215     // Assign summary
216     $smarty->assign("HEADLINE", $this->headline);
218     return ($smarty->fetch(get_template_path($this->xmlData['definition']['template'], true)));
219   }
222   function setFilter($filter)
223   {
224     $this->filter= &$filter;
225     if ($this->departmentBrowser){
226       # $this->departments= $this->filter->getDepartments();
227     }
228     $this->filter->setBase($this->base);
229     $this->entries= $this->filter->query();
230   }
233   function update()
234   {
235     global $config;
236     $ui= get_userinfo();
238     // Do not do anything if this is not our PID
239     # DISABLED because the object is not in the session
240     #if(isset($_REQUEST['PID']) && $_REQUEST['PID'] != $this->pid) {
241     #  return;
242     #}
244     if ($this->departmentBrowser){
245       # $this->departments= $this->filter->getDepartments();
246     }
248     // Save base
249     if (isset($_POST['BASE']) && $this->baseMode == true) {
250       $base= validate($_POST['BASE']);
251       if (isset($this->bases[$base])) {
252         $this->base= $base;
253       }
254     }
256     // Override base if we got signals from the navigation elements
257     $action= "";
258     foreach ($_POST as $key => $value) {
259       if (preg_match('/^(ROOT|BACK|HOME)_x$/', $key, $match)) {
260         $action= $match[1];
261         break;
262       }
263     }
265     // Navigation handling
266     if ($action == 'ROOT') {
267       $deps= $ui->get_module_departments($this->module);
268       $this->base= $deps[0];
269     }
270     if ($action == 'BACK') {
271       $deps= $ui->get_module_departments($this->module);
272       $base= preg_replace("/^[^,]+,/", "", $this->base);
273       if(in_array_ics($base, $deps)){
274         $this->base= $base;
275       }
276     }
277     if ($action == 'HOME') {
278       $ui= get_userinfo();
279       $this->base= get_base_from_people($ui->dn);
280     }
282     // Update filter and refresh entries
283     $this->filter->setBase($this->base);
284     $this->entries= $this->filter->query();
285   }
288   function parseLayout($layout)
289   {
290     $result= array();
291     $layout= preg_replace("/^\|/", "", $layout);
292     $layout= preg_replace("/\|$/", "", $layout);
293     $cols= split("\|", $layout);
294     foreach ($cols as $index => $config) {
295       if ($config != "") {
296         $components= split(';', $config);
297         $config= "";
298         foreach ($components as $part) {
299           if (preg_match("/^r$/", $part)) {
300             $config.= "text-align:right;";
301             continue;
302           }
303           if (preg_match("/^l$/", $part)) {
304             $config.= "text-align:left;";
305             continue;
306           }
307           if (preg_match("/^c$/", $part)) {
308             $config.= "text-align:center;";
309             continue;
310           }
311           if (preg_match("/^[0-9]+(|px|%)$/", $part)) {
312             $config.= "width:$part;";
313             continue;
314           }
315         }
317         $result[$index]= " style='$config' ";
318       } else {
319         $result[$index]= null;
320       }
321     }
323     return $result;
324   }
327   function renderCell($data, $config, $row)
328   {
329     // Replace flat attributes in data string
330     for ($i= 0; $i<$config['count']; $i++) {
331       $attr= $config[$i];
332       $value= "";
333       if (is_array($config[$attr])) {
334         $value= $config[$attr][0];
335       } else {
336         $value= $config[$attr];
337       }
338       $data= preg_replace("/%\{$attr\}/", $value, $data);
339     }
341     // Watch out for filters and prepare to execute them
342     $data= $this->processElementFilter($data, $config, $row);
344     return $data;
345   }
348   function renderBase()
349   {
350     $result= "<select name='BASE' onChange='mainform.submit()' size='1'>";
351     $firstDN= null;
352     $found= false;
354     foreach ($this->bases as $key=>$value) {
355       // Keep first entry to fall back eventually
356       if(!$firstDN) {
357         $firstDN= $key;
358       }
360       // Prepare to render entry
361       $selected= "";
362       if ($key == $this->base) {
363         $selected= " selected";
364         $found= true;
365       }
366       $result.= "<option value='".$key."'$selected>".$value."</option>";
367     }
368     $result.= "</select>";
370     // Reset the currently used base to the first DN we found if there
371     // was no match.
372     if(!$found){
373       $this->base = $firstDN;
374     }
376     return $result;
377   }
380   function processElementFilter($data, $config, $row)
381   {
382     preg_match_all("/%\{filter:([^(]+)\((.*)\)\}/", $data, $matches, PREG_SET_ORDER);
384     foreach ($matches as $match) {
385       if (!isset($this->filters[$match[1]])) {
386         continue;
387       }
388       $cl= preg_replace('/::.*$/', '', $this->filters[$match[1]]);
389       $method= preg_replace('/^.*::/', '', $this->filters[$match[1]]);
391       // Prepare params for function call
392       $params= array();
393       preg_match_all('/"[^"]+"|[^,]+/', $match[2], $parts);
394       foreach ($parts[0] as $param) {
396         // Row is replaced by the row number
397         if ($param == "row") {
398           $params[]= $row;
399         }
401         // pid is replaced by the current PID
402         if ($param == "pid") {
403           $params[]= $this->pid;
404         }
406         // Fixie with "" is passed directly
407         if (preg_match('/^".*"$/', $param)){
408           $params[]= preg_replace('/"/', '', $param);
409         }
411         // LDAP variables get replaced by their objects
412         for ($i= 0; $i<$config['count']; $i++) {
413           if ($param == $config[$i]) {
414             $values= $config[$config[$i]];
415             if (is_array($values)){
416               unset($values['count']);
417             }
418             $params[]= $values;
419           }
420         }
422         // Move dn if needed
423         if ($param == "dn") {
424           $params[]= LDAP::fix($config["dn"]);
425         }
426       }
428       // Replace information
429       if ($cl == "listing") {
430         // Non static call - seems to result in errors
431         $data= @preg_replace('/'.preg_quote($match[0]).'/', call_user_func_array(array($this, "$method"), $params), $data);
432       } else {
433         // Static call
434         $data= preg_replace('/'.preg_quote($match[0]).'/', call_user_func_array(array($cl, $method), $params), $data);
435       }
436     }
438     return $data;
439   }
442   function getObjectType($types, $classes)
443   {
444     // Walk thru types and see if there's something matching
445     foreach ($types as $objectType) {
446       $ocs= $objectType['objectClass'];
447       if (!is_array($ocs)){
448         $ocs= array($ocs);
449       }
451       $found= true;
452       foreach ($ocs as $oc){
453         if (preg_match('/^!(.*)$/', $oc, $match)) {
454           $oc= $match[1];
455           if (in_array($oc, $classes)) {
456             $found= false;
457           }
458         } else {
459           if (!in_array($oc, $classes)) {
460             $found= false;
461           }
462         }
463       }
465       if ($found) {
466         return $objectType;
467       }
468     }
470     return null;
471   }
474   function filterObjectType($dn, $classes)
475   {
476     // Walk thru classes and return on first match
477     $result= "&nbsp;";
479     $objectType= $this->getObjectType($this->objectTypes, $classes);
480     if ($objectType) {
481       $result= "<img class='center' title='".LDAP::fix($dn)."' src='".$objectType["image"]."'>";
482       if (!isset($this->objectTypeCount[$objectType['label']])) {
483         $this->objectTypeCount[$objectType['label']]= 0;
484       }
485       $this->objectTypeCount[$objectType['label']]++;
486     }
487     return $result;
488   }
491   function filterActions($dn, $row, $classes)
492   {
493     // Do nothing if there's no menu defined
494     if (!isset($this->xmlData['actiontriggers']['action'])) {
495       return "&nbsp;";
496     }
498     // Go thru all actions
499     $result= "";
500     $actions= $this->xmlData['actiontriggers']['action'];
501     foreach($actions as $action) {
502       // Skip the entry completely if there's no permission to execute it
503       if (!$this->hasActionPermission($action, $dn)) {
504         continue;
505       }
507       // If there's an objectclass definition and we don't have it
508       // add an empty picture here.
509       if (isset($action['objectclass'])){
510         $objectclass= $action['objectclass'];
511         if (preg_match('/^!(.*)$/', $objectclass, $m)){
512           $objectclass= $m[1];
513           if(in_array($objectclass, $classes)) {
514             $result.= "<img src='images/empty.png' alt=' ' class='center' style='padding:1px'>";
515             continue;
516           }
517         } else {
518           if(!in_array($objectclass, $classes)) {
519             $result.= "<img src='images/empty.png' alt=' ' class='center' style='padding:1px'>";
520             continue;
521           }
522         }
523       }
525       // Render normal entries as usual
526       if ($action['type'] == "entry") {
527         $label= $this->processElementFilter($action['label'], $this->entries[$row], $row);
528         $image= $this->processElementFilter($action['image'], $this->entries[$row], $row);
529         $result.="<input class='center' type='image' src='$image' title='$label' ".
530                  "name='listing_".$action['name']."_$row' style='padding:1px'>";
531       }
533       // Handle special types
534       if ($action['type'] == "snapshot") {
535         #TODO
536         #echo "actiontriggers: snapshot missing<br>";
537       }
538       if ($action['type'] == "copypaste") {
539         #TODO
540         #echo "actiontriggers: copypaste missing<br>";
541       }
542       if ($action['type'] == "daemon") {
543         #TODO
544         #echo "actiontriggers: daemon missing<br>";
545       }
547     }
549     return $result;
550   }
553   function filterLink()
554   {
555     $result= "&nbsp;";
557     $row= func_get_arg(0);
558     $pid= func_get_arg(1);
559     $dn= LDAP::fix(func_get_arg(2));
560     $params= array(func_get_arg(3));
562     // Collect sprintf params
563     for ($i = 4;$i < func_num_args();$i++) {
564       $val= func_get_arg($i);
565       if (is_array($val)){
566         $params[]= $val[0];
567         continue;
568       }
569       $params[]= $val;
570     }
572     $result= "&nbsp;";
573     $trans= call_user_func_array("sprintf", $params);
574     if ($trans != "") {
575       return("<a href='?plug=".$_GET['plug']."&amp;PID=$pid&amp;act=listing_edit_$row' title='$dn'>$trans</a>");
576     }
578     return $result;
579   }
582   function renderNavigation()
583   {
584     $result= array();
585     $enableBack = true;
586     $enableRoot = true;
587     $enableHome = true;
589     $ui = get_userinfo();
591     /* Check if base = first available base */
592     $deps = $ui->get_module_departments($this->module);
594     if(!count($deps) || $deps[0] == $this->filter->base){
595       $enableBack = false;
596       $enableRoot = false;
597     }
599     $listhead ="";
601     /* Check if we are in users home  department */
602     if(!count($deps) ||$this->filter->base == get_base_from_people($ui->dn)){
603       $enableHome = false;
604     }
606     /* Draw root button */
607     if($enableRoot){
608       $result["ROOT"]= "<input class='center' type='image' src='images/lists/root.png' align='middle' ".
609                        "title='"._("Go to root department")."' name='ROOT' alt='"._("Root")."'>";
610     }else{
611       $result["ROOT"]= "<img src='images/lists/root_grey.png' class='center' alt='"._("Root")."'>";
612     }
614     /* Draw back button */
615     if($enableBack){
616       $result["BACK"]= "<input class='center' type='image' align='middle' src='images/lists/back.png' ".
617                        "title='"._("Go up one department")."' alt='"._("Up")."' name='BACK'>";
618     }else{
619       $result["BACK"]= "<img src='images/lists/back_grey.png' class='center' alt='"._("Up")."'>";
620     }
622     /* Draw home button */
623     if($enableHome){
624       $result["HOME"]= "<input class='center' type='image' align='middle' src='images/lists/home.png' ".
625                        "title='"._("Go to users department")."' alt='"._("Home")."' name='HOME'>";
626     }else{
627       $result["HOME"]= "<img src='images/lists/home_grey.png' class='center' alt='"._("Home")."'>";
628     }
630     /* Draw reload button, this button is enabled everytime */
631     $result["RELOAD"]= "<input class='center' type='image' src='images/lists/reload.png' align='middle' ".
632                        "title='"._("Reload list")."' name='REFRESH' alt='"._("Submit")."'>";
634     return ($result);
635   }
638   function getAction()
639   {
640     // Do not do anything if this is not our PID
641     # DISABLED because the object is not in the session
642     #if(isset($_REQUEST['PID']) && $_REQUEST['PID'] != $this->pid) {
643     #  return;
644     #}
646     $result= array("targets" => array(), "action" => "");
648     // Filter GET with "act" attributes
649     if (isset($_GET['act'])) {
650       $key= validate($_GET['act']);
651       $target= preg_replace('/^listing_[a-zA-Z_]+_([0-9]+)$/', '$1', $key);
652       if (isset($this->entries[$target]['dn'])) {
653         $result['action']= preg_replace('/^listing_([a-zA-Z_]+)_[0-9]+$/', '$1', $key);
654         $result['targets'][]= $this->entries[$target]['dn'];
655       }
657       // Drop targets if empty
658       if (count($result['targets']) == 0) {
659         unset($result['targets']);
660       }
661       return $result;
662     }
664     // Filter POST with "listing_" attributes
665     foreach ($_POST as $key => $prop) {
667       // Capture selections
668       if (preg_match('/^listing_selected_[0-9]+$/', $key)) {
669         $target= preg_replace('/^listing_selected_([0-9]+)$/', '$1', $key);
670         if (isset($this->entries[$target]['dn'])) {
671           $result['targets'][]= $this->entries[$target]['dn'];
672         }
673         continue;
674       }
676       // Capture action with target - this is a one shot
677       if (preg_match('/^listing_[a-zA-Z_]+_[0-9]+(|_x)$/', $key)) {
678         $target= preg_replace('/^listing_[a-zA-Z_]+_([0-9]+)(|_x)$/', '$1', $key);
679         if (isset($this->entries[$target]['dn'])) {
680           $result['action']= preg_replace('/^listing_([a-zA-Z_]+)_[0-9]+(|_x)$/', '$1', $key);
681           $result['targets']= array($this->entries[$target]['dn']);
682         }
683         break;
684       }
686       // Capture action without target
687       if (preg_match('/^listing_[a-zA-Z_]+(|_x)$/', $key)) {
688         $result['action']= preg_replace('/^listing_([a-zA-Z_]+)(|_x)$/', '$1', $key);
689         continue;
690       }
691     }
693     // Filter POST with "act" attributes -> posted from action menu
694     if (isset($_POST['act']) && $_POST['act'] != '') {
695       $result['action']= validate($_POST['act']);
696     }
698     // Drop targets if empty
699     if (count($result['targets']) == 0) {
700       unset($result['targets']);
701     }
702     return $result;
703   }
706   function renderActionMenu()
707   {
708     // Don't send anything if the menu is not defined
709     if (!isset($this->xmlData['actionmenu']['action'])){
710       return "";
711     }
713     // Load shortcut
714     $actions= &$this->xmlData['actionmenu']['action'];
715     $result= "<input type='hidden' name='act' id='actionmenu' value=''>".
716              "<ul class='level1' id='root'><li><a href='#'>Aktionen&nbsp;<img ".
717              "border=0 src='images/lists/sort-down.png'></a>";
719     // Build ul/li list
720     $result.= $this->recurseActions($actions);
722     return "<div id='pulldown'>".$result."</li></ul><div>";
723   }
726   function recurseActions($actions)
727   {
728     static $level= 2;
729     $result= "<ul class='level$level'>";
730     $separator= "";
732     foreach ($actions as $action) {
734       // Skip the entry completely if there's no permission to execute it
735       if (!$this->hasActionPermission($action, $this->filter->base)) {
736         continue;
737       }
739       // Fill image if set
740       $img= "";
741       if (isset($action['image'])){
742         $img= "<img border=0 src='".$action['image']."'>&nbsp;";
743       }
745       if ($action['type'] == "separator"){
746         $separator= " style='border-top:1px solid #AAA' ";
747         continue;
748       }
750       // Dive into subs
751       if ($action['type'] == "sub" && isset($action['action'])) {
752         $level++;
753         if (isset($action['label'])){
754           $result.= "<li$separator><a href='#'>$img"._($action['label'])."&nbsp;<img border='0' src='images/forward-arrow.png'></a>";
755         }
756         $result.= $this->recurseActions($action['action'])."</li>";
757         $level--;
758         $separator= "";
759         continue;
760       }
762       // Render entry elseways
763       if (isset($action['label'])){
764         $result.= "<li$separator><a href='#' onClick='document.getElementById(\"actionmenu\").value= \"".$action['name']."\";mainform.submit();'>$img"._($action['label'])."</a></li>";
765       }
767       // Check for special types
768       switch ($action['type']) {
769         case 'copypaste':
770           #TODO
771           #echo "actionmenu: copypaste missing<br>";
772           break;
774         case 'snapshot':
775           #TODO
776           #echo "actionmenu: snapshot missing<br>";
777           break;
779         case 'daemon':
780           #TODO
781           #echo "actionmenu: daemon missing<br>";
782           break;
783       }
785       $separator= "";
786     }
788     $result.= "</ul>";
789     return $result;
790   }
793   function hasActionPermission($action, $dn)
794   {
795     $ui= get_userinfo();
797     if (isset($action['acl'])) {
798       $acls= $action['acl'];
799       if (!is_array($acls)) {
800         $acls= array($acls);
801       }
803       // Every ACL has to pass
804       foreach ($acls as $acl) {
805         $module= $this->module;
806         $acllist= array();
808         // Split for category and plugins if needed
809         // match for "[rw]" style entries
810         if (preg_match('/^\[([rwcdm]+)\]$/', $acl, $match)){
811           $aclList= array($match[1]);
812         }
814         // match for "users[rw]" style entries
815         if (preg_match('/^([a-zA-Z0-9]+)\[([rwcdm]+)\]$/', $acl, $match)){
816           $module= $match[1];
817           $aclList= array($match[2]);
818         }
820         // match for "users/user[rw]" style entries
821         if (preg_match('/^([a-zA-Z0-9]+\/[a-zA-Z0-9]+)\[([rwcdm]+)\]$/', $acl, $match)){
822           $module= $match[1];
823           $aclList= array($match[2]);
824         }
826         // match "users/user[userPassword:rw(,...)*]" style entries
827         if (preg_match('/^([a-zA-Z0-9]+\/[a-zA-Z0-9]+)\[([a-zA-Z0-9]+:[rwcdm]+(,[a-zA-Z0-9]+:[rwcdm]+)*)\]$/', $acl, $match)){
828           $module= $match[1];
829           $aclList= split(',', $match[2]);
830         }
832         // Walk thru prepared ACL by using $module
833         foreach($aclList as $sAcl) {
834           $checkAcl= "";
836           // Category or detailed permission?
837           if (strpos('/', $module) === false) {
838             if (preg_match('/([a-zA-Z0-9]+):([rwcdm]+)/', $sAcl, $m) ) {
839               $checkAcl= $ui->get_permissions($dn, $module, $m[1]);
840               $sAcl= $m[2];
841             } else {
842               $checkAcl= $ui->get_permissions($dn, $module, '0');
843             }
844           } else {
845             $checkAcl= $ui->get_category_permissions($dn, $module);
846           }
848           // Split up remaining part of the acl and check if it we're
849           // allowed to do something...
850           $parts= str_split($sAcl);
851           foreach ($parts as $part) {
852             if (strpos($checkAcl, $part) === false){
853               return false;
854             }
855           }
857         }
858       }
859     }
861     return true;
862   }
865   function refreshBasesList()
866   {
867     global $config;
868     $ui= get_userinfo();
870     // Do some array munching to get it user friendly
871     $ids= $config->idepartments;
872     $d= $ui->get_module_departments($this->module);
873     $k_ids= array_keys($ids);
874     $deps= array_intersect($d,$k_ids);
876     // Fill internal bases list
877     $this->bases= array();
878     foreach($k_ids as $department){
879       $this->bases[$department] = $ids[$department];
880     }
881   }
886 ?>