Completed
Push — remoteapiGetversions ( 33fe8b...b2f4ab )
by Gerrit
12s
created

admin_plugin_acl::_html_explorer()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 25
rs 8.5806
cc 4
eloc 17
nc 4
nop 0
1
<?php
2
/**
3
 * ACL administration functions
4
 *
5
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
 * @author     Andreas Gohr <[email protected]>
7
 * @author     Anika Henke <[email protected]> (concepts)
8
 * @author     Frank Schubert <[email protected]> (old version)
9
 */
10
// must be run within Dokuwiki
11
if(!defined('DOKU_INC')) die();
12
13
/**
14
 * All DokuWiki plugins to extend the admin function
15
 * need to inherit from this class
16
 */
17
class 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 prompt for admin menu
35
     */
36
    function getMenuText($language) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
37
        return $this->getLang('admin_acl');
38
    }
39
40
    /**
41
     * return sort order for position in admin menu
42
     */
43
    function getMenuSort() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
44
        return 1;
45
    }
46
47
    /**
48
     * handle user request
49
     *
50
     * Initializes internal vars and handles modifications
51
     *
52
     * @author Andreas Gohr <[email protected]>
53
     */
54
    function handle() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
55
        global $AUTH_ACL;
56
        global $ID;
57
        global $auth;
58
        global $config_cascade;
59
        global $INPUT;
60
61
        // fresh 1:1 copy without replacements
62
        $AUTH_ACL = file($config_cascade['acl']['default']);
63
64
        // namespace given?
65
        if($INPUT->str('ns') == '*'){
66
            $this->ns = '*';
67
        }else{
68
            $this->ns = cleanID($INPUT->str('ns'));
69
        }
70
71
        if ($INPUT->str('current_ns')) {
72
            $this->current_item = array('id' => cleanID($INPUT->str('current_ns')), 'type' => 'd');
73
        } elseif ($INPUT->str('current_id')) {
74
            $this->current_item = array('id' => cleanID($INPUT->str('current_id')), 'type' => 'f');
75
        } elseif ($this->ns) {
76
            $this->current_item = array('id' => $this->ns, 'type' => 'd');
77
        } else {
78
            $this->current_item = array('id' => $ID, 'type' => 'f');
79
        }
80
81
        // user or group choosen?
82
        $who = trim($INPUT->str('acl_w'));
83
        if($INPUT->str('acl_t') == '__g__' && $who){
84
            $this->who = '@'.ltrim($auth->cleanGroup($who),'@');
85
        }elseif($INPUT->str('acl_t') == '__u__' && $who){
86
            $this->who = ltrim($who,'@');
87
            if($this->who != '%USER%' && $this->who != '%GROUP%'){ #keep wildcard as is
88
                $this->who = $auth->cleanUser($this->who);
89
            }
90
        }elseif($INPUT->str('acl_t') &&
91
                $INPUT->str('acl_t') != '__u__' &&
92
                $INPUT->str('acl_t') != '__g__'){
93
            $this->who = $INPUT->str('acl_t');
94
        }elseif($who){
95
            $this->who = $who;
96
        }
97
98
        // handle modifications
99
        if($INPUT->has('cmd') && checkSecurityToken()){
100
            $cmd = $INPUT->extract('cmd')->str('cmd');
101
102
            // scope for modifications
103
            if($this->ns){
104
                if($this->ns == '*'){
105
                    $scope = '*';
106
                }else{
107
                    $scope = $this->ns.':*';
108
                }
109
            }else{
110
                $scope = $ID;
111
            }
112
113
            if($cmd == 'save' && $scope && $this->who && $INPUT->has('acl')){
114
                // handle additions or single modifications
115
                $this->_acl_del($scope, $this->who);
116
                $this->_acl_add($scope, $this->who, $INPUT->int('acl'));
117
            }elseif($cmd == 'del' && $scope && $this->who){
118
                // handle single deletions
119
                $this->_acl_del($scope, $this->who);
120
            }elseif($cmd == 'update'){
121
                $acl = $INPUT->arr('acl');
122
123
                // handle update of the whole file
124
                foreach($INPUT->arr('del') as $where => $names){
125
                    // remove all rules marked for deletion
126
                    foreach($names as $who)
127
                        unset($acl[$where][$who]);
128
                }
129
                // prepare lines
130
                $lines = array();
131
                // keep header
132
                foreach($AUTH_ACL as $line){
133
                    if($line{0} == '#'){
134
                        $lines[] = $line;
135
                    }else{
136
                        break;
137
                    }
138
                }
139
                // re-add all rules
140
                foreach($acl as $where => $opt){
141
                    foreach($opt as $who => $perm){
142
                        if ($who[0]=='@') {
143
                            if ($who!='@ALL') {
144
                                $who = '@'.ltrim($auth->cleanGroup($who),'@');
145
                            }
146
                        } elseif ($who != '%USER%' && $who != '%GROUP%'){ #keep wildcard as is
147
                            $who = $auth->cleanUser($who);
148
                        }
149
                        $who = auth_nameencode($who,true);
150
                        $lines[] = "$where\t$who\t$perm\n";
151
                    }
152
                }
153
                // save it
154
                io_saveFile($config_cascade['acl']['default'], join('',$lines));
155
            }
156
157
            // reload ACL config
158
            $AUTH_ACL = file($config_cascade['acl']['default']);
159
        }
