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