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