xref: /dokuwiki/lib/plugins/acl/admin.php (revision 0636144287f7acf89c633d3d2f5214e1d229e033)
1<?php
2/**
3 * ACL administration functions
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Andreas Gohr <andi@splitbrain.org>
7 * @author     Anika Henke <anika@selfthinker.org> (concepts)
8 * @author     Frank Schubert <frank@schokilade.de> (old version)
9 */
10// must be run within Dokuwiki
11if(!defined('DOKU_INC')) die();
12
13/**
14 * All DokuWiki plugins to extend the admin function
15 * need to inherit from this class
16 */
17class admin_plugin_acl extends DokuWiki_Admin_Plugin {
18    var $acl = null;
19    var $ns  = null;
20    /**
21     * The currently selected item, associative array with id and type.
22     * Populated from (in this order):
23     * $_REQUEST['current_ns']
24     * $_REQUEST['current_id']
25     * $ns
26     * $ID
27     */
28    var $current_item = null;
29    var $who = '';
30    var $usersgroups = array();
31    var $specials = array();
32
33    /**
34     * return some info
35     */
36    function getInfo(){
37        return array(
38            'author' => 'Andreas Gohr',
39            'email'  => 'andi@splitbrain.org',
40            'date'   => '2010-01-17',
41            'name'   => 'ACL Manager',
42            'desc'   => 'Manage Page Access Control Lists',
43            'url'    => 'http://dokuwiki.org/plugin:acl',
44        );
45    }
46
47    /**
48     * return prompt for admin menu
49     */
50    function getMenuText($language) {
51        return $this->getLang('admin_acl');
52    }
53
54    /**
55     * return sort order for position in admin menu
56     */
57    function getMenuSort() {
58        return 1;
59    }
60
61    /**
62     * handle user request
63     *
64     * Initializes internal vars and handles modifications
65     *
66     * @author Andreas Gohr <andi@splitbrain.org>
67     */
68    function handle() {
69        global $AUTH_ACL;
70        global $ID;
71        global $auth;
72
73        // fresh 1:1 copy without replacements
74        $AUTH_ACL = file(DOKU_CONF.'acl.auth.php');
75
76
77        // namespace given?
78        if($_REQUEST['ns'] == '*'){
79            $this->ns = '*';
80        }else{
81            $this->ns = cleanID($_REQUEST['ns']);
82        }
83
84        if ($_REQUEST['current_ns']) {
85            $this->current_item = array('id' => cleanID($_REQUEST['current_ns']), 'type' => 'd');
86        } elseif ($_REQUEST['current_id']) {
87            $this->current_item = array('id' => cleanID($_REQUEST['current_id']), 'type' => 'f');
88        } elseif ($this->ns) {
89            $this->current_item = array('id' => $this->ns, 'type' => 'd');
90        } else {
91            $this->current_item = array('id' => $ID, 'type' => 'f');
92        }
93
94        // user or group choosen?
95        $who = trim($_REQUEST['acl_w']);
96        if($_REQUEST['acl_t'] == '__g__' && $who){
97            $this->who = '@'.ltrim($auth->cleanGroup($who),'@');
98        }elseif($_REQUEST['acl_t'] == '__u__' && $who){
99            $this->who = ltrim($who,'@');
100            if($this->who != '%USER%'){ #keep wildcard as is
101                $this->who = $auth->cleanUser($this->who);
102            }
103        }elseif($_REQUEST['acl_t'] &&
104                $_REQUEST['acl_t'] != '__u__' &&
105                $_REQUEST['acl_t'] != '__g__'){
106            $this->who = $_REQUEST['acl_t'];
107        }elseif($who){
108            $this->who = $who;
109        }
110
111        // handle modifications
112        if(isset($_REQUEST['cmd']) && checkSecurityToken()){
113
114            // scope for modifications
115            if($this->ns){
116                if($this->ns == '*'){
117                    $scope = '*';
118                }else{
119                    $scope = $this->ns.':*';
120                }
121            }else{
122                $scope = $ID;
123            }
124
125            if(isset($_REQUEST['cmd']['save']) && $scope && $this->who && isset($_REQUEST['acl'])){
126                // handle additions or single modifications
127                $this->_acl_del($scope, $this->who);
128                $this->_acl_add($scope, $this->who, (int) $_REQUEST['acl']);
129            }elseif(isset($_REQUEST['cmd']['del']) && $scope && $this->who){
130                // handle single deletions
131                $this->_acl_del($scope, $this->who);
132            }elseif(isset($_REQUEST['cmd']['update'])){
133                // handle update of the whole file
134                foreach((array) $_REQUEST['del'] as $where => $names){
135                    // remove all rules marked for deletion
136                    foreach($names as $who)
137                        unset($_REQUEST['acl'][$where][$who]);
138                }
139                // prepare lines
140                $lines = array();
141                // keep header
142                foreach($AUTH_ACL as $line){
143                    if($line{0} == '#'){
144                        $lines[] = $line;
145                    }else{
146                        break;
147                    }
148                }
149                // re-add all rules
150                foreach((array) $_REQUEST['acl'] as $where => $opt){
151                    foreach($opt as $who => $perm){
152                        if ($who[0]=='@') {
153                            if ($who!='@ALL') {
154                                $who = '@'.ltrim($auth->cleanGroup($who),'@');
155                            }
156                        } elseif ($who != '%USER%'){ #keep wildcard as is
157                            $who = $auth->cleanUser($who);
158                        }
159                        $who = auth_nameencode($who,true);
160                        $lines[] = "$where\t$who\t$perm\n";
161                    }
162                }
163                // save it
164                io_saveFile(DOKU_CONF.'acl.auth.php', join('',$lines));
165            }
166
167            // reload ACL config
168            $AUTH_ACL = file(DOKU_CONF.'acl.auth.php');
169        }
170
171        // initialize ACL array
172        $this->_init_acl_config();
173    }
174
175    /**
176     * ACL Output function
177     *
178     * print a table with all significant permissions for the
179     * current id
180     *
181     * @author  Frank Schubert <frank@schokilade.de>
182     * @author  Andreas Gohr <andi@splitbrain.org>
183     */
184    function html() {
185        global $ID;
186
187        echo '<div id="acl_manager">'.NL;
188        echo '<h1>'.$this->getLang('admin_acl').'</h1>'.NL;
189        echo '<div class="level1">'.NL;
190
191        echo '<div id="acl__tree">'.NL;
192        $this->_html_explorer();
193        echo '</div>'.NL;
194
195        echo '<div id="acl__detail">'.NL;
196        $this->_html_detail();
197        echo '</div>'.NL;
198        echo '</div>'.NL;
199
200        echo '<div class="clearer"></div>';
201        echo '<h2>'.$this->getLang('current').'</h2>'.NL;
202        echo '<div class="level2">'.NL;
203        $this->_html_table();
204        echo '</div>'.NL;
205
206        echo '<div class="footnotes"><div class="fn">'.NL;
207        echo '<sup><a id="fn__1" class="fn_bot" name="fn__1" href="#fnt__1">1)</a></sup>'.NL;
208        echo $this->getLang('p_include');
209        echo '</div></div>';
210
211        echo '</div>'.NL;
212    }
213
214    /**
215     * returns array with set options for building links
216     *
217     * @author Andreas Gohr <andi@splitbrain.org>
218     */
219    function _get_opts($addopts=null){
220        global $ID;
221        $opts = array(
222                    'do'=>'admin',
223                    'page'=>'acl',
224                );
225        if($this->ns) $opts['ns'] = $this->ns;
226        if($this->who) $opts['acl_w'] = $this->who;
227
228        if(is_null($addopts)) return $opts;
229        return array_merge($opts, $addopts);
230    }
231
232    /**
233     * Display a tree menu to select a page or namespace
234     *
235     * @author Andreas Gohr <andi@splitbrain.org>
236     */
237    function _html_explorer(){
238        global $conf;
239        global $ID;
240        global $lang;
241
242        $dir = $conf['datadir'];
243        $ns  = $this->ns;
244        if(empty($ns)){
245            $ns = dirname(str_replace(':','/',$ID));
246            if($ns == '.') $ns ='';
247        }elseif($ns == '*'){
248            $ns ='';
249        }
250        $ns  = utf8_encodeFN(str_replace(':','/',$ns));
251
252        $data = $this->_get_tree($ns);
253
254        // wrap a list with the root level around the other namespaces
255        $item = array( 'level' => 0, 'id' => '*', 'type' => 'd',
256                   'open' =>'true', 'label' => '['.$lang['mediaroot'].']');
257
258        echo '<ul class="acltree">';
259        echo $this->_html_li_acl($item);
260        echo '<div class="li">';
261        echo $this->_html_list_acl($item);
262        echo '</div>';
263        echo html_buildlist($data,'acl',
264                            array($this,'_html_list_acl'),
265                            array($this,'_html_li_acl'));
266        echo '</li>';
267        echo '</ul>';
268
269    }
270
271    /**
272     * get a combined list of media and page files
273     *
274     * @param string $folder an already converted filesystem folder of the current namespace
275     * @param string $limit  limit the search to this folder
276     */
277    function _get_tree($folder,$limit=''){
278        global $conf;
279
280        // read tree structure from pages and media
281        $data = array();
282        search($data,$conf['datadir'],'search_index',array('ns' => $folder),$limit);
283        $media = array();
284        search($media,$conf['mediadir'],'search_index',array('ns' => $folder, 'nofiles' => true),$limit);
285        $data = array_merge($data,$media);
286        unset($media);
287
288        // combine by sorting and removing duplicates
289        usort($data,array($this,'_tree_sort'));
290        $count = count($data);
291        if($count>0) for($i=1; $i<$count; $i++){
292            if($data[$i-1]['id'] == $data[$i]['id'] && $data[$i-1]['type'] == $data[$i]['type']) unset($data[$i]);
293        }
294        return $data;
295    }
296
297    /**
298     * usort callback
299     *
300     * Sorts the combined trees of media and page files
301     */
302    function _tree_sort($a,$b){
303        // handle the trivial cases first
304        if ($a['id'] == '') return -1;
305        if ($b['id'] == '') return 1;
306        // split up the id into parts
307        $a_ids = explode(':', $a['id']);
308        $b_ids = explode(':', $b['id']);
309        // now loop through the parts
310        while (count($a_ids) && count($b_ids)) {
311            // compare each level from upper to lower
312            // until a non-equal component is found
313            $cur_result = strcmp(array_shift($a_ids), array_shift($b_ids));
314            if ($cur_result) {
315                // if one of the components is the last component and is a file
316                // and the other one is either of a deeper level or a directory,
317                // the file has to come after the deeper level or directory
318                if (empty($a_ids) && $a['type'] == 'f' && (count($b_ids) || $b['type'] == 'd')) return 1;
319                if (empty($b_ids) && $b['type'] == 'f' && (count($a_ids) || $a['type'] == 'd')) return -1;
320                return $cur_result;
321            }
322        }
323        // The two ids seem to be equal. One of them might however refer
324        // to a page, one to a namespace, the namespace needs to be first.
325        if (empty($a_ids) && empty($b_ids)) {
326            if ($a['type'] == $b['type']) return 0;
327            if ($a['type'] == 'f') return 1;
328            return -1;
329        }
330        // Now the empty part is either a page in the parent namespace
331        // that obviously needs to be after the namespace
332        // Or it is the namespace that contains the other part and should be
333        // before that other part.
334        if (empty($a_ids)) return ($a['type'] == 'd') ? -1 : 1;
335        if (empty($b_ids)) return ($b['type'] == 'd') ? 1 : -1;
336    }
337
338    /**
339     * Display the current ACL for selected where/who combination with
340     * selectors and modification form
341     *
342     * @author Andreas Gohr <andi@splitbrain.org>
343     */
344    function _html_detail(){
345        global $conf;
346        global $ID;
347
348        echo '<form action="'.wl().'" method="post" accept-charset="utf-8"><div class="no">'.NL;
349
350        echo '<div id="acl__user">';
351        echo $this->getLang('acl_perms').' ';
352        $inl =  $this->_html_select();
353        echo '<input type="text" name="acl_w" class="edit" value="'.(($inl)?'':hsc(ltrim($this->who,'@'))).'" />'.NL;
354        echo '<input type="submit" value="'.$this->getLang('btn_select').'" class="button" />'.NL;
355        echo '</div>'.NL;
356
357        echo '<div id="acl__info">';
358        $this->_html_info();
359        echo '</div>';
360
361        echo '<input type="hidden" name="ns" value="'.hsc($this->ns).'" />'.NL;
362        echo '<input type="hidden" name="id" value="'.hsc($ID).'" />'.NL;
363        echo '<input type="hidden" name="do" value="admin" />'.NL;
364        echo '<input type="hidden" name="page" value="acl" />'.NL;
365        echo '<input type="hidden" name="sectok" value="'.getSecurityToken().'" />'.NL;
366        echo '</div></form>'.NL;
367    }
368
369    /**
370     * Print infos and editor
371     */
372    function _html_info(){
373        global $ID;
374
375        if($this->who){
376            $current = $this->_get_exact_perm();
377
378            // explain current permissions
379            $this->_html_explain($current);
380            // load editor
381            $this->_html_acleditor($current);
382        }else{
383            echo '<p>';
384            if($this->ns){
385                printf($this->getLang('p_choose_ns'),hsc($this->ns));
386            }else{
387                printf($this->getLang('p_choose_id'),hsc($ID));
388            }
389            echo '</p>';
390
391            echo $this->locale_xhtml('help');
392        }
393    }
394
395    /**
396     * Display the ACL editor
397     *
398     * @author Andreas Gohr <andi@splitbrain.org>
399     */
400    function _html_acleditor($current){
401        global $lang;
402
403        echo '<fieldset>';
404        if(is_null($current)){
405            echo '<legend>'.$this->getLang('acl_new').'</legend>';
406        }else{
407            echo '<legend>'.$this->getLang('acl_mod').'</legend>';
408        }
409
410
411        echo $this->_html_checkboxes($current,empty($this->ns),'acl');
412
413        if(is_null($current)){
414            echo '<input type="submit" name="cmd[save]" class="button" value="'.$lang['btn_save'].'" />'.NL;
415        }else{
416            echo '<input type="submit" name="cmd[save]" class="button" value="'.$lang['btn_update'].'" />'.NL;
417            echo '<input type="submit" name="cmd[del]" class="button" value="'.$lang['btn_delete'].'" />'.NL;
418        }
419
420        echo '</fieldset>';
421    }
422
423    /**
424     * Explain the currently set permissions in plain english/$lang
425     *
426     * @author Andreas Gohr <andi@splitbrain.org>
427     */
428    function _html_explain($current){
429        global $ID;
430        global $auth;
431
432        $who = $this->who;
433        $ns  = $this->ns;
434
435        // prepare where to check
436        if($ns){
437            if($ns == '*'){
438                $check='*';
439            }else{
440                $check=$ns.':*';
441            }
442        }else{
443            $check = $ID;
444        }
445
446        // prepare who to check
447        if($who{0} == '@'){
448            $user   = '';
449            $groups = array(ltrim($who,'@'));
450        }else{
451            $user = auth_nameencode($who);
452            $info = $auth->getUserData($user);
453            if($info === false){
454                $groups = array();
455            }else{
456                $groups = $info['grps'];
457            }
458        }
459
460        // check the permissions
461        $perm = auth_aclcheck($check,$user,$groups);
462
463        // build array of named permissions
464        $names = array();
465        if($perm){
466            if($ns){
467                if($perm >= AUTH_DELETE) $names[] = $this->getLang('acl_perm16');
468                if($perm >= AUTH_UPLOAD) $names[] = $this->getLang('acl_perm8');
469                if($perm >= AUTH_CREATE) $names[] = $this->getLang('acl_perm4');
470            }
471            if($perm >= AUTH_EDIT) $names[] = $this->getLang('acl_perm2');
472            if($perm >= AUTH_READ) $names[] = $this->getLang('acl_perm1');
473            $names = array_reverse($names);
474        }else{
475            $names[] = $this->getLang('acl_perm0');
476        }
477
478        // print permission explanation
479        echo '<p>';
480        if($user){
481            if($ns){
482                printf($this->getLang('p_user_ns'),hsc($who),hsc($ns),join(', ',$names));
483            }else{
484                printf($this->getLang('p_user_id'),hsc($who),hsc($ID),join(', ',$names));
485            }
486        }else{
487            if($ns){
488                printf($this->getLang('p_group_ns'),hsc(ltrim($who,'@')),hsc($ns),join(', ',$names));
489            }else{
490                printf($this->getLang('p_group_id'),hsc(ltrim($who,'@')),hsc($ID),join(', ',$names));
491            }
492        }
493        echo '</p>';
494
495        // add note if admin
496        if($perm == AUTH_ADMIN){
497            echo '<p>'.$this->getLang('p_isadmin').'</p>';
498        }elseif(is_null($current)){
499            echo '<p>'.$this->getLang('p_inherited').'</p>';
500        }
501    }
502
503
504    /**
505     * Item formatter for the tree view
506     *
507     * User function for html_buildlist()
508     *
509     * @author Andreas Gohr <andi@splitbrain.org>
510     */
511    function _html_list_acl($item){
512        global $ID;
513        $ret = '';
514        // what to display
515        if($item['label']){
516            $base = $item['label'];
517        }else{
518            $base = ':'.$item['id'];
519            $base = substr($base,strrpos($base,':')+1);
520        }
521
522        // highlight?
523        if( ($item['type']== $this->current_item['type'] && $item['id'] == $this->current_item['id']))
524            $cl = ' cur';
525
526        // namespace or page?
527        if($item['type']=='d'){
528            if($item['open']){
529                $img   = DOKU_BASE.'lib/images/minus.gif';
530                $alt   = '&minus;';
531            }else{
532                $img   = DOKU_BASE.'lib/images/plus.gif';
533                $alt   = '+';
534            }
535            $ret .= '<img src="'.$img.'" alt="'.$alt.'" />';
536            $ret .= '<a href="'.wl('',$this->_get_opts(array('ns'=>$item['id'],'sectok'=>getSecurityToken()))).'" class="idx_dir'.$cl.'">';
537            $ret .= $base;
538            $ret .= '</a>';
539        }else{
540            $ret .= '<a href="'.wl('',$this->_get_opts(array('id'=>$item['id'],'ns'=>'','sectok'=>getSecurityToken()))).'" class="wikilink1'.$cl.'">';
541            $ret .= noNS($item['id']);
542            $ret .= '</a>';
543        }
544        return $ret;
545    }
546
547
548    function _html_li_acl($item){
549            return '<li class="level'.$item['level'].'">';
550    }
551
552
553    /**
554     * Get current ACL settings as multidim array
555     *
556     * @author Andreas Gohr <andi@splitbrain.org>
557     */
558    function _init_acl_config(){
559        global $AUTH_ACL;
560        global $conf;
561        $acl_config=array();
562        $usersgroups = array();
563
564        // get special users and groups
565        $this->specials[] = '@ALL';
566        $this->specials[] = '@'.$conf['defaultgroup'];
567        if($conf['manager'] != '!!not set!!'){
568            $this->specials = array_merge($this->specials,
569                                          array_map('trim',
570                                                    explode(',',$conf['manager'])));
571        }
572        $this->specials = array_filter($this->specials);
573        $this->specials = array_unique($this->specials);
574        sort($this->specials);
575
576        foreach($AUTH_ACL as $line){
577            $line = trim(preg_replace('/#.*$/','',$line)); //ignore comments
578            if(!$line) continue;
579
580            $acl = preg_split('/\s+/',$line);
581            //0 is pagename, 1 is user, 2 is acl
582
583            $acl[1] = rawurldecode($acl[1]);
584            $acl_config[$acl[0]][$acl[1]] = $acl[2];
585
586            // store non-special users and groups for later selection dialog
587            $ug = $acl[1];
588            if(in_array($ug,$this->specials)) continue;
589            $usersgroups[] = $ug;
590        }
591
592        $usersgroups = array_unique($usersgroups);
593        sort($usersgroups);
594        ksort($acl_config);
595
596        $this->acl = $acl_config;
597        $this->usersgroups = $usersgroups;
598    }
599
600    /**
601     * Display all currently set permissions in a table
602     *
603     * @author Andreas Gohr <andi@splitbrain.org>
604     */
605    function _html_table(){
606        global $lang;
607        global $ID;
608
609        echo '<form action="'.wl().'" method="post" accept-charset="utf-8"><div class="no">'.NL;
610        if($this->ns){
611            echo '<input type="hidden" name="ns" value="'.hsc($this->ns).'" />'.NL;
612        }else{
613            echo '<input type="hidden" name="id" value="'.hsc($ID).'" />'.NL;
614        }
615        echo '<input type="hidden" name="acl_w" value="'.hsc($this->who).'" />'.NL;
616        echo '<input type="hidden" name="do" value="admin" />'.NL;
617        echo '<input type="hidden" name="page" value="acl" />'.NL;
618        echo '<input type="hidden" name="sectok" value="'.getSecurityToken().'" />'.NL;
619        echo '<table class="inline">';
620        echo '<tr>';
621        echo '<th>'.$this->getLang('where').'</th>';
622        echo '<th>'.$this->getLang('who').'</th>';
623        echo '<th>'.$this->getLang('perm').'<sup><a id="fnt__1" class="fn_top" name="fnt__1" href="#fn__1">1)</a></sup></th>';
624        echo '<th>'.$lang['btn_delete'].'</th>';
625        echo '</tr>';
626        foreach($this->acl as $where => $set){
627            foreach($set as $who => $perm){
628                echo '<tr>';
629                echo '<td>';
630                if(substr($where,-1) == '*'){
631                    echo '<span class="aclns">'.hsc($where).'</span>';
632                    $ispage = false;
633                }else{
634                    echo '<span class="aclpage">'.hsc($where).'</span>';
635                    $ispage = true;
636                }
637                echo '</td>';
638
639                echo '<td>';
640                if($who{0} == '@'){
641                    echo '<span class="aclgroup">'.hsc($who).'</span>';
642                }else{
643                    echo '<span class="acluser">'.hsc($who).'</span>';
644                }
645                echo '</td>';
646
647                echo '<td>';
648                echo $this->_html_checkboxes($perm,$ispage,'acl['.$where.']['.$who.']');
649                echo '</td>';
650
651                echo '<td align="center">';
652                echo '<input type="checkbox" name="del['.hsc($where).'][]" value="'.hsc($who).'" />';
653                echo '</td>';
654                echo '</tr>';
655            }
656        }
657
658        echo '<tr>';
659        echo '<th align="right" colspan="4">';
660        echo '<input type="submit" value="'.$lang['btn_update'].'" name="cmd[update]" class="button" />';
661        echo '</th>';
662        echo '</tr>';
663        echo '</table>';
664        echo '</div></form>'.NL;
665    }
666
667
668    /**
669     * Returns the permission which were set for exactly the given user/group
670     * and page/namespace. Returns null if no exact match is available
671     *
672     * @author Andreas Gohr <andi@splitbrain.org>
673     */
674    function _get_exact_perm(){
675        global $ID;
676        if($this->ns){
677            if($this->ns == '*'){
678                $check = '*';
679            }else{
680                $check = $this->ns.':*';
681            }
682        }else{
683            $check = $ID;
684        }
685
686        if(isset($this->acl[$check][$this->who])){
687            return $this->acl[$check][$this->who];
688        }else{
689            return null;
690        }
691    }
692
693    /**
694     * adds new acl-entry to conf/acl.auth.php
695     *
696     * @author  Frank Schubert <frank@schokilade.de>
697     */
698    function _acl_add($acl_scope, $acl_user, $acl_level){
699        $acl_config = file_get_contents(DOKU_CONF.'acl.auth.php');
700        $acl_user = auth_nameencode($acl_user,true);
701
702        // max level for pagenames is edit
703        if(strpos($acl_scope,'*') === false) {
704            if($acl_level > AUTH_EDIT) $acl_level = AUTH_EDIT;
705        }
706
707
708        $new_acl = "$acl_scope\t$acl_user\t$acl_level\n";
709
710        $new_config = $acl_config.$new_acl;
711
712        return io_saveFile(DOKU_CONF.'acl.auth.php', $new_config);
713    }
714
715    /**
716     * remove acl-entry from conf/acl.auth.php
717     *
718     * @author  Frank Schubert <frank@schokilade.de>
719     */
720    function _acl_del($acl_scope, $acl_user){
721        $acl_config = file(DOKU_CONF.'acl.auth.php');
722        $acl_user = auth_nameencode($acl_user,true);
723
724        $acl_pattern = '^'.preg_quote($acl_scope,'/').'\s+'.$acl_user.'\s+[0-8].*$';
725
726        // save all non!-matching
727        $new_config = preg_grep("/$acl_pattern/", $acl_config, PREG_GREP_INVERT);
728
729        return io_saveFile(DOKU_CONF.'acl.auth.php', join('',$new_config));
730    }
731
732    /**
733     * print the permission radio boxes
734     *
735     * @author  Frank Schubert <frank@schokilade.de>
736     * @author  Andreas Gohr <andi@splitbrain.org>
737     */
738    function _html_checkboxes($setperm,$ispage,$name){
739        global $lang;
740
741        static $label = 0; //number labels
742        $ret = '';
743
744        if($ispage && $setperm > AUTH_EDIT) $perm = AUTH_EDIT;
745
746        foreach(array(AUTH_NONE,AUTH_READ,AUTH_EDIT,AUTH_CREATE,AUTH_UPLOAD,AUTH_DELETE) as $perm){
747            $label += 1;
748
749            //general checkbox attributes
750            $atts = array( 'type'  => 'radio',
751                           'id'    => 'pbox'.$label,
752                           'name'  => $name,
753                           'value' => $perm );
754            //dynamic attributes
755            if(!is_null($setperm) && $setperm == $perm) $atts['checked']  = 'checked';
756            if($ispage && $perm > AUTH_EDIT){
757                $atts['disabled'] = 'disabled';
758                $class = ' class="disabled"';
759            }else{
760                $class = '';
761            }
762
763            //build code
764            $ret .= '<label for="pbox'.$label.'" title="'.$this->getLang('acl_perm'.$perm).'"'.$class.'>';
765            $ret .= '<input '.html_attbuild($atts).' />&nbsp;';
766            $ret .= $this->getLang('acl_perm'.$perm);
767            $ret .= '</label>'.NL;
768        }
769        return $ret;
770    }
771
772    /**
773     * Print a user/group selector (reusing already used users and groups)
774     *
775     * @author  Andreas Gohr <andi@splitbrain.org>
776     */
777    function _html_select(){
778        global $conf;
779        $inlist = false;
780
781        if($this->who &&
782           !in_array($this->who,$this->usersgroups) &&
783           !in_array($this->who,$this->specials)){
784
785            if($this->who{0} == '@'){
786                $gsel = ' selected="selected"';
787            }else{
788                $usel   = ' selected="selected"';
789            }
790        }else{
791            $usel = '';
792            $gsel = '';
793            $inlist = true;
794        }
795
796
797        echo '<select name="acl_t" class="edit">'.NL;
798        echo '  <option value="__g__" class="aclgroup"'.$gsel.'>'.$this->getLang('acl_group').':</option>'.NL;
799        echo '  <option value="__u__"  class="acluser"'.$usel.'>'.$this->getLang('acl_user').':</option>'.NL;
800        echo '  <optgroup label="&nbsp;">'.NL;
801        foreach($this->specials as $ug){
802            if($ug == $this->who){
803                $sel    = ' selected="selected"';
804                $inlist = true;
805            }else{
806                $sel = '';
807            }
808
809            if($ug{0} == '@'){
810                    echo '  <option value="'.hsc($ug).'" class="aclgroup"'.$sel.'>'.hsc($ug).'</option>'.NL;
811            }else{
812                    echo '  <option value="'.hsc($ug).'" class="acluser"'.$sel.'>'.hsc($ug).'</option>'.NL;
813            }
814        }
815        echo '  </optgroup>'.NL;
816        echo '  <optgroup label="&nbsp;">'.NL;
817        foreach($this->usersgroups as $ug){
818            if($ug == $this->who){
819                $sel    = ' selected="selected"';
820                $inlist = true;
821            }else{
822                $sel = '';
823            }
824
825            if($ug{0} == '@'){
826                    echo '  <option value="'.hsc($ug).'" class="aclgroup"'.$sel.'>'.hsc($ug).'</option>'.NL;
827            }else{
828                    echo '  <option value="'.hsc($ug).'" class="acluser"'.$sel.'>'.hsc($ug).'</option>'.NL;
829            }
830        }
831        echo '  </optgroup>'.NL;
832        echo '</select>'.NL;
833        return $inlist;
834    }
835}
836