160
161
        // initialize ACL array
162
        $this->_init_acl_config();
163
    }
164
165
    /**
166
     * ACL Output function
167
     *
168
     * print a table with all significant permissions for the
169
     * current id
170
     *
171
     * @author  Frank Schubert <[email protected]>
172
     * @author  Andreas Gohr <[email protected]>
173
     */
174
    function html() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
175
        echo '<div id="acl_manager">'.NL;
176
        echo '<h1>'.$this->getLang('admin_acl').'</h1>'.NL;
177
        echo '<div class="level1">'.NL;
178
179
        echo '<div id="acl__tree">'.NL;
180
        $this->_html_explorer();
181
        echo '</div>'.NL;
182
183
        echo '<div id="acl__detail">'.NL;
184
        $this->_html_detail();
185
        echo '</div>'.NL;
186
        echo '</div>'.NL;
187
188
        echo '<div class="clearer"></div>';
189
        echo '<h2>'.$this->getLang('current').'</h2>'.NL;
190
        echo '<div class="level2">'.NL;
191
        $this->_html_table();
192
        echo '</div>'.NL;
193
194
        echo '<div class="footnotes"><div class="fn">'.NL;
195
        echo '<sup><a id="fn__1" class="fn_bot" href="#fnt__1">1)</a></sup>'.NL;
196
        echo $this->getLang('p_include');
197
        echo '</div></div>';
198
199
        echo '</div>'.NL;
200
    }
201
202
    /**
203
     * returns array with set options for building links
204
     *
205
     * @author Andreas Gohr <[email protected]>
206
     */
207
    function _get_opts($addopts=null){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
208
        $opts = array(
209
                    'do'=>'admin',
210
                    'page'=>'acl',
211
                );
212
        if($this->ns) $opts['ns'] = $this->ns;
213
        if($this->who) $opts['acl_w'] = $this->who;
214
215
        if(is_null($addopts)) return $opts;
216
        return array_merge($opts, $addopts);
217
    }
218
219
    /**
220
     * Display a tree menu to select a page or namespace
221
     *
222
     * @author Andreas Gohr <[email protected]>
223
     */
224
    function _html_explorer(){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
225
        global $conf;
226
        global $ID;
227
        global $lang;
228
229
        $ns  = $this->ns;
230
        if(empty($ns)){
231
            $ns = dirname(str_replace(':','/',$ID));
232
            if($ns == '.') $ns ='';
233
        }elseif($ns == '*'){
234
            $ns ='';
235
        }
236
        $ns  = utf8_encodeFN(str_replace(':','/',$ns));
237
238
        $data = $this->_get_tree($ns);
239
240
        // wrap a list with the root level around the other namespaces
241
        array_unshift($data, array( 'level' => 0, 'id' => '*', 'type' => 'd',
242
                   'open' =>'true', 'label' => '['.$lang['mediaroot'].']'));
243
244
        echo html_buildlist($data,'acl',
245
                            array($this,'_html_list_acl'),
246
                            array($this,'_html_li_acl'));
247
248
    }
249
250
    /**
251
     * get a combined list of media and page files
252
     *
253
     * @param string $folder an already converted filesystem folder of the current namespace
254
     * @param string $limit  limit the search to this folder
255
     */
