xref: /dokuwiki/lib/plugins/acl/admin.php (revision e44b94a4bd0679ff22e14add34b60590fe7077d3)
111e2ce22Schris<?php
290fb952cSAndreas Gohr
38553d24dSAndreas Gohruse dokuwiki\Extension\AdminPlugin;
40489c64bSMoisés Braga Ribeirouse dokuwiki\Utf8\Sort;
50489c64bSMoisés Braga Ribeiro
611e2ce22Schris/**
711e2ce22Schris * ACL administration functions
811e2ce22Schris *
911e2ce22Schris * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
102a3623daSAndreas Gohr * @author     Andreas Gohr <andi@splitbrain.org>
11e965e37fSAnika Henke * @author     Anika Henke <anika@selfthinker.org> (concepts)
122a3623daSAndreas Gohr * @author     Frank Schubert <frank@schokilade.de> (old version)
1311e2ce22Schris */
14e04f1f16Schris
1511e2ce22Schris/**
1611e2ce22Schris * All DokuWiki plugins to extend the admin function
1711e2ce22Schris * need to inherit from this class
1811e2ce22Schris */
198553d24dSAndreas Gohrclass admin_plugin_acl extends AdminPlugin
20a4e3d556SAndreas Gohr{
21bff2c9d2SAndreas Gohr    public $acl;
22bff2c9d2SAndreas Gohr    protected $ns;
2340307ce6SMichael Hamann    /**
2440307ce6SMichael Hamann     * The currently selected item, associative array with id and type.
2540307ce6SMichael Hamann     * Populated from (in this order):
2640307ce6SMichael Hamann     * $_REQUEST['current_ns']
2740307ce6SMichael Hamann     * $_REQUEST['current_id']
2840307ce6SMichael Hamann     * $ns
2940307ce6SMichael Hamann     * $ID
3040307ce6SMichael Hamann     */
31bff2c9d2SAndreas Gohr    protected $current_item;
323dc2d50cSAndreas Gohr    protected $who = '';
33bff2c9d2SAndreas Gohr    protected $usersgroups = [];
34bff2c9d2SAndreas Gohr    protected $specials = [];
351d3e0272SAndreas Gohr
3611e2ce22Schris    /**
3711e2ce22Schris     * return prompt for admin menu
3811e2ce22Schris     */
39a4e3d556SAndreas Gohr    public function getMenuText($language)
40a4e3d556SAndreas Gohr    {
412a3623daSAndreas Gohr        return $this->getLang('admin_acl');
4211e2ce22Schris    }
4311e2ce22Schris
4411e2ce22Schris    /**
4511e2ce22Schris     * return sort order for position in admin menu
4611e2ce22Schris     */
47a4e3d556SAndreas Gohr    public function getMenuSort()
48a4e3d556SAndreas Gohr    {
4911e2ce22Schris        return 1;
5011e2ce22Schris    }
5111e2ce22Schris
5211e2ce22Schris    /**
5311e2ce22Schris     * handle user request
542a3623daSAndreas Gohr     *
552a3623daSAndreas Gohr     * Initializes internal vars and handles modifications
562a3623daSAndreas Gohr     *
572a3623daSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
5811e2ce22Schris     */
59a4e3d556SAndreas Gohr    public function handle()
60a4e3d556SAndreas Gohr    {
6111e2ce22Schris        global $AUTH_ACL;
622a3623daSAndreas Gohr        global $ID;
63d752aedeSAndreas Gohr        global $auth;
64c8f80b4eSAndreas Gohr        global $config_cascade;
6564273335SAndreas Gohr        global $INPUT;
6611e2ce22Schris
675d87b2ccSAndreas Gohr        // fresh 1:1 copy without replacements
68defb7d57SAnika Henke        $AUTH_ACL = file($config_cascade['acl']['default']);
695d87b2ccSAndreas Gohr
702a3623daSAndreas Gohr        // namespace given?
7164273335SAndreas Gohr        if ($INPUT->str('ns') == '*') {
722a3623daSAndreas Gohr            $this->ns = '*';
7311e2ce22Schris        } else {
7464273335SAndreas Gohr            $this->ns = cleanID($INPUT->str('ns'));
7511e2ce22Schris        }
7611e2ce22Schris
7764273335SAndreas Gohr        if ($INPUT->str('current_ns')) {
78bff2c9d2SAndreas Gohr            $this->current_item = ['id' => cleanID($INPUT->str('current_ns')), 'type' => 'd'];
7964273335SAndreas Gohr        } elseif ($INPUT->str('current_id')) {
80bff2c9d2SAndreas Gohr            $this->current_item = ['id' => cleanID($INPUT->str('current_id')), 'type' => 'f'];
8140307ce6SMichael Hamann        } elseif ($this->ns) {
82bff2c9d2SAndreas Gohr            $this->current_item = ['id' => $this->ns, 'type' => 'd'];
8340307ce6SMichael Hamann        } else {
84bff2c9d2SAndreas Gohr            $this->current_item = ['id' => $ID, 'type' => 'f'];
8540307ce6SMichael Hamann        }
8640307ce6SMichael Hamann
872a3623daSAndreas Gohr        // user or group choosen?
8864273335SAndreas Gohr        $who = trim($INPUT->str('acl_w'));
8964273335SAndreas Gohr        if ($INPUT->str('acl_t') == '__g__' && $who) {
90d752aedeSAndreas Gohr            $this->who = '@' . ltrim($auth->cleanGroup($who), '@');
9164273335SAndreas Gohr        } elseif ($INPUT->str('acl_t') == '__u__' && $who) {
9280601d26SAndreas Gohr            $this->who = ltrim($who, '@');
93b78bf706Sromain            if ($this->who != '%USER%' && $this->who != '%GROUP%') { #keep wildcard as is
9480601d26SAndreas Gohr                $this->who = $auth->cleanUser($this->who);
9580601d26SAndreas Gohr            }
967d34963bSAndreas Gohr        } elseif (
977d34963bSAndreas Gohr            $INPUT->str('acl_t') &&
9864273335SAndreas Gohr            $INPUT->str('acl_t') != '__u__' &&
997d34963bSAndreas Gohr            $INPUT->str('acl_t') != '__g__'
1007d34963bSAndreas Gohr        ) {
10164273335SAndreas Gohr            $this->who = $INPUT->str('acl_t');
1022a3623daSAndreas Gohr        } elseif ($who) {
1032a3623daSAndreas Gohr            $this->who = $who;
1042a3623daSAndreas Gohr        }
105634d7150SAndreas Gohr
1062a3623daSAndreas Gohr        // handle modifications
10764273335SAndreas Gohr        if ($INPUT->has('cmd') && checkSecurityToken()) {
10864273335SAndreas Gohr            $cmd = $INPUT->extract('cmd')->str('cmd');
109d7554c0bSAndreas Gohr
1102a3623daSAndreas Gohr            // scope for modifications
1112a3623daSAndreas Gohr            if ($this->ns) {
1122a3623daSAndreas Gohr                if ($this->ns == '*') {
1132a3623daSAndreas Gohr                    $scope = '*';
1142a3623daSAndreas Gohr                } else {
1152a3623daSAndreas Gohr                    $scope = $this->ns . ':*';
1162a3623daSAndreas Gohr                }
1172a3623daSAndreas Gohr            } else {
1182a3623daSAndreas Gohr                $scope = $ID;
1192a3623daSAndreas Gohr            }
12011e2ce22Schris
12164273335SAndreas Gohr            if ($cmd == 'save' && $scope && $this->who && $INPUT->has('acl')) {
1222a3623daSAndreas Gohr                // handle additions or single modifications
123a4e3d556SAndreas Gohr                $this->deleteACL($scope, $this->who);
12455cc5b99SAndreas Gohr                $this->addOrUpdateACL($scope, $this->who, $INPUT->int('acl'));
12564273335SAndreas Gohr            } elseif ($cmd == 'del' && $scope && $this->who) {
1262a3623daSAndreas Gohr                // handle single deletions
127a4e3d556SAndreas Gohr                $this->deleteACL($scope, $this->who);
12864273335SAndreas Gohr            } elseif ($cmd == 'update') {
12964273335SAndreas Gohr                $acl = $INPUT->arr('acl');
13064273335SAndreas Gohr
1312a3623daSAndreas Gohr                // handle update of the whole file
13264273335SAndreas Gohr                foreach ($INPUT->arr('del') as $where => $names) {
1332a3623daSAndreas Gohr                    // remove all rules marked for deletion
1347325569eSTom N Harris                    foreach ($names as $who)
13564273335SAndreas Gohr                        unset($acl[$where][$who]);
1362a3623daSAndreas Gohr                }
1372a3623daSAndreas Gohr                // prepare lines
138bff2c9d2SAndreas Gohr                $lines = [];
1392a3623daSAndreas Gohr                // keep header
1402a3623daSAndreas Gohr                foreach ($AUTH_ACL as $line) {
1415312cb0bSSyntaxseed                    if ($line[0] == '#') {
1422a3623daSAndreas Gohr                        $lines[] = $line;
1432a3623daSAndreas Gohr                    } else {
1442a3623daSAndreas Gohr                        break;
1452a3623daSAndreas Gohr                    }
1462a3623daSAndreas Gohr                }
1472a3623daSAndreas Gohr                // re-add all rules
14864273335SAndreas Gohr                foreach ($acl as $where => $opt) {
1492a3623daSAndreas Gohr                    foreach ($opt as $who => $perm) {
1504db77915SChristian Marg                        if ($who[0] == '@') {
1514db77915SChristian Marg                            if ($who != '@ALL') {
1524db77915SChristian Marg                                $who = '@' . ltrim($auth->cleanGroup($who), '@');
1534db77915SChristian Marg                            }
154b78bf706Sromain                        } elseif ($who != '%USER%' && $who != '%GROUP%') { #keep wildcard as is
1554db77915SChristian Marg                            $who = $auth->cleanUser($who);
1564db77915SChristian Marg                        }
1572a3623daSAndreas Gohr                        $who = auth_nameencode($who, true);
1582a3623daSAndreas Gohr                        $lines[] = "$where\t$who\t$perm\n";
1592a3623daSAndreas Gohr                    }
1602a3623daSAndreas Gohr                }
1612a3623daSAndreas Gohr                // save it
162bff2c9d2SAndreas Gohr                io_saveFile($config_cascade['acl']['default'], implode('', $lines));
16311e2ce22Schris            }
16411e2ce22Schris
16511e2ce22Schris            // reload ACL config
166c8f80b4eSAndreas Gohr            $AUTH_ACL = file($config_cascade['acl']['default']);
16711e2ce22Schris        }
16811e2ce22Schris
1692a3623daSAndreas Gohr        // initialize ACL array
170a4e3d556SAndreas Gohr        $this->initAclConfig();
1712a3623daSAndreas Gohr    }
1722a3623daSAndreas Gohr
17311e2ce22Schris    /**
17411e2ce22Schris     * ACL Output function
17511e2ce22Schris     *
17611e2ce22Schris     * print a table with all significant permissions for the
17711e2ce22Schris     * current id
17811e2ce22Schris     *
17911e2ce22Schris     * @author  Frank Schubert <frank@schokilade.de>
18011e2ce22Schris     * @author  Andreas Gohr <andi@splitbrain.org>
18111e2ce22Schris     */
182a4e3d556SAndreas Gohr    public function html()
183a4e3d556SAndreas Gohr    {
18490fb952cSAndreas Gohr        echo '<div id="acl_manager">';
18590fb952cSAndreas Gohr        echo '<h1>' . $this->getLang('admin_acl') . '</h1>';
18690fb952cSAndreas Gohr        echo '<div class="level1">';
18711e2ce22Schris
18890fb952cSAndreas Gohr        echo '<div id="acl__tree">';
189a4e3d556SAndreas Gohr        $this->makeExplorer();
19090fb952cSAndreas Gohr        echo '</div>';
19111e2ce22Schris
19290fb952cSAndreas Gohr        echo '<div id="acl__detail">';
193a4e3d556SAndreas Gohr        $this->printDetail();
19490fb952cSAndreas Gohr        echo '</div>';
19590fb952cSAndreas Gohr        echo '</div>';
19611e2ce22Schris
1972a3623daSAndreas Gohr        echo '<div class="clearer"></div>';
19890fb952cSAndreas Gohr        echo '<h2>' . $this->getLang('current') . '</h2>';
19990fb952cSAndreas Gohr        echo '<div class="level2">';
200a4e3d556SAndreas Gohr        $this->printAclTable();
20190fb952cSAndreas Gohr        echo '</div>';
2022a3623daSAndreas Gohr
20390fb952cSAndreas Gohr        echo '<div class="footnotes"><div class="fn">';
20490fb952cSAndreas Gohr        echo '<sup><a id="fn__1" class="fn_bot" href="#fnt__1">1)</a></sup>';
205e7f8ebf3SPhy        echo '<div class="content">' . $this->getLang('p_include') . '</div>';
2060ef43815SAndreas Gohr        echo '</div></div>';
2070ef43815SAndreas Gohr
20890fb952cSAndreas Gohr        echo '</div>';
20911e2ce22Schris    }
21011e2ce22Schris
2112a3623daSAndreas Gohr    /**
2122a3623daSAndreas Gohr     * returns array with set options for building links
2132a3623daSAndreas Gohr     *
2142a3623daSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
2152a3623daSAndreas Gohr     */
216a4e3d556SAndreas Gohr    protected function getLinkOptions($addopts = null)
217a4e3d556SAndreas Gohr    {
218bff2c9d2SAndreas Gohr        $opts = ['do' => 'admin', 'page' => 'acl'];
2192a3623daSAndreas Gohr        if ($this->ns) $opts['ns'] = $this->ns;
2202a3623daSAndreas Gohr        if ($this->who) $opts['acl_w'] = $this->who;
2212a3623daSAndreas Gohr
2222a3623daSAndreas Gohr        if (is_null($addopts)) return $opts;
2232a3623daSAndreas Gohr        return array_merge($opts, $addopts);
2242a3623daSAndreas Gohr    }
2252a3623daSAndreas Gohr
2262a3623daSAndreas Gohr    /**
2272a3623daSAndreas Gohr     * Display a tree menu to select a page or namespace
2282a3623daSAndreas Gohr     *
2292a3623daSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
2302a3623daSAndreas Gohr     */
231a4e3d556SAndreas Gohr    protected function makeExplorer()
232a4e3d556SAndreas Gohr    {
2332a3623daSAndreas Gohr        global $conf;
2342a3623daSAndreas Gohr        global $ID;
2352a3623daSAndreas Gohr        global $lang;
2362a3623daSAndreas Gohr
2372a3623daSAndreas Gohr        $ns = $this->ns;
2382a3623daSAndreas Gohr        if (empty($ns)) {
2392a3623daSAndreas Gohr            $ns = dirname(str_replace(':', '/', $ID));
2402a3623daSAndreas Gohr            if ($ns == '.') $ns = '';
2412a3623daSAndreas Gohr        } elseif ($ns == '*') {
2422a3623daSAndreas Gohr            $ns = '';
2432a3623daSAndreas Gohr        }
2442a3623daSAndreas Gohr        $ns = utf8_encodeFN(str_replace(':', '/', $ns));
2452a3623daSAndreas Gohr
246a4e3d556SAndreas Gohr        $data = $this->makeTree($ns);
2472a3623daSAndreas Gohr
2482a3623daSAndreas Gohr        // wrap a list with the root level around the other namespaces
249bff2c9d2SAndreas Gohr        array_unshift($data, [
250bff2c9d2SAndreas Gohr            'level' => 0,
251bff2c9d2SAndreas Gohr            'id' => '*',
252bff2c9d2SAndreas Gohr            'type' => 'd',
253bff2c9d2SAndreas Gohr            'open' => 'true',
254bff2c9d2SAndreas Gohr            'label' => '[' . $lang['mediaroot'] . ']'
255bff2c9d2SAndreas Gohr        ]);
2562a3623daSAndreas Gohr
257a4e3d556SAndreas Gohr        echo html_buildlist(
258a4e3d556SAndreas Gohr            $data,
259a4e3d556SAndreas Gohr            'acl',
260bff2c9d2SAndreas Gohr            [$this, 'makeTreeItem'],
261bff2c9d2SAndreas Gohr            [$this, 'makeListItem']
262a4e3d556SAndreas Gohr        );
2632a3623daSAndreas Gohr    }
2642a3623daSAndreas Gohr
2652a3623daSAndreas Gohr    /**
266a8900dc9SAndreas Gohr     * get a combined list of media and page files
267a8900dc9SAndreas Gohr     *
268a4e3d556SAndreas Gohr     * also called via AJAX
269a4e3d556SAndreas Gohr     *
270a8900dc9SAndreas Gohr     * @param string $folder an already converted filesystem folder of the current namespace
271a8900dc9SAndreas Gohr     * @param string $limit limit the search to this folder
2723dc2d50cSAndreas Gohr     * @return array
273a8900dc9SAndreas Gohr     */
274a4e3d556SAndreas Gohr    public function makeTree($folder, $limit = '')
275a4e3d556SAndreas Gohr    {
276a8900dc9SAndreas Gohr        global $conf;
277a8900dc9SAndreas Gohr
278a8900dc9SAndreas Gohr        // read tree structure from pages and media
279bff2c9d2SAndreas Gohr        $data = [];
280bff2c9d2SAndreas Gohr        search($data, $conf['datadir'], 'search_index', ['ns' => $folder], $limit);
281bff2c9d2SAndreas Gohr        $media = [];
282bff2c9d2SAndreas Gohr        search($media, $conf['mediadir'], 'search_index', ['ns' => $folder, 'nofiles' => true], $limit);
283a8900dc9SAndreas Gohr        $data = array_merge($data, $media);
284a8900dc9SAndreas Gohr        unset($media);
285a8900dc9SAndreas Gohr
286a8900dc9SAndreas Gohr        // combine by sorting and removing duplicates
287bff2c9d2SAndreas Gohr        usort($data, [$this, 'treeSort']);
288a8900dc9SAndreas Gohr        $count = count($data);
289a8900dc9SAndreas Gohr        if ($count > 0) for ($i = 1; $i < $count; $i++) {
290d072820dSChristopher Smith            if ($data[$i - 1]['id'] == $data[$i]['id'] && $data[$i - 1]['type'] == $data[$i]['type']) {
291d072820dSChristopher Smith                unset($data[$i]);
292d072820dSChristopher Smith                $i++;  // duplicate found, next $i can't be a duplicate, so skip forward one
293d072820dSChristopher Smith            }
294a8900dc9SAndreas Gohr        }
295a8900dc9SAndreas Gohr        return $data;
296a8900dc9SAndreas Gohr    }
297a8900dc9SAndreas Gohr
298a8900dc9SAndreas Gohr    /**
299a8900dc9SAndreas Gohr     * usort callback
300a8900dc9SAndreas Gohr     *
301a8900dc9SAndreas Gohr     * Sorts the combined trees of media and page files
302a8900dc9SAndreas Gohr     */
303a4e3d556SAndreas Gohr    public function treeSort($a, $b)
304a4e3d556SAndreas Gohr    {
305d74913c6SMichael Hamann        // handle the trivial cases first
306d74913c6SMichael Hamann        if ($a['id'] == '') return -1;
307d74913c6SMichael Hamann        if ($b['id'] == '') return 1;
308d74913c6SMichael Hamann        // split up the id into parts
309d74913c6SMichael Hamann        $a_ids = explode(':', $a['id']);
310d74913c6SMichael Hamann        $b_ids = explode(':', $b['id']);
311d74913c6SMichael Hamann        // now loop through the parts
312d74913c6SMichael Hamann        while (count($a_ids) && count($b_ids)) {
313d74913c6SMichael Hamann            // compare each level from upper to lower
314d74913c6SMichael Hamann            // until a non-equal component is found
3150489c64bSMoisés Braga Ribeiro            $cur_result = Sort::strcmp(array_shift($a_ids), array_shift($b_ids));
316d74913c6SMichael Hamann            if ($cur_result) {
317d74913c6SMichael Hamann                // if one of the components is the last component and is a file
318d74913c6SMichael Hamann                // and the other one is either of a deeper level or a directory,
319d74913c6SMichael Hamann                // the file has to come after the deeper level or directory
320bff2c9d2SAndreas Gohr                if ($a_ids === [] && $a['type'] == 'f' && (count($b_ids) || $b['type'] == 'd')) return 1;
321bff2c9d2SAndreas Gohr                if ($b_ids === [] && $b['type'] == 'f' && (count($a_ids) || $a['type'] == 'd')) return -1;
322d74913c6SMichael Hamann                return $cur_result;
323a8900dc9SAndreas Gohr            }
324a8900dc9SAndreas Gohr        }
325d74913c6SMichael Hamann        // The two ids seem to be equal. One of them might however refer
326d74913c6SMichael Hamann        // to a page, one to a namespace, the namespace needs to be first.
327bff2c9d2SAndreas Gohr        if ($a_ids === [] && $b_ids === []) {
328d74913c6SMichael Hamann            if ($a['type'] == $b['type']) return 0;
329d74913c6SMichael Hamann            if ($a['type'] == 'f') return 1;
330d74913c6SMichael Hamann            return -1;
331d74913c6SMichael Hamann        }
332d74913c6SMichael Hamann        // Now the empty part is either a page in the parent namespace
333d74913c6SMichael Hamann        // that obviously needs to be after the namespace
334d74913c6SMichael Hamann        // Or it is the namespace that contains the other part and should be
335d74913c6SMichael Hamann        // before that other part.
336bff2c9d2SAndreas Gohr        if ($a_ids === []) return ($a['type'] == 'd') ? -1 : 1;
337bff2c9d2SAndreas Gohr        if ($b_ids === []) return ($b['type'] == 'd') ? 1 : -1;
3383dc2d50cSAndreas Gohr        return 0; //shouldn't happen
339d74913c6SMichael Hamann    }
340a8900dc9SAndreas Gohr
341a8900dc9SAndreas Gohr    /**
3422a3623daSAndreas Gohr     * Display the current ACL for selected where/who combination with
3432a3623daSAndreas Gohr     * selectors and modification form
3442a3623daSAndreas Gohr     *
3452a3623daSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
3462a3623daSAndreas Gohr     */
347a4e3d556SAndreas Gohr    protected function printDetail()
348a4e3d556SAndreas Gohr    {
3492a3623daSAndreas Gohr        global $ID;
3502a3623daSAndreas Gohr
35190fb952cSAndreas Gohr        echo '<form action="' . wl() . '" method="post" accept-charset="utf-8"><div class="no">';
3522a3623daSAndreas Gohr
3532a3623daSAndreas Gohr        echo '<div id="acl__user">';
3542a3623daSAndreas Gohr        echo $this->getLang('acl_perms') . ' ';
355a4e3d556SAndreas Gohr        $inl = $this->makeSelect();
35690fb952cSAndreas Gohr        echo sprintf(
35790fb952cSAndreas Gohr            '<input type="text" name="acl_w" class="edit" value="%s" />',
35890fb952cSAndreas Gohr            ($inl) ? '' : hsc(ltrim($this->who, '@'))
35990fb952cSAndreas Gohr        );
36090fb952cSAndreas Gohr        echo '<button type="submit">' . $this->getLang('btn_select') . '</button>';
36190fb952cSAndreas Gohr        echo '</div>';
3622a3623daSAndreas Gohr
3632a3623daSAndreas Gohr        echo '<div id="acl__info">';
364a4e3d556SAndreas Gohr        $this->printInfo();
3652a3623daSAndreas Gohr        echo '</div>';
3662a3623daSAndreas Gohr
36790fb952cSAndreas Gohr        echo '<input type="hidden" name="ns" value="' . hsc($this->ns) . '" />';
36890fb952cSAndreas Gohr        echo '<input type="hidden" name="id" value="' . hsc($ID) . '" />';
36990fb952cSAndreas Gohr        echo '<input type="hidden" name="do" value="admin" />';
37090fb952cSAndreas Gohr        echo '<input type="hidden" name="page" value="acl" />';
37190fb952cSAndreas Gohr        echo '<input type="hidden" name="sectok" value="' . getSecurityToken() . '" />';
37290fb952cSAndreas Gohr        echo '</div></form>';
3732a3623daSAndreas Gohr    }
3742a3623daSAndreas Gohr
3752a3623daSAndreas Gohr    /**
3765381a7eeSElan Ruusamäe     * Print info and editor
377a4e3d556SAndreas Gohr     *
378a4e3d556SAndreas Gohr     * also loaded via Ajax
3792a3623daSAndreas Gohr     */
380a4e3d556SAndreas Gohr    public function printInfo()
381a4e3d556SAndreas Gohr    {
3822a3623daSAndreas Gohr        global $ID;
3832a3623daSAndreas Gohr
3842a3623daSAndreas Gohr        if ($this->who) {
385a4e3d556SAndreas Gohr            $current = $this->getExactPermisson();
3862a3623daSAndreas Gohr
3872a3623daSAndreas Gohr            // explain current permissions
388a4e3d556SAndreas Gohr            $this->printExplanation($current);
3892a3623daSAndreas Gohr            // load editor
390a4e3d556SAndreas Gohr            $this->printAclEditor($current);
3912a3623daSAndreas Gohr        } else {
3922a3623daSAndreas Gohr            echo '<p>';
3932a3623daSAndreas Gohr            if ($this->ns) {
3942a3623daSAndreas Gohr                printf($this->getLang('p_choose_ns'), hsc($this->ns));
3952a3623daSAndreas Gohr            } else {
3962a3623daSAndreas Gohr                printf($this->getLang('p_choose_id'), hsc($ID));
3972a3623daSAndreas Gohr            }
3982a3623daSAndreas Gohr            echo '</p>';
3992a3623daSAndreas Gohr
4002a3623daSAndreas Gohr            echo $this->locale_xhtml('help');
4012a3623daSAndreas Gohr        }
4022a3623daSAndreas Gohr    }
4032a3623daSAndreas Gohr
4042a3623daSAndreas Gohr    /**
4052a3623daSAndreas Gohr     * Display the ACL editor
4062a3623daSAndreas Gohr     *
4072a3623daSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
4082a3623daSAndreas Gohr     */
409a4e3d556SAndreas Gohr    protected function printAclEditor($current)
410a4e3d556SAndreas Gohr    {
4112a3623daSAndreas Gohr        global $lang;
4122a3623daSAndreas Gohr
4132a3623daSAndreas Gohr        echo '<fieldset>';
4142a3623daSAndreas Gohr        if (is_null($current)) {
4152a3623daSAndreas Gohr            echo '<legend>' . $this->getLang('acl_new') . '</legend>';
4162a3623daSAndreas Gohr        } else {
4172a3623daSAndreas Gohr            echo '<legend>' . $this->getLang('acl_mod') . '</legend>';
4182a3623daSAndreas Gohr        }
4192a3623daSAndreas Gohr
420a4e3d556SAndreas Gohr        echo $this->makeCheckboxes($current, empty($this->ns), 'acl');
4212a3623daSAndreas Gohr
4222a3623daSAndreas Gohr        if (is_null($current)) {
42390fb952cSAndreas Gohr            echo '<button type="submit" name="cmd[save]">' . $lang['btn_save'] . '</button>';
4242a3623daSAndreas Gohr        } else {
42590fb952cSAndreas Gohr            echo '<button type="submit" name="cmd[save]">' . $lang['btn_update'] . '</button>';
42690fb952cSAndreas Gohr            echo '<button type="submit" name="cmd[del]">' . $lang['btn_delete'] . '</button>';
4272a3623daSAndreas Gohr        }
4282a3623daSAndreas Gohr
4292a3623daSAndreas Gohr        echo '</fieldset>';
4302a3623daSAndreas Gohr    }
4312a3623daSAndreas Gohr
4322a3623daSAndreas Gohr    /**
4332a3623daSAndreas Gohr     * Explain the currently set permissions in plain english/$lang
4342a3623daSAndreas Gohr     *
4352a3623daSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
4362a3623daSAndreas Gohr     */
437a4e3d556SAndreas Gohr    protected function printExplanation($current)
438a4e3d556SAndreas Gohr    {
4392a3623daSAndreas Gohr        global $ID;
4402a3623daSAndreas Gohr        global $auth;
4412a3623daSAndreas Gohr
4422a3623daSAndreas Gohr        $who = $this->who;
4432a3623daSAndreas Gohr        $ns = $this->ns;
4442a3623daSAndreas Gohr
4452a3623daSAndreas Gohr        // prepare where to check
4462a3623daSAndreas Gohr        if ($ns) {
4472a3623daSAndreas Gohr            if ($ns == '*') {
4482a3623daSAndreas Gohr                $check = '*';
4492a3623daSAndreas Gohr            } else {
4502a3623daSAndreas Gohr                $check = $ns . ':*';
4512a3623daSAndreas Gohr            }
4522a3623daSAndreas Gohr        } else {
4532a3623daSAndreas Gohr            $check = $ID;
4542a3623daSAndreas Gohr        }
4552a3623daSAndreas Gohr
4562a3623daSAndreas Gohr        // prepare who to check
4575312cb0bSSyntaxseed        if ($who[0] == '@') {
4582a3623daSAndreas Gohr            $user = '';
459bff2c9d2SAndreas Gohr            $groups = [ltrim($who, '@')];
4602a3623daSAndreas Gohr        } else {
461116065d2SAndreas Gohr            $user = $who;
4622a3623daSAndreas Gohr            $info = $auth->getUserData($user);
463c1791678SAndreas Gohr            if ($info === false) {
464bff2c9d2SAndreas Gohr                $groups = [];
465c1791678SAndreas Gohr            } else {
46678750b94SAndreas Gohr                $groups = $info['grps'];
4672a3623daSAndreas Gohr            }
468c1791678SAndreas Gohr        }
4692a3623daSAndreas Gohr
4702a3623daSAndreas Gohr        // check the permissions
4712a3623daSAndreas Gohr        $perm = auth_aclcheck($check, $user, $groups);
4722a3623daSAndreas Gohr
4732a3623daSAndreas Gohr        // build array of named permissions
474bff2c9d2SAndreas Gohr        $names = [];
4752a3623daSAndreas Gohr        if ($perm) {
4762a3623daSAndreas Gohr            if ($ns) {
4772a3623daSAndreas Gohr                if ($perm >= AUTH_DELETE) $names[] = $this->getLang('acl_perm16');
4782a3623daSAndreas Gohr                if ($perm >= AUTH_UPLOAD) $names[] = $this->getLang('acl_perm8');
4792a3623daSAndreas Gohr                if ($perm >= AUTH_CREATE) $names[] = $this->getLang('acl_perm4');
4802a3623daSAndreas Gohr            }
4812a3623daSAndreas Gohr            if ($perm >= AUTH_EDIT) $names[] = $this->getLang('acl_perm2');
4822a3623daSAndreas Gohr            if ($perm >= AUTH_READ) $names[] = $this->getLang('acl_perm1');
4832a3623daSAndreas Gohr            $names = array_reverse($names);
4842a3623daSAndreas Gohr        } else {
4852a3623daSAndreas Gohr            $names[] = $this->getLang('acl_perm0');
4862a3623daSAndreas Gohr        }
4872a3623daSAndreas Gohr
4882a3623daSAndreas Gohr        // print permission explanation
4892a3623daSAndreas Gohr        echo '<p>';
4902a3623daSAndreas Gohr        if ($user) {
4912a3623daSAndreas Gohr            if ($ns) {
492bff2c9d2SAndreas Gohr                printf($this->getLang('p_user_ns'), hsc($who), hsc($ns), implode(', ', $names));
4932a3623daSAndreas Gohr            } else {
494bff2c9d2SAndreas Gohr                printf($this->getLang('p_user_id'), hsc($who), hsc($ID), implode(', ', $names));
4952a3623daSAndreas Gohr            }
496bff2c9d2SAndreas Gohr        } elseif ($ns) {
497bff2c9d2SAndreas Gohr            printf($this->getLang('p_group_ns'), hsc(ltrim($who, '@')), hsc($ns), implode(', ', $names));
4982a3623daSAndreas Gohr        } else {
499bff2c9d2SAndreas Gohr            printf($this->getLang('p_group_id'), hsc(ltrim($who, '@')), hsc($ID), implode(', ', $names));
5002a3623daSAndreas Gohr        }
5012a3623daSAndreas Gohr        echo '</p>';
5022a3623daSAndreas Gohr
5032a3623daSAndreas Gohr        // add note if admin
5042a3623daSAndreas Gohr        if ($perm == AUTH_ADMIN) {
5052a3623daSAndreas Gohr            echo '<p>' . $this->getLang('p_isadmin') . '</p>';
5062a3623daSAndreas Gohr        } elseif (is_null($current)) {
5072a3623daSAndreas Gohr            echo '<p>' . $this->getLang('p_inherited') . '</p>';
5082a3623daSAndreas Gohr        }
50911e2ce22Schris    }
51011e2ce22Schris
51111e2ce22Schris
51211e2ce22Schris    /**
5132a3623daSAndreas Gohr     * Item formatter for the tree view
51411e2ce22Schris     *
5152a3623daSAndreas Gohr     * User function for html_buildlist()
51611e2ce22Schris     *
5172a3623daSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
51811e2ce22Schris     */
5197ecc081fSAndreas Gohr    public function makeTreeItem($item)
520a4e3d556SAndreas Gohr    {
5212a3623daSAndreas Gohr        $ret = '';
5222a3623daSAndreas Gohr        // what to display
5230e80bb5eSChristopher Smith        if (!empty($item['label'])) {
5242a3623daSAndreas Gohr            $base = $item['label'];
5252a3623daSAndreas Gohr        } else {
5262a3623daSAndreas Gohr            $base = ':' . $item['id'];
5272a3623daSAndreas Gohr            $base = substr($base, strrpos($base, ':') + 1);
5282a3623daSAndreas Gohr        }
5292a3623daSAndreas Gohr
5302a3623daSAndreas Gohr        // highlight?
531d072820dSChristopher Smith        if (($item['type'] == $this->current_item['type'] && $item['id'] == $this->current_item['id'])) {
53240307ce6SMichael Hamann            $cl = ' cur';
533d072820dSChristopher Smith        } else {
534d072820dSChristopher Smith            $cl = '';
535d072820dSChristopher Smith        }
5362a3623daSAndreas Gohr
5372a3623daSAndreas Gohr        // namespace or page?
5382a3623daSAndreas Gohr        if ($item['type'] == 'd') {
5392a3623daSAndreas Gohr            if ($item['open']) {
540*e44b94a4SAndreas Gohr                $img = DOKU_BASE . 'lib/images/minus.gif';
541e260f93bSAnika Henke                $alt = '−';
5422a3623daSAndreas Gohr            } else {
543*e44b94a4SAndreas Gohr                $img = DOKU_BASE . 'lib/images/plus.gif';
5442a3623daSAndreas Gohr                $alt = '+';
5452a3623daSAndreas Gohr            }
5462a3623daSAndreas Gohr            $ret .= '<img src="' . $img . '" alt="' . $alt . '" />';
54764159a61SAndreas Gohr            $ret .= '<a href="' .
548bff2c9d2SAndreas Gohr                wl('', $this->getLinkOptions(['ns' => $item['id'], 'sectok' => getSecurityToken()])) .
54964159a61SAndreas Gohr                '" class="idx_dir' . $cl . '">';
5502a3623daSAndreas Gohr            $ret .= $base;
5512a3623daSAndreas Gohr            $ret .= '</a>';
5522a3623daSAndreas Gohr        } else {
55364159a61SAndreas Gohr            $ret .= '<a href="' .
554bff2c9d2SAndreas Gohr                wl('', $this->getLinkOptions(['id' => $item['id'], 'ns' => '', 'sectok' => getSecurityToken()])) .
55564159a61SAndreas Gohr                '" class="wikilink1' . $cl . '">';
5562a3623daSAndreas Gohr            $ret .= noNS($item['id']);
5572a3623daSAndreas Gohr            $ret .= '</a>';
5582a3623daSAndreas Gohr        }
5592a3623daSAndreas Gohr        return $ret;
5602a3623daSAndreas Gohr    }
5612a3623daSAndreas Gohr
5623dc2d50cSAndreas Gohr    /**
5633dc2d50cSAndreas Gohr     * List Item formatter
5643dc2d50cSAndreas Gohr     *
5653dc2d50cSAndreas Gohr     * @param array $item
5663dc2d50cSAndreas Gohr     * @return string
5673dc2d50cSAndreas Gohr     */
568a4e3d556SAndreas Gohr    public function makeListItem($item)
569a4e3d556SAndreas Gohr    {
5702b580f7aSAdrian Lang        return '<li class="level' . $item['level'] . ' ' .
5712b580f7aSAdrian Lang            ($item['open'] ? 'open' : 'closed') . '">';
5722a3623daSAndreas Gohr    }
5732a3623daSAndreas Gohr
5742a3623daSAndreas Gohr
5752a3623daSAndreas Gohr    /**
5762a3623daSAndreas Gohr     * Get current ACL settings as multidim array
5772a3623daSAndreas Gohr     *
5782a3623daSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
5792a3623daSAndreas Gohr     */
580a4e3d556SAndreas Gohr    public function initAclConfig()
581a4e3d556SAndreas Gohr    {
58211e2ce22Schris        global $AUTH_ACL;
5832a3623daSAndreas Gohr        global $conf;
584bff2c9d2SAndreas Gohr        $acl_config = [];
585bff2c9d2SAndreas Gohr        $usersgroups = [];
58611e2ce22Schris
58715976576SAndreas Gohr        // get special users and groups
58815976576SAndreas Gohr        $this->specials[] = '@ALL';
58915976576SAndreas Gohr        $this->specials[] = '@' . $conf['defaultgroup'];
59015976576SAndreas Gohr        if ($conf['manager'] != '!!not set!!') {
591a4e3d556SAndreas Gohr            $this->specials = array_merge(
592a4e3d556SAndreas Gohr                $this->specials,
593a4e3d556SAndreas Gohr                array_map(
594a4e3d556SAndreas Gohr                    'trim',
595a4e3d556SAndreas Gohr                    explode(',', $conf['manager'])
596a4e3d556SAndreas Gohr                )
597a4e3d556SAndreas Gohr            );
59815976576SAndreas Gohr        }
59915976576SAndreas Gohr        $this->specials = array_filter($this->specials);
60015976576SAndreas Gohr        $this->specials = array_unique($this->specials);
6010489c64bSMoisés Braga Ribeiro        Sort::sort($this->specials);
60215976576SAndreas Gohr
6032a3623daSAndreas Gohr        foreach ($AUTH_ACL as $line) {
6042a3623daSAndreas Gohr            $line = trim(preg_replace('/#.*$/', '', $line)); //ignore comments
6052a3623daSAndreas Gohr            if (!$line) continue;
6062a3623daSAndreas Gohr
60721c3090aSChristopher Smith            $acl = preg_split('/[ \t]+/', $line);
60811e2ce22Schris            //0 is pagename, 1 is user, 2 is acl
6092a3623daSAndreas Gohr
6102a3623daSAndreas Gohr            $acl[1] = rawurldecode($acl[1]);
6112a3623daSAndreas Gohr            $acl_config[$acl[0]][$acl[1]] = $acl[2];
6122a3623daSAndreas Gohr
6132a3623daSAndreas Gohr            // store non-special users and groups for later selection dialog
6142a3623daSAndreas Gohr            $ug = $acl[1];
61515976576SAndreas Gohr            if (in_array($ug, $this->specials)) continue;
6162a3623daSAndreas Gohr            $usersgroups[] = $ug;
6172a3623daSAndreas Gohr        }
6182a3623daSAndreas Gohr
6192a3623daSAndreas Gohr        $usersgroups = array_unique($usersgroups);
6200489c64bSMoisés Braga Ribeiro        Sort::sort($usersgroups);
6210489c64bSMoisés Braga Ribeiro        Sort::ksort($acl_config);
6220489c64bSMoisés Braga Ribeiro        foreach (array_keys($acl_config) as $pagename) {
6230489c64bSMoisés Braga Ribeiro            Sort::ksort($acl_config[$pagename]);
6240489c64bSMoisés Braga Ribeiro        }
6252a3623daSAndreas Gohr
6262a3623daSAndreas Gohr        $this->acl = $acl_config;
6272a3623daSAndreas Gohr        $this->usersgroups = $usersgroups;
6282a3623daSAndreas Gohr    }
6292a3623daSAndreas Gohr
6302a3623daSAndreas Gohr    /**
6312a3623daSAndreas Gohr     * Display all currently set permissions in a table
6322a3623daSAndreas Gohr     *
6332a3623daSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
6342a3623daSAndreas Gohr     */
635a4e3d556SAndreas Gohr    protected function printAclTable()
636a4e3d556SAndreas Gohr    {
6372a3623daSAndreas Gohr        global $lang;
6382a3623daSAndreas Gohr        global $ID;
6392a3623daSAndreas Gohr
64090fb952cSAndreas Gohr        echo '<form action="' . wl() . '" method="post" accept-charset="utf-8"><div class="no">';
6412a3623daSAndreas Gohr        if ($this->ns) {
64290fb952cSAndreas Gohr            echo '<input type="hidden" name="ns" value="' . hsc($this->ns) . '" />';
6432a3623daSAndreas Gohr        } else {
64490fb952cSAndreas Gohr            echo '<input type="hidden" name="id" value="' . hsc($ID) . '" />';
64511e2ce22Schris        }
64690fb952cSAndreas Gohr        echo '<input type="hidden" name="acl_w" value="' . hsc($this->who) . '" />';
64790fb952cSAndreas Gohr        echo '<input type="hidden" name="do" value="admin" />';
64890fb952cSAndreas Gohr        echo '<input type="hidden" name="page" value="acl" />';
64990fb952cSAndreas Gohr        echo '<input type="hidden" name="sectok" value="' . getSecurityToken() . '" />';
650c7b28ffdSAnika Henke        echo '<div class="table">';
6512a3623daSAndreas Gohr        echo '<table class="inline">';
6522a3623daSAndreas Gohr        echo '<tr>';
6532a3623daSAndreas Gohr        echo '<th>' . $this->getLang('where') . '</th>';
6542a3623daSAndreas Gohr        echo '<th>' . $this->getLang('who') . '</th>';
65563e967bdSAnika Henke        echo '<th>' . $this->getLang('perm') . '<sup><a id="fnt__1" class="fn_top" href="#fn__1">1)</a></sup></th>';
6562a3623daSAndreas Gohr        echo '<th>' . $lang['btn_delete'] . '</th>';
6572a3623daSAndreas Gohr        echo '</tr>';
6582a3623daSAndreas Gohr        foreach ($this->acl as $where => $set) {
6592a3623daSAndreas Gohr            foreach ($set as $who => $perm) {
6602a3623daSAndreas Gohr                echo '<tr>';
6612a3623daSAndreas Gohr                echo '<td>';
6621b2deed9Sfiwswe                if (str_ends_with($where, '*')) {
6632a3623daSAndreas Gohr                    echo '<span class="aclns">' . hsc($where) . '</span>';
6642a3623daSAndreas Gohr                    $ispage = false;
6652a3623daSAndreas Gohr                } else {
6662a3623daSAndreas Gohr                    echo '<span class="aclpage">' . hsc($where) . '</span>';
6672a3623daSAndreas Gohr                    $ispage = true;
6682a3623daSAndreas Gohr                }
6692a3623daSAndreas Gohr                echo '</td>';
6702a3623daSAndreas Gohr
6712a3623daSAndreas Gohr                echo '<td>';
6725312cb0bSSyntaxseed                if ($who[0] == '@') {
6732a3623daSAndreas Gohr                    echo '<span class="aclgroup">' . hsc($who) . '</span>';
6742a3623daSAndreas Gohr                } else {
6752a3623daSAndreas Gohr                    echo '<span class="acluser">' . hsc($who) . '</span>';
6762a3623daSAndreas Gohr                }
6772a3623daSAndreas Gohr                echo '</td>';
6782a3623daSAndreas Gohr
6792a3623daSAndreas Gohr                echo '<td>';
680a4e3d556SAndreas Gohr                echo $this->makeCheckboxes($perm, $ispage, 'acl[' . $where . '][' . $who . ']');
6812a3623daSAndreas Gohr                echo '</td>';
6822a3623daSAndreas Gohr
68363e967bdSAnika Henke                echo '<td class="check">';
6847325569eSTom N Harris                echo '<input type="checkbox" name="del[' . hsc($where) . '][]" value="' . hsc($who) . '" />';
6852a3623daSAndreas Gohr                echo '</td>';
6862a3623daSAndreas Gohr                echo '</tr>';
68711e2ce22Schris            }
68811e2ce22Schris        }
68911e2ce22Schris
6902a3623daSAndreas Gohr        echo '<tr>';
69163e967bdSAnika Henke        echo '<th class="action" colspan="4">';
692ae614416SAnika Henke        echo '<button type="submit" name="cmd[update]">' . $lang['btn_update'] . '</button>';
6932a3623daSAndreas Gohr        echo '</th>';
6942a3623daSAndreas Gohr        echo '</tr>';
6952a3623daSAndreas Gohr        echo '</table>';
696c7b28ffdSAnika Henke        echo '</div>';
69790fb952cSAndreas Gohr        echo '</div></form>';
69811e2ce22Schris    }
69911e2ce22Schris
7002a3623daSAndreas Gohr    /**
7012a3623daSAndreas Gohr     * Returns the permission which were set for exactly the given user/group
7022a3623daSAndreas Gohr     * and page/namespace. Returns null if no exact match is available
7032a3623daSAndreas Gohr     *
7042a3623daSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
7052a3623daSAndreas Gohr     */
706a4e3d556SAndreas Gohr    protected function getExactPermisson()
707a4e3d556SAndreas Gohr    {
7082a3623daSAndreas Gohr        global $ID;
7092a3623daSAndreas Gohr        if ($this->ns) {
7102a3623daSAndreas Gohr            if ($this->ns == '*') {
7112a3623daSAndreas Gohr                $check = '*';
7122a3623daSAndreas Gohr            } else {
7132a3623daSAndreas Gohr                $check = $this->ns . ':*';
7142a3623daSAndreas Gohr            }
7152a3623daSAndreas Gohr        } else {
7162a3623daSAndreas Gohr            $check = $ID;
71711e2ce22Schris        }
71811e2ce22Schris
7193bde27bfSAndreas Gohr        if (isset($this->acl[$check][$this->who])) {
7203bde27bfSAndreas Gohr            return $this->acl[$check][$this->who];
7212a3623daSAndreas Gohr        } else {
7222a3623daSAndreas Gohr            return null;
7232a3623daSAndreas Gohr        }
7242a3623daSAndreas Gohr    }
72511e2ce22Schris
72611e2ce22Schris    /**
72711e2ce22Schris     * adds new acl-entry to conf/acl.auth.php
72811e2ce22Schris     *
72911e2ce22Schris     * @author  Frank Schubert <frank@schokilade.de>
73011e2ce22Schris     */
73155cc5b99SAndreas Gohr    public function addOrUpdateACL($acl_scope, $acl_user, $acl_level)
732a4e3d556SAndreas Gohr    {
733c8f80b4eSAndreas Gohr        global $config_cascade;
7343f1e0037SGuillaume Turri
73555cc5b99SAndreas Gohr        // first make sure we won't end up with 2 lines matching this user and scope. See issue #1115
73655cc5b99SAndreas Gohr        $this->deleteACL($acl_scope, $acl_user);
7372a3623daSAndreas Gohr        $acl_user = auth_nameencode($acl_user, true);
73811e2ce22Schris
73911e2ce22Schris        // max level for pagenames is edit
74011e2ce22Schris        if (strpos($acl_scope, '*') === false) {
74111e2ce22Schris            if ($acl_level > AUTH_EDIT) $acl_level = AUTH_EDIT;
74211e2ce22Schris        }
74311e2ce22Schris
74411e2ce22Schris        $new_acl = "$acl_scope\t$acl_user\t$acl_level\n";
74511e2ce22Schris
7462b71c2eeSPatrick Brown        return io_saveFile($config_cascade['acl']['default'], $new_acl, true);
74711e2ce22Schris    }
74811e2ce22Schris
74911e2ce22Schris    /**
75011e2ce22Schris     * remove acl-entry from conf/acl.auth.php
75111e2ce22Schris     *
75211e2ce22Schris     * @author  Frank Schubert <frank@schokilade.de>
75311e2ce22Schris     */
754a4e3d556SAndreas Gohr    public function deleteACL($acl_scope, $acl_user)
755a4e3d556SAndreas Gohr    {
756c8f80b4eSAndreas Gohr        global $config_cascade;
7572a3623daSAndreas Gohr        $acl_user = auth_nameencode($acl_user, true);
75811e2ce22Schris
75921c3090aSChristopher Smith        $acl_pattern = '^' . preg_quote($acl_scope, '/') . '[ \t]+' . $acl_user . '[ \t]+[0-8].*$';
76011e2ce22Schris
761699e3c49SPatrick Brown        return io_deleteFromFile($config_cascade['acl']['default'], "/$acl_pattern/", true);
76211e2ce22Schris    }
76311e2ce22Schris
76411e2ce22Schris    /**
7652a3623daSAndreas Gohr     * print the permission radio boxes
76611e2ce22Schris     *
76711e2ce22Schris     * @author  Frank Schubert <frank@schokilade.de>
76811e2ce22Schris     * @author  Andreas Gohr <andi@splitbrain.org>
76911e2ce22Schris     */
770a4e3d556SAndreas Gohr    protected function makeCheckboxes($setperm, $ispage, $name)
771a4e3d556SAndreas Gohr    {
77211e2ce22Schris        global $lang;
77311e2ce22Schris
77411e2ce22Schris        static $label = 0; //number labels
77511e2ce22Schris        $ret = '';
77611e2ce22Schris
777041a602dSChristopher Smith        if ($ispage && $setperm > AUTH_EDIT) $setperm = AUTH_EDIT;
7782a3623daSAndreas Gohr
779bff2c9d2SAndreas Gohr        foreach ([AUTH_NONE, AUTH_READ, AUTH_EDIT, AUTH_CREATE, AUTH_UPLOAD, AUTH_DELETE] as $perm) {
780bff2c9d2SAndreas Gohr            ++$label;
78111e2ce22Schris
78211e2ce22Schris            //general checkbox attributes
783bff2c9d2SAndreas Gohr            $atts = [
784bff2c9d2SAndreas Gohr                'type' => 'radio',
78511e2ce22Schris                'id' => 'pbox' . $label,
7862a3623daSAndreas Gohr                'name' => $name,
787bff2c9d2SAndreas Gohr                'value' => $perm
788bff2c9d2SAndreas Gohr            ];
78911e2ce22Schris            //dynamic attributes
7902a3623daSAndreas Gohr            if (!is_null($setperm) && $setperm == $perm) $atts['checked'] = 'checked';
7912a3623daSAndreas Gohr            if ($ispage && $perm > AUTH_EDIT) {
7922a3623daSAndreas Gohr                $atts['disabled'] = 'disabled';
7932a3623daSAndreas Gohr                $class = ' class="disabled"';
7942a3623daSAndreas Gohr            } else {
7952a3623daSAndreas Gohr                $class = '';
7962a3623daSAndreas Gohr            }
79711e2ce22Schris
79811e2ce22Schris            //build code
79963e967bdSAnika Henke            $ret .= '<label for="pbox' . $label . '"' . $class . '>';
800e260f93bSAnika Henke            $ret .= '<input ' . buildAttributes($atts) . ' />&#160;';
8012a3623daSAndreas Gohr            $ret .= $this->getLang('acl_perm' . $perm);
80290fb952cSAndreas Gohr            $ret .= '</label>';
80311e2ce22Schris        }
80411e2ce22Schris        return $ret;
80511e2ce22Schris    }
80611e2ce22Schris
8072a3623daSAndreas Gohr    /**
8082a3623daSAndreas Gohr     * Print a user/group selector (reusing already used users and groups)
8092a3623daSAndreas Gohr     *
8102a3623daSAndreas Gohr     * @author  Andreas Gohr <andi@splitbrain.org>
8112a3623daSAndreas Gohr     */
812a4e3d556SAndreas Gohr    protected function makeSelect()
813a4e3d556SAndreas Gohr    {
8142a3623daSAndreas Gohr        $inlist = false;
81559bc3b48SGerrit Uitslag        $usel = '';
81659bc3b48SGerrit Uitslag        $gsel = '';
8172a3623daSAndreas Gohr
8187d34963bSAndreas Gohr        if (
8197d34963bSAndreas Gohr            $this->who &&
8202a3623daSAndreas Gohr            !in_array($this->who, $this->usersgroups) &&
8217d34963bSAndreas Gohr            !in_array($this->who, $this->specials)
8227d34963bSAndreas Gohr        ) {
8235312cb0bSSyntaxseed            if ($this->who[0] == '@') {
8242a3623daSAndreas Gohr                $gsel = ' selected="selected"';
8252a3623daSAndreas Gohr            } else {
8262a3623daSAndreas Gohr                $usel = ' selected="selected"';
8272a3623daSAndreas Gohr            }
8282a3623daSAndreas Gohr        } else {
8292a3623daSAndreas Gohr            $inlist = true;
8302a3623daSAndreas Gohr        }
8312a3623daSAndreas Gohr
83290fb952cSAndreas Gohr        echo '<select name="acl_t" class="edit">';
83390fb952cSAndreas Gohr        echo '  <option value="__g__" class="aclgroup"' . $gsel . '>' . $this->getLang('acl_group') . '</option>';
83490fb952cSAndreas Gohr        echo '  <option value="__u__"  class="acluser"' . $usel . '>' . $this->getLang('acl_user') . '</option>';
835ecd7c1d6SAnika Henke        if (!empty($this->specials)) {
83690fb952cSAndreas Gohr            echo '  <optgroup label="&#160;">';
83715976576SAndreas Gohr            foreach ($this->specials as $ug) {
8382a3623daSAndreas Gohr                if ($ug == $this->who) {
8392a3623daSAndreas Gohr                    $sel = ' selected="selected"';
8402a3623daSAndreas Gohr                    $inlist = true;
8412a3623daSAndreas Gohr                } else {
8422a3623daSAndreas Gohr                    $sel = '';
8432a3623daSAndreas Gohr                }
8442a3623daSAndreas Gohr
8455312cb0bSSyntaxseed                if ($ug[0] == '@') {
84690fb952cSAndreas Gohr                    echo '  <option value="' . hsc($ug) . '" class="aclgroup"' . $sel . '>' . hsc($ug) . '</option>';
8472a3623daSAndreas Gohr                } else {
84890fb952cSAndreas Gohr                    echo '  <option value="' . hsc($ug) . '" class="acluser"' . $sel . '>' . hsc($ug) . '</option>';
8492a3623daSAndreas Gohr                }
8502a3623daSAndreas Gohr            }
85190fb952cSAndreas Gohr            echo '  </optgroup>';
852ecd7c1d6SAnika Henke        }
853ecd7c1d6SAnika Henke        if (!empty($this->usersgroups)) {
85490fb952cSAndreas Gohr            echo '  <optgroup label="&#160;">';
8552a3623daSAndreas Gohr            foreach ($this->usersgroups as $ug) {
8562a3623daSAndreas Gohr                if ($ug == $this->who) {
8572a3623daSAndreas Gohr                    $sel = ' selected="selected"';
8582a3623daSAndreas Gohr                    $inlist = true;
8592a3623daSAndreas Gohr                } else {
8602a3623daSAndreas Gohr                    $sel = '';
8612a3623daSAndreas Gohr                }
8622a3623daSAndreas Gohr
8635312cb0bSSyntaxseed                if ($ug[0] == '@') {
86490fb952cSAndreas Gohr                    echo '  <option value="' . hsc($ug) . '" class="aclgroup"' . $sel . '>' . hsc($ug) . '</option>';
8652a3623daSAndreas Gohr                } else {
86690fb952cSAndreas Gohr                    echo '  <option value="' . hsc($ug) . '" class="acluser"' . $sel . '>' . hsc($ug) . '</option>';
8672a3623daSAndreas Gohr                }
8682a3623daSAndreas Gohr            }
86990fb952cSAndreas Gohr            echo '  </optgroup>';
870ecd7c1d6SAnika Henke        }
87190fb952cSAndreas Gohr        echo '</select>';
8722a3623daSAndreas Gohr        return $inlist;
8732a3623daSAndreas Gohr    }
87411e2ce22Schris}
875