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