256
    function _get_tree($folder,$limit=''){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
257
        global $conf;
258
259
        // read tree structure from pages and media
260
        $data = array();
261
        search($data,$conf['datadir'],'search_index',array('ns' => $folder),$limit);
262
        $media = array();
263
        search($media,$conf['mediadir'],'search_index',array('ns' => $folder, 'nofiles' => true),$limit);
264
        $data = array_merge($data,$media);
265
        unset($media);
266
267
        // combine by sorting and removing duplicates
268
        usort($data,array($this,'_tree_sort'));
269
        $count = count($data);
270
        if($count>0) for($i=1; $i<$count; $i++){
271
            if($data[$i-1]['id'] == $data[$i]['id'] && $data[$i-1]['type'] == $data[$i]['type']) {
272
                unset($data[$i]);
273
                $i++;  // duplicate found, next $i can't be a duplicate, so skip forward one
274
            }
275
        }
276
        return $data;
277
    }
278
279
    /**
280
     * usort callback
281
     *
282
     * Sorts the combined trees of media and page files
283
     */
284
    function _tree_sort($a,$b){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
285
        // handle the trivial cases first
286
        if ($a['id'] == '') return -1;
287
        if ($b['id'] == '') return 1;
288
        // split up the id into parts
289
        $a_ids = explode(':', $a['id']);
290
        $b_ids = explode(':', $b['id']);
291
        // now loop through the parts
292
        while (count($a_ids) && count($b_ids)) {
293
            // compare each level from upper to lower
294
            // until a non-equal component is found
295
            $cur_result = strcmp(array_shift($a_ids), array_shift($b_ids));
296
            if ($cur_result) {
297
                // if one of the components is the last component and is a file
298
                // and the other one is either of a deeper level or a directory,
299
                // the file has to come after the deeper level or directory
300
                if (empty($a_ids) && $a['type'] == 'f' && (count($b_ids) || $b['type'] == 'd')) return 1;
301
                if (empty($b_ids) && $b['type'] == 'f' && (count($a_ids) || $a['type'] == 'd')) return -1;
302
                return $cur_result;
303
            }
304
        }
305
        // The two ids seem to be equal. One of them might however refer
306
        // to a page, one to a namespace, the namespace needs to be first.
307
        if (empty($a_ids) && empty($b_ids)) {
308
            if ($a['type'] == $b['type']) return 0;
309
            if ($a['type'] == 'f') return 1;
310
            return -1;
311
        }
312
        // Now the empty part is either a page in the parent namespace
313
        // that obviously needs to be after the namespace
314
        // Or it is the namespace that contains the other part and should be
315
        // before that other part.
316
        if (empty($a_ids)) return ($a['type'] == 'd') ? -1 : 1;
317
        if (empty($b_ids)) return ($b['type'] == 'd') ? 1 : -1;
318
    }
319
320
    /**
321
     * Display the current ACL for selected where/who combination with
322
     * selectors and modification form
323
     *
324
     * @author Andreas Gohr <[email protected]>
325
     */
326
    function _html_detail(){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
327
        global $ID;
328
329
        echo '<form action="'.wl().'" method="post" accept-charset="utf-8"><div class="no">'.NL;
330
331
        echo '<div id="acl__user">';
332
        echo $this->getLang('acl_perms').' ';
333
        $inl =  $this->_html_select();
334
        echo '<input type="text" name="acl_w" class="edit" value="'.(($inl)?'':hsc(ltrim($this->who,'@'))).'" />'.NL;
335
        echo '<button type="submit">'.$this->getLang('btn_select').'</button>'.NL;
336
        echo '</div>'.NL;
337
338
        echo '<div id="acl__info">';
339
        $this->_html_info();
340
        echo '</div>';
341
342
        echo '<input type="hidden" name="ns" value="'.hsc($this->ns).'" />'.NL;
343
        echo '<input type="hidden" name="id" value="'.hsc($ID).'" />'.NL;
344
        echo '<input type="hidden" name="do" value="admin" />'.NL;
345
        echo '<input type="hidden" name="page" value="acl" />'.NL;
346
        echo '<input type="hidden" name="sectok" value="'.getSecurityToken().'" />'.NL;
347
        echo '</div></form>'.NL;
348
    }
349
350
    /**
351
     * Print info and editor
352
     */
353
    function _html_info(){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
354
        global $ID;
355
356
        if($this->who){
357
            $current = $this->_get_exact_perm();
358
359
            // explain current permissions
360
            $this->_html_explain($current);
361
            // load editor
362
            $this->_html_acleditor($current);
363
        }else{
364
            echo '<p>';
365
            if($this->ns){
366
                printf($this->getLang('p_choose_ns'),hsc($this->ns));
367
            }else{
368
                printf($this->getLang('p_choose_id'),hsc($ID));
369
            }
370
            echo '</p>';
371
372
            echo $this->locale_xhtml('help');
373
        }
374
    }
375
376
    /**
377
     * Display the ACL editor
378
     *
379
     * @author Andreas Gohr <[email protected]>
380
     */
381
    function _html_acleditor($current){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
382
        global $lang;
383
384
        echo '<fieldset>';
385
        if(is_null($current)){
386
            echo '<legend>'.$this->getLang('acl_new').'</legend>';
387
        }else{
388
            echo '<legend>'.$this->getLang('acl_mod').'</legend>';
389
        }
390
391
        echo $this->_html_checkboxes($current,empty($this->ns),'acl');
392
393
        if(is_null($current)){
394
            echo '<button type="submit" name="cmd[save]">'.$lang['btn_save'].'</button>'.NL;
395
        }else{
396
            echo '<button type="submit" name="cmd[save]">'.$lang['btn_update'].'</button>'.NL;
397
            echo '<button type="submit" name="cmd[del]">'.$lang['btn_delete'].'</button>'.NL;
398
        }
399
400
        echo '</fieldset>';
401
    }
402
403
    /**
404
     * Explain the currently set permissions in plain english/$lang
405
     *
406
     * @author Andreas Gohr <[email protected]>
407
     */
408
    function _html_explain($current){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
409
        global $ID;
410
        global $auth;
411
412
        $who = $this->who;
413
        $ns  = $this->ns;
414
415
        // prepare where to check
416
        if($ns){
417
            if($ns == '*'){
418
                $check='*';
419
            }else{
420
                $check=$ns.':*';
421
            }
422
        }else{
423
            $check = $ID;
424
        }
425
426
        // prepare who to check
427
        if($who{0} == '@'){
428
            $user   = '';
429
            $groups = array(ltrim($who,'@'));
430
        }else{
431
            $user = $who;
432
            $info = $auth->getUserData($user);
433
            if($info === false){
434
                $groups = array();
435
            }else{
436
                $groups = $info['grps'];
437
            }
438
        }
439
440
        // check the permissions
441
        $perm = auth_aclcheck($check,$user,$groups);
442
443
        // build array of named permissions
444
        $names = array();
445
        if($perm){
446
            if($ns){
447
                if($perm >= AUTH_DELETE) $names[] = $this->getLang('acl_perm16');
448
                if($perm >= AUTH_UPLOAD) $names[] = $this->getLang('acl_perm8');
449
                if($perm >= AUTH_CREATE) $names[] = $this->getLang('acl_perm4');
450
            }
451
            if($perm >= AUTH_EDIT) $names[] = $this->getLang('acl_perm2');
452
            if($perm >= AUTH_READ) $names[] = $this->getLang('acl_perm1');
453
            $names = array_reverse($names);
454
        }else{
455
            $names[] = $this->getLang('acl_perm0');
456
        }
457
458
        // print permission explanation
459
        echo '<p>';
460
        if($user){
461
            if($ns){
462
                printf($this->getLang('p_user_ns'),hsc($who),hsc($ns),join(', ',$names));
463
            }else{
464
                printf($this->getLang('p_user_id'),hsc($who),hsc($ID),join(', ',$names));
465
            }
466
        }else{
467
            if($ns){
468
                printf($this->getLang('p_group_ns'),hsc(ltrim($who,'@')),hsc($ns),join(', ',$names));
469
            }else{
470
                printf($this->getLang('p_group_id'),hsc(ltrim($who,'@')),hsc($ID),join(', ',$names));
471
            }
472
        }
473
        echo '</p>';
474
475
        // add note if admin
476
        if($perm == AUTH_ADMIN){
477
            echo '<p>'.$this->getLang('p_isadmin').'</p>';
478
        }elseif(is_null($current)){
479
            echo '<p>'.$this->getLang('p_inherited').'</p>';
480
        }
481
    }
482
483
484
    /**
485
     * Item formatter for the tree view
486
     *
487
     * User function for html_buildlist()
488
     *
489
     * @author Andreas Gohr <[email protected]>
490
     */
491
    function _html_list_acl($item){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
492
        $ret = '';
493
        // what to display
494
        if(!empty($item['label'])){
495
            $base = $item['label'];
496
        }else{
497
            $base = ':'.$item['id'];
498
            $base = substr($base,strrpos($base,':')+1);
499
        }
500
501
        // highlight?
502
        if( ($item['type']== $this->current_item['type'] && $item['id'] == $this->current_item['id'])) {
503
            $cl = ' cur';
504
        } else {
505
            $cl = '';
506
        }
507
508
        // namespace or page?
509
        if($item['type']=='d'){
510
            if($item['open']){
511
                $img   = DOKU_BASE.'lib/images/minus.gif';
512
                $alt   = '−';
513
            }else{
514
                $img   = DOKU_BASE.'lib/images/plus.gif';
515
                $alt   = '+';
516
            }
517
            $ret .= '<img src="'.$img.'" alt="'.$alt.'" />';
518
            $ret .= '<a href="'.wl('',$this->_get_opts(array('ns'=>$item['id'],'sectok'=>getSecurityToken()))).'" class="idx_dir'.$cl.'">';
519
            $ret .= $base;
520
            $ret .= '</a>';
521
        }else{
522
            $ret .= '<a href="'.wl('',$this->_get_opts(array('id'=>$item['id'],'ns'=>'','sectok'=>getSecurityToken()))).'" class="wikilink1'.$cl.'">';
523
            $ret .= noNS($item['id']);
524
            $ret .= '</a>';
525
        }
526
        return $ret;
527
    }
528
529
530
    function _html_li_acl($item){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
531
        return '<li class="level' . $item['level'] . ' ' .
532
               ($item['open'] ? 'open' : 'closed') . '">';
533
    }
534
535
536
    /**
537
     * Get current ACL settings as multidim array
538
     *
539
     * @author Andreas Gohr <[email protected]>
540
     */
541
    function _init_acl_config(){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
542
        global $AUTH_ACL;
543
        global $conf;
544
        $acl_config=array();
545
        $usersgroups = array();
546
547
        // get special users and groups
548
        $this->specials[] = '@ALL';
549
        $this->specials[] = '@'.$conf['defaultgroup'];
550
        if($conf['manager'] != '!!not set!!'){
551
            $this->specials = array_merge($this->specials,
552
                                          array_map('trim',
553
                                                    explode(',',$conf['manager'])));
554
        }
555
        $this->specials = array_filter($this->specials);
556
        $this->specials = array_unique($this->specials);
557
        sort($this->specials);
558
559
        foreach($AUTH_ACL as $line){
560
            $line = trim(preg_replace('/#.*$/','',$line)); //ignore comments
561
            if(!$line) continue;
562
563
            $acl = preg_split('/[ \t]+/',$line);
564
            //0 is pagename, 1 is user, 2 is acl
565
566
            $acl[1] = rawurldecode($acl[1]);
567
            $acl_config[$acl[0]][$acl[1]] = $acl[2];
568
569
            // store non-special users and groups for later selection dialog
570
            $ug = $acl[1];
571
            if(in_array($ug,$this->specials)) continue;
572
            $usersgroups[] = $ug;
573
        }
574
575
        $usersgroups = array_unique($usersgroups);
576
        sort($usersgroups);
577
        ksort($acl_config);
578
579
        $this->acl = $acl_config;
580
        $this->usersgroups = $usersgroups;
581
    }
582
583
    /**
584
     * Display all currently set permissions in a table
585
     *
586
     * @author Andreas Gohr <[email protected]>
587
     */
588
    function _html_table(){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
589
        global $lang;
590
        global $ID;
591
592
        echo '<form action="'.wl().'" method="post" accept-charset="utf-8"><div class="no">'.NL;
593
        if($this->ns){
594
            echo '<input type="hidden" name="ns" value="'.hsc($this->ns).'" />'.NL;
595
        }else{
596
            echo '<input type="hidden" name="id" value="'.hsc($ID).'" />'.NL;
597
        }
598
        echo '<input type="hidden" name="acl_w" value="'.hsc($this->who).'" />'.NL;
599
        echo '<input type="hidden" name="do" value="admin" />'.NL;
600
        echo '<input type="hidden" name="page" value="acl" />'.NL;
601
        echo '<input type="hidden" name="sectok" value="'.getSecurityToken().'" />'.NL;
602
        echo '<div class="table">';
603
        echo '<table class="inline">';
604
        echo '<tr>';
605
        echo '<th>'.$this->getLang('where').'</th>';
606
        echo '<th>'.$this->getLang('who').'</th>';
607
        echo '<th>'.$this->getLang('perm').'<sup><a id="fnt__1" class="fn_top" href="#fn__1">1)</a></sup></th>';
608
        echo '<th>'.$lang['btn_delete'].'</th>';
609
        echo '</tr>';
610
        foreach($this->acl as $where => $set){
611
            foreach($set as $who => $perm){
612
                echo '<tr>';
613
                echo '<td>';
614
                if(substr($where,-1) == '*'){
615
                    echo '<span class="aclns">'.hsc($where).'</span>';
616
                    $ispage = false;
617
                }else{
618
                    echo '<span class="aclpage">'.hsc($where).'</span>';
619
                    $ispage = true;
620
                }
621
                echo '</td>';
622
623
                echo '<td>';
624
                if($who{0} == '@'){
625
                    echo '<span class="aclgroup">'.hsc($who).'</span>';
626
                }else{
627
                    echo '<span class="acluser">'.hsc($who).'</span>';
628
                }
629
                echo '</td>';
630
631
                echo '<td>';
632
                echo $this->_html_checkboxes($perm,$ispage,'acl['.$where.']['.$who.']');
633
                echo '</td>';
634
635
                echo '<td class="check">';
636
                echo '<input type="checkbox" name="del['.hsc($where).'][]" value="'.hsc($who).'" />';
637
                echo '</td>';
638
                echo '</tr>';
639
            }
640
        }
641
642
        echo '<tr>';
643
        echo '<th class="action" colspan="4">';
644
        echo '<button type="submit" name="cmd[update]">'.$lang['btn_update'].'</button>';
645
        echo '</th>';
646
        echo '</tr>';
647
        echo '</table>';
648
        echo '</div>';
649
        echo '</div></form>'.NL;
650
    }
651
652
    /**
653
     * Returns the permission which were set for exactly the given user/group
654
     * and page/namespace. Returns null if no exact match is available
655
     *
656
     * @author Andreas Gohr <[email protected]>
657
     */
658
    function _get_exact_perm(){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
659
        global $ID;
660
        if($this->ns){
661
            if($this->ns == '*'){
662
                $check = '*';
663
            }else{
664
                $check = $this->ns.':*';
665
            }
666
        }else{
667
            $check = $ID;
668
        }
669
670
        if(isset($this->acl[$check][$this->who])){
671
            return $this->acl[$check][$this->who];
672
        }else{
673
            return null;
674
        }
675
    }
676
677
    /**
678
     * adds new acl-entry to conf/acl.auth.php
679
     *
680
     * @author  Frank Schubert <[email protected]>
681
     */
682
    function _acl_add($acl_scope, $acl_user, $acl_level){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
683
        global $config_cascade;
684
        $acl_user = auth_nameencode($acl_user,true);
685
686
        // max level for pagenames is edit
687
        if(strpos($acl_scope,'*') === false) {
688
            if($acl_level > AUTH_EDIT) $acl_level = AUTH_EDIT;
689
        }
690
691
        $new_acl = "$acl_scope\t$acl_user\t$acl_level\n";
692
693
        return io_saveFile($config_cascade['acl']['default'], $new_acl, true);
694
    }
695
696
    /**
697
     * remove acl-entry from conf/acl.auth.php
698
     *
699
     * @author  Frank Schubert <[email protected]>
700
     */
701
    function _acl_del($acl_scope, $acl_user){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
702
        global $config_cascade;
703
        $acl_user = auth_nameencode($acl_user,true);
704
705
        $acl_pattern = '^'.preg_quote($acl_scope,'/').'[ \t]+'.$acl_user.'[ \t]+[0-8].*$';
706
707
        return io_deleteFromFile($config_cascade['acl']['default'], "/$acl_pattern/", true);
708
    }
709
710
    /**
711
     * print the permission radio boxes
712
     *
713
     * @author  Frank Schubert <[email protected]>
714
     * @author  Andreas Gohr <[email protected]>
715
     */
716
    function _html_checkboxes($setperm,$ispage,$name){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
717
        global $lang;
718
719
        static $label = 0; //number labels
720
        $ret = '';
721
722
        if($ispage && $setperm > AUTH_EDIT) $setperm = AUTH_EDIT;
723
724
        foreach(array(AUTH_NONE,AUTH_READ,AUTH_EDIT,AUTH_CREATE,AUTH_UPLOAD,AUTH_DELETE) as $perm){
725
            $label += 1;
726
727
            //general checkbox attributes
728
            $atts = array( 'type'  => 'radio',
729
                           'id'    => 'pbox'.$label,
730
                           'name'  => $name,
731
                           'value' => $perm );
732
            //dynamic attributes
733
            if(!is_null($setperm) && $setperm == $perm) $atts['checked']  = 'checked';
734
            if($ispage && $perm > AUTH_EDIT){
735
                $atts['disabled'] = 'disabled';
736
                $class = ' class="disabled"';
737
            }else{
738
                $class = '';
739
            }
740
741
            //build code
742
            $ret .= '<label for="pbox'.$label.'"'.$class.'>';
743
            $ret .= '<input '.buildAttributes($atts).' />&#160;';
744
            $ret .= $this->getLang('acl_perm'.$perm);
745
            $ret .= '</label>'.NL;
746
        }
747
        return $ret;
748
    }
749
750
    /**
751
     * Print a user/group selector (reusing already used users and groups)
752
     *
753
     * @author  Andreas Gohr <[email protected]>
754
     */
755
    function _html_select(){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
756
        $inlist = false;
757
        $usel = '';
758
        $gsel = '';
759
760
        if($this->who &&
761
           !in_array($this->who,$this->usersgroups) &&
762
           !in_array($this->who,$this->specials)){
763
764
            if($this->who{0} == '@'){
765
                $gsel = ' selected="selected"';
766
            }else{
767
                $usel = ' selected="selected"';
768
            }
769
        }else{
770
            $inlist = true;
771
        }
772
773
        echo '<select name="acl_t" class="edit">'.NL;
774
        echo '  <option value="__g__" class="aclgroup"'.$gsel.'>'.$this->getLang('acl_group').'</option>'.NL;
775
        echo '  <option value="__u__"  class="acluser"'.$usel.'>'.$this->getLang('acl_user').'</option>'.NL;
776
        if (!empty($this->specials)) {
777
            echo '  <optgroup label="&#160;">'.NL;
778
            foreach($this->specials as $ug){
779
                if($ug == $this->who){
780
                    $sel    = ' selected="selected"';
781
                    $inlist = true;
782
                }else{
783
                    $sel = '';
784
                }
785
786
                if($ug{0} == '@'){
787
                        echo '  <option value="'.hsc($ug).'" class="aclgroup"'.$sel.'>'.hsc($ug).'</option>'.NL;
788
                }else{
789
                        echo '  <option value="'.hsc($ug).'" class="acluser"'.$sel.'>'.hsc($ug).'</option>'.NL;
790
                }
791
            }
792
            echo '  </optgroup>'.NL;
793
        }
794
        if (!empty($this->usersgroups)) {
795
            echo '  <optgroup label="&#160;">'.NL;
796
            foreach($this->usersgroups as $ug){
797
                if($ug == $this->who){
798
                    $sel    = ' selected="selected"';
799
                    $inlist = true;
800
                }else{
801
                    $sel = '';
802
                }
803
804
                if($ug{0} == '@'){
805
                        echo '  <option value="'.hsc($ug).'" class="aclgroup"'.$sel.'>'.hsc($ug).'</option>'.NL;
806
                }else{
807
                        echo '  <option value="'.hsc($ug).'" class="acluser"'.$sel.'>'.hsc($ug).'</option>'.NL;
808
                }
809
            }
810
            echo '  </optgroup>'.NL;
811
        }
812
        echo '</select>'.NL;
813
        return $inlist;
814
    }
815
}
816