111e2ce22Schris<?php 211e2ce22Schris/** 311e2ce22Schris * ACL administration functions 411e2ce22Schris * 511e2ce22Schris * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 611e2ce22Schris * @author Frank Schubert <frank@schokilade.de> 711e2ce22Schris */ 8e04f1f16Schris// must be run within Dokuwiki 9e04f1f16Schrisif(!defined('DOKU_INC')) die(); 10e04f1f16Schris 1111e2ce22Schrisif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 1211e2ce22Schrisrequire_once(DOKU_PLUGIN.'admin.php'); 1311e2ce22Schris 1411e2ce22Schris/** 1511e2ce22Schris * All DokuWiki plugins to extend the admin function 1611e2ce22Schris * need to inherit from this class 1711e2ce22Schris */ 1811e2ce22Schrisclass admin_plugin_acl extends DokuWiki_Admin_Plugin { 1911e2ce22Schris 201d3e0272SAndreas Gohr 211d3e0272SAndreas Gohr function admin_plugin_acl(){ 221d3e0272SAndreas Gohr $this->setupLocale(); 231d3e0272SAndreas Gohr } 241d3e0272SAndreas Gohr 251d3e0272SAndreas Gohr 261d3e0272SAndreas Gohr 2711e2ce22Schris /** 2811e2ce22Schris * return some info 2911e2ce22Schris */ 3011e2ce22Schris function getInfo(){ 3111e2ce22Schris return array( 3211e2ce22Schris 'author' => 'Frank Schubert', 3311e2ce22Schris 'email' => 'frank@schokilade.de', 3411e2ce22Schris 'date' => '2005-08-08', 3511e2ce22Schris 'name' => 'ACL', 3611e2ce22Schris 'desc' => 'Manage Page Access Control Lists', 3711e2ce22Schris 'url' => 'http://wiki.splitbrain.org/wiki:acl', 3811e2ce22Schris ); 3911e2ce22Schris } 4011e2ce22Schris 4111e2ce22Schris /** 4211e2ce22Schris * return prompt for admin menu 4311e2ce22Schris */ 4411e2ce22Schris function getMenuText($language) { 451d3e0272SAndreas Gohr return $this->lang['admin_acl']; 4611e2ce22Schris } 4711e2ce22Schris 4811e2ce22Schris /** 4911e2ce22Schris * return sort order for position in admin menu 5011e2ce22Schris */ 5111e2ce22Schris function getMenuSort() { 5211e2ce22Schris return 1; 5311e2ce22Schris } 5411e2ce22Schris 5511e2ce22Schris /** 5611e2ce22Schris * handle user request 5711e2ce22Schris */ 5811e2ce22Schris function handle() { 5911e2ce22Schris global $AUTH_ACL; 6011e2ce22Schris 6111e2ce22Schris $cmd = $_REQUEST['acl_cmd']; 6211e2ce22Schris $scope = $_REQUEST['acl_scope']; 6311e2ce22Schris $type = $_REQUEST['acl_type']; 6411e2ce22Schris $user = $_REQUEST['acl_user']; 6511e2ce22Schris $perm = $_REQUEST['acl_perm']; 6611e2ce22Schris 6711e2ce22Schris if(is_array($perm)){ 6811e2ce22Schris //use the maximum 6911e2ce22Schris sort($perm); 7011e2ce22Schris $perm = array_pop($perm); 7111e2ce22Schris }else{ 7211e2ce22Schris $perm = 0; 7311e2ce22Schris } 7411e2ce22Schris 7511e2ce22Schris //sanitize 766c2bb100SAndreas Gohr $user = auth_nameencode($user); 7711e2ce22Schris if($type == '@') $user = '@'.$user; 7811e2ce22Schris if($user == '@all') $user = '@ALL'; //special group! (now case insensitive) 7911e2ce22Schris $perm = (int) $perm; 8011e2ce22Schris if($perm > AUTH_DELETE) $perm = AUTH_DELETE; 81*634d7150SAndreas Gohr 82*634d7150SAndreas Gohr // check token 83*634d7150SAndreas Gohr if(!checkSecurityToken()) return; 8411e2ce22Schris 8511e2ce22Schris //nothing to do? 8611e2ce22Schris if(empty($cmd) || empty($scope) || empty($user)) return; 8711e2ce22Schris 8811e2ce22Schris 8911e2ce22Schris if($cmd == 'save'){ 9011e2ce22Schris $this->admin_acl_del($scope, $user); 9111e2ce22Schris $this->admin_acl_add($scope, $user, $perm); 9211e2ce22Schris }elseif($cmd == 'delete'){ 9311e2ce22Schris $this->admin_acl_del($scope, $user); 9411e2ce22Schris } 9511e2ce22Schris 9611e2ce22Schris // reload ACL config 9711e2ce22Schris $AUTH_ACL = file(DOKU_CONF.'acl.auth.php'); 9811e2ce22Schris } 9911e2ce22Schris 10011e2ce22Schris /** 10111e2ce22Schris * ACL Output function 10211e2ce22Schris * 10311e2ce22Schris * print a table with all significant permissions for the 10411e2ce22Schris * current id 10511e2ce22Schris * 10611e2ce22Schris * @author Frank Schubert <frank@schokilade.de> 10711e2ce22Schris * @author Andreas Gohr <andi@splitbrain.org> 10811e2ce22Schris */ 10911e2ce22Schris function html() { 11011e2ce22Schris global $ID; 11111e2ce22Schris 1121d3e0272SAndreas Gohr print $this->locale_xhtml('intro'); 11311e2ce22Schris 11458dde80dSAnika Henke ptln('<div id="acl__manager">'); 11511e2ce22Schris ptln('<table class="inline">'); 11611e2ce22Schris 11711e2ce22Schris //new 11811e2ce22Schris $this->admin_acl_html_new(); 11911e2ce22Schris 12011e2ce22Schris //current config 12111e2ce22Schris $acls = $this->get_acl_config($ID); 12211e2ce22Schris foreach ($acls as $id => $acl){ 12311e2ce22Schris $this->admin_acl_html_current($id,$acl); 12411e2ce22Schris } 12511e2ce22Schris 12611e2ce22Schris ptln('</table>'); 12711e2ce22Schris ptln('</div>'); 12811e2ce22Schris } 12911e2ce22Schris 13011e2ce22Schris 13111e2ce22Schris /** 13211e2ce22Schris * Get matching ACL lines for a page 13311e2ce22Schris * 13411e2ce22Schris * $ID is pagename, reads matching lines from $AUTH_ACL, 13511e2ce22Schris * also reads acls from namespace 13611e2ce22Schris * returns multi-array with key=pagename and value=array(user, acl) 13711e2ce22Schris * 13811e2ce22Schris * @todo Fix comment to make sense 13911e2ce22Schris * @todo should this moved to auth.php? 14011e2ce22Schris * @todo can this be combined with auth_aclcheck to avoid duplicate code? 14111e2ce22Schris * @author Frank Schubert <frank@schokilade.de> 14211e2ce22Schris */ 14311e2ce22Schris function get_acl_config($id){ 14411e2ce22Schris global $AUTH_ACL; 14511e2ce22Schris 14611e2ce22Schris $acl_config=array(); 14711e2ce22Schris 14811e2ce22Schris // match exact name 14911e2ce22Schris $matches = preg_grep('/^'.$id.'\s+.*/',$AUTH_ACL); 15011e2ce22Schris if(count($matches)){ 15111e2ce22Schris foreach($matches as $match){ 15211e2ce22Schris $match = preg_replace('/#.*$/','',$match); //ignore comments 15311e2ce22Schris $acl = preg_split('/\s+/',$match); 15411e2ce22Schris //0 is pagename, 1 is user, 2 is acl 15511e2ce22Schris $acl_config[$acl[0]][] = array( 'name' => $acl[1], 'perm' => $acl[2]); 15611e2ce22Schris } 15711e2ce22Schris } 15811e2ce22Schris 15911e2ce22Schris $specific_found=array(); 16011e2ce22Schris // match ns 16111e2ce22Schris while(($id=getNS($id)) !== false){ 16211e2ce22Schris $matches = preg_grep('/^'.$id.':\*\s+.*/',$AUTH_ACL); 16311e2ce22Schris if(count($matches)){ 16411e2ce22Schris foreach($matches as $match){ 16511e2ce22Schris $match = preg_replace('/#.*$/','',$match); //ignore comments 16611e2ce22Schris $acl = preg_split('/\s+/',$match); 16711e2ce22Schris //0 is pagename, 1 is user, 2 is acl 16811e2ce22Schris $acl_config[$acl[0]][] = array( 'name' => $acl[1], 'perm' => $acl[2]); 16911e2ce22Schris $specific_found[]=$acl[1]; 17011e2ce22Schris } 17111e2ce22Schris } 17211e2ce22Schris } 17311e2ce22Schris 17411e2ce22Schris //include *-config 17511e2ce22Schris $matches = preg_grep('/^\*\s+.*/',$AUTH_ACL); 17611e2ce22Schris if(count($matches)){ 17711e2ce22Schris foreach($matches as $match){ 17811e2ce22Schris $match = preg_replace('/#.*$/','',$match); //ignore comments 17911e2ce22Schris $acl = preg_split('/\s+/',$match); 18011e2ce22Schris // only include * for this user if not already found in ns 18111e2ce22Schris if(!in_array($acl[1], $specific_found)){ 18211e2ce22Schris //0 is pagename, 1 is user, 2 is acl 18311e2ce22Schris $acl_config[$acl[0]][] = array( 'name' => $acl[1], 'perm' => $acl[2]); 18411e2ce22Schris } 18511e2ce22Schris } 18611e2ce22Schris } 18711e2ce22Schris 18811e2ce22Schris //sort 18911e2ce22Schris //FIXME: better sort algo: first sort by key, then sort by first value 19011e2ce22Schris krsort($acl_config, SORT_STRING); 19111e2ce22Schris 19211e2ce22Schris return($acl_config); 19311e2ce22Schris } 19411e2ce22Schris 19511e2ce22Schris 19611e2ce22Schris /** 19711e2ce22Schris * adds new acl-entry to conf/acl.auth.php 19811e2ce22Schris * 19911e2ce22Schris * @author Frank Schubert <frank@schokilade.de> 20011e2ce22Schris */ 20111e2ce22Schris function admin_acl_add($acl_scope, $acl_user, $acl_level){ 20211e2ce22Schris $acl_config = join("",file(DOKU_CONF.'acl.auth.php')); 20311e2ce22Schris 20411e2ce22Schris // max level for pagenames is edit 20511e2ce22Schris if(strpos($acl_scope,'*') === false) { 20611e2ce22Schris if($acl_level > AUTH_EDIT) $acl_level = AUTH_EDIT; 20711e2ce22Schris } 20811e2ce22Schris 20911e2ce22Schris $new_acl = "$acl_scope\t$acl_user\t$acl_level\n"; 21011e2ce22Schris 21111e2ce22Schris $new_config = $acl_config.$new_acl; 21211e2ce22Schris 21311e2ce22Schris return io_saveFile(DOKU_CONF.'acl.auth.php', $new_config); 21411e2ce22Schris } 21511e2ce22Schris 21611e2ce22Schris /** 21711e2ce22Schris * remove acl-entry from conf/acl.auth.php 21811e2ce22Schris * 21911e2ce22Schris * @author Frank Schubert <frank@schokilade.de> 22011e2ce22Schris */ 22111e2ce22Schris function admin_acl_del($acl_scope, $acl_user){ 22211e2ce22Schris $acl_config = file(DOKU_CONF.'acl.auth.php'); 22311e2ce22Schris 22411e2ce22Schris $acl_pattern = '^'.preg_quote($acl_scope,'/').'\s+'.$acl_user.'\s+[0-8].*$'; 22511e2ce22Schris 22611e2ce22Schris // save all non!-matching #FIXME invert is available from 4.2.0 only! 22711e2ce22Schris $new_config = preg_grep("/$acl_pattern/", $acl_config, PREG_GREP_INVERT); 22811e2ce22Schris 22911e2ce22Schris return io_saveFile(DOKU_CONF.'acl.auth.php', join('',$new_config)); 23011e2ce22Schris } 23111e2ce22Schris 23211e2ce22Schris // --- HTML OUTPUT FUNCTIONS BELOW --- // 23311e2ce22Schris 23411e2ce22Schris /** 23511e2ce22Schris * print tablerows with the current permissions for one id 23611e2ce22Schris * 23711e2ce22Schris * @author Frank Schubert <frank@schokilade.de> 23811e2ce22Schris * @author Andreas Gohr <andi@splitbrain.org> 23911e2ce22Schris */ 24011e2ce22Schris function admin_acl_html_dropdown($id){ 24111e2ce22Schris $cur = $id; 24211e2ce22Schris $ret = ''; 24311e2ce22Schris $opt = array(); 24411e2ce22Schris 24511e2ce22Schris //prepare all options 24611e2ce22Schris 24711e2ce22Schris // current page 2481d3e0272SAndreas Gohr $opt[] = array('key'=> $id, 'val'=> $id.' ('.$this->lang['page'].')'); 24911e2ce22Schris 25011e2ce22Schris // additional namespaces 25111e2ce22Schris while(($id=getNS($id)) !== false){ 2521d3e0272SAndreas Gohr $opt[] = array('key'=> $id.':*', 'val'=> $id.':* ('.$this->lang['namespace'].')'); 25311e2ce22Schris } 25411e2ce22Schris 25511e2ce22Schris // the top namespace 2561d3e0272SAndreas Gohr $opt[] = array('key'=> '*', 'val'=> '* ('.$this->lang['namespace'].')'); 25711e2ce22Schris 25811e2ce22Schris // set sel on second entry (current namespace) 25911e2ce22Schris $opt[1]['sel'] = ' selected="selected"'; 26011e2ce22Schris 26111e2ce22Schris // flip options 26211e2ce22Schris $opt = array_reverse($opt); 26311e2ce22Schris 26411e2ce22Schris // create HTML 26511e2ce22Schris $att = array( 'name' => 'acl_scope', 26611e2ce22Schris 'class' => 'edit', 2671d3e0272SAndreas Gohr 'title' => $this->lang['page'].'/'.$this->lang['namespace']); 26811e2ce22Schris $ret .= '<select '.html_attbuild($att).'>'; 26911e2ce22Schris foreach($opt as $o){ 27011e2ce22Schris $ret .= '<option value="'.$o['key'].'"'.$o['sel'].'>'.$o['val'].'</option>'; 27111e2ce22Schris } 27211e2ce22Schris $ret .= '</select>'; 27311e2ce22Schris 27411e2ce22Schris return $ret; 27511e2ce22Schris } 27611e2ce22Schris 27711e2ce22Schris /** 27811e2ce22Schris * print tablerows with the current permissions for one id 27911e2ce22Schris * 28011e2ce22Schris * @author Frank Schubert <frank@schokilade.de> 28111e2ce22Schris * @author Andreas Gohr <andi@splitbrain.org> 28211e2ce22Schris */ 28311e2ce22Schris function admin_acl_html_new(){ 28411e2ce22Schris global $ID; 2851d3e0272SAndreas Gohr global $lang; 28611e2ce22Schris 28711e2ce22Schris // table headers 28811e2ce22Schris ptln('<tr>',2); 2891d3e0272SAndreas Gohr ptln(' <th class="leftalign" colspan="3">'.$this->lang['acl_new'].'</th>',2); 29011e2ce22Schris ptln('</tr>',2); 29111e2ce22Schris 29211e2ce22Schris ptln('<tr>',2); 29311e2ce22Schris 29411e2ce22Schris ptln('<td class="centeralign" colspan="3">',4); 29511e2ce22Schris 2965164d9c9SAnika Henke ptln(' <form method="post" action="'.wl($ID).'"><div class="no">',4); 29711e2ce22Schris ptln(' <input type="hidden" name="do" value="admin" />',4); 29811e2ce22Schris ptln(' <input type="hidden" name="page" value="acl" />',4); 29911e2ce22Schris ptln(' <input type="hidden" name="acl_cmd" value="save" />',4); 300*634d7150SAndreas Gohr formSecurityToken(); 30111e2ce22Schris 30211e2ce22Schris //scope select 3031d3e0272SAndreas Gohr ptln($this->lang['acl_perms'],4); 30411e2ce22Schris ptln($this->admin_acl_html_dropdown($ID),4); 30511e2ce22Schris 30611e2ce22Schris $att = array( 'name' => 'acl_type', 30711e2ce22Schris 'class' => 'edit', 3081d3e0272SAndreas Gohr 'title' => $this->lang['acl_user'].'/'.$this->lang['acl_group']); 30911e2ce22Schris ptln(' <select '.html_attbuild($att).'>',4); 3101d3e0272SAndreas Gohr ptln(' <option value="@">'.$this->lang['acl_group'].'</option>',4); 3111d3e0272SAndreas Gohr ptln(' <option value="">'.$this->lang['acl_user'].'</option>',4); 31211e2ce22Schris ptln(' </select>',4); 31311e2ce22Schris 31411e2ce22Schris $att = array( 'name' => 'acl_user', 31511e2ce22Schris 'type' => 'text', 31611e2ce22Schris 'class' => 'edit', 3171d3e0272SAndreas Gohr 'title' => $this->lang['acl_user'].'/'.$this->lang['acl_group']); 31811e2ce22Schris ptln(' <input '.html_attbuild($att).' />',4); 31911e2ce22Schris ptln(' <br />'); 32011e2ce22Schris 32111e2ce22Schris ptln( $this->admin_acl_html_checkboxes(0,false),8); 32211e2ce22Schris 32358dde80dSAnika Henke ptln(' <input type="submit" class="button" value="'.$lang['btn_save'].'" />',4); 3245164d9c9SAnika Henke ptln(' </div></form>'); 325bf5d40c2SAnika Henke ptln('</td>',4); 32611e2ce22Schris ptln('</tr>',2); 32711e2ce22Schris } 32811e2ce22Schris 32911e2ce22Schris /** 33011e2ce22Schris * print tablerows with the current permissions for one id 33111e2ce22Schris * 33211e2ce22Schris * @author Frank Schubert <frank@schokilade.de> 33311e2ce22Schris * @author Andreas Gohr <andi@splitbrain.org> 33411e2ce22Schris */ 33511e2ce22Schris function admin_acl_html_current($id,$permissions){ 33611e2ce22Schris global $lang; 33711e2ce22Schris global $ID; 33811e2ce22Schris 33911e2ce22Schris //is it a page? 34011e2ce22Schris if(substr($id,-1) == '*'){ 34111e2ce22Schris $ispage = false; 34211e2ce22Schris }else{ 34311e2ce22Schris $ispage = true; 34411e2ce22Schris } 34511e2ce22Schris 34611e2ce22Schris // table headers 34711e2ce22Schris ptln(' <tr>'); 34811e2ce22Schris ptln(' <th class="leftalign" colspan="3">'); 3491d3e0272SAndreas Gohr ptln($this->lang['acl_perms'],6); 35011e2ce22Schris if($ispage){ 3511d3e0272SAndreas Gohr ptln($this->lang['page'],6); 35211e2ce22Schris }else{ 3531d3e0272SAndreas Gohr ptln($this->lang['namespace'],6); 35411e2ce22Schris } 35511e2ce22Schris ptln('<em>'.$id.'</em>',6); 35611e2ce22Schris ptln(' </th>'); 35711e2ce22Schris ptln(' </tr>'); 35811e2ce22Schris 35911e2ce22Schris sort($permissions); 36011e2ce22Schris 36111e2ce22Schris foreach ($permissions as $conf){ 36211e2ce22Schris //userfriendly group/user display 3636c2bb100SAndreas Gohr $conf['name'] = rawurldecode($conf['name']); 36411e2ce22Schris if(substr($conf['name'],0,1)=="@"){ 3651d3e0272SAndreas Gohr $group = $this->lang['acl_group']; 36611e2ce22Schris $name = substr($conf['name'],1); 36711e2ce22Schris $type = '@'; 36811e2ce22Schris }else{ 3691d3e0272SAndreas Gohr $group = $this->lang['acl_user']; 37011e2ce22Schris $name = $conf['name']; 37111e2ce22Schris $type = ''; 37211e2ce22Schris } 37311e2ce22Schris 37411e2ce22Schris ptln('<tr>',2); 3756c2bb100SAndreas Gohr ptln('<td class="leftalign">'.htmlspecialchars($group.' '.$name).'</td>',4); 37611e2ce22Schris 37711e2ce22Schris // update form 37811e2ce22Schris ptln('<td class="centeralign">',4); 3795164d9c9SAnika Henke ptln(' <form method="post" action="'.wl($ID).'"><div class="no">',4); 380*634d7150SAndreas Gohr formSecurityToken(); 38111e2ce22Schris ptln(' <input type="hidden" name="do" value="admin" />',4); 38211e2ce22Schris ptln(' <input type="hidden" name="page" value="acl" />',4); 38311e2ce22Schris ptln(' <input type="hidden" name="acl_cmd" value="save" />',4); 38411e2ce22Schris ptln(' <input type="hidden" name="acl_scope" value="'.formtext($id).'" />',4); 38511e2ce22Schris ptln(' <input type="hidden" name="acl_type" value="'.$type.'" />',4); 38611e2ce22Schris ptln(' <input type="hidden" name="acl_user" value="'.formtext($name).'" />',4); 38711e2ce22Schris ptln( $this->admin_acl_html_checkboxes($conf['perm'],$ispage),8); 38858dde80dSAnika Henke ptln(' <input type="submit" class="button" value="'.$lang['btn_update'].'" />',4); 3895164d9c9SAnika Henke ptln(' </div></form>'); 39011e2ce22Schris ptln('</td>',4); 39111e2ce22Schris 39211e2ce22Schris 39311e2ce22Schris // deletion form 39411e2ce22Schris 39511e2ce22Schris $ask = $lang['del_confirm'].'\\n'; 39611e2ce22Schris $ask .= $id.' '.$conf['name'].' '.$conf['perm']; 39711e2ce22Schris ptln('<td class="centeralign">',4); 3985164d9c9SAnika Henke ptln(' <form method="post" action="'.wl($ID).'" onsubmit="return confirm(\''.str_replace('\\\\n','\\n',addslashes($ask)).'\')"><div class="no">',4); 399*634d7150SAndreas Gohr formSecurityToken(); 40011e2ce22Schris ptln(' <input type="hidden" name="do" value="admin" />',4); 40111e2ce22Schris ptln(' <input type="hidden" name="page" value="acl" />',4); 40211e2ce22Schris ptln(' <input type="hidden" name="acl_cmd" value="delete" />',4); 40311e2ce22Schris ptln(' <input type="hidden" name="acl_scope" value="'.formtext($id).'" />',4); 40411e2ce22Schris ptln(' <input type="hidden" name="acl_type" value="'.$type.'" />',4); 40511e2ce22Schris ptln(' <input type="hidden" name="acl_user" value="'.formtext($name).'" />',4); 40658dde80dSAnika Henke ptln(' <input type="submit" class="button" value="'.$lang['btn_delete'].'" />',4); 4075164d9c9SAnika Henke ptln(' </div></form>',4); 40811e2ce22Schris ptln('</td>',4); 40911e2ce22Schris 41011e2ce22Schris ptln('</tr>',2); 41111e2ce22Schris } 41211e2ce22Schris 41311e2ce22Schris } 41411e2ce22Schris 41511e2ce22Schris 41611e2ce22Schris /** 41711e2ce22Schris * print the permission checkboxes 41811e2ce22Schris * 41911e2ce22Schris * @author Frank Schubert <frank@schokilade.de> 42011e2ce22Schris * @author Andreas Gohr <andi@splitbrain.org> 42111e2ce22Schris */ 42211e2ce22Schris function admin_acl_html_checkboxes($setperm,$ispage){ 42311e2ce22Schris global $lang; 42411e2ce22Schris 42511e2ce22Schris static $label = 0; //number labels 42611e2ce22Schris $ret = ''; 42711e2ce22Schris 42811e2ce22Schris foreach(array(AUTH_READ,AUTH_EDIT,AUTH_CREATE,AUTH_UPLOAD,AUTH_DELETE) as $perm){ 42911e2ce22Schris $label += 1; 43011e2ce22Schris 43111e2ce22Schris //general checkbox attributes 43211e2ce22Schris $atts = array( 'type' => 'checkbox', 43311e2ce22Schris 'id' => 'pbox'.$label, 43411e2ce22Schris 'name' => 'acl_perm[]', 43511e2ce22Schris 'value' => $perm ); 43611e2ce22Schris //dynamic attributes 43711e2ce22Schris if($setperm >= $perm) $atts['checked'] = 'checked'; 43811e2ce22Schris # if($perm > AUTH_READ) $atts['onchange'] = #FIXME JS to autoadd lower perms 43911e2ce22Schris if($ispage && $perm > AUTH_EDIT) $atts['disabled'] = 'disabled'; 44011e2ce22Schris 44111e2ce22Schris //build code 4421d3e0272SAndreas Gohr $ret .= '<label for="pbox'.$label.'" title="'.$this->lang['acl_perm'.$perm].'">'; 44311e2ce22Schris $ret .= '<input '.html_attbuild($atts).' />'; 4441d3e0272SAndreas Gohr $ret .= $this->lang['acl_perm'.$perm]; 44511e2ce22Schris $ret .= "</label>\n"; 44611e2ce22Schris } 44711e2ce22Schris return $ret; 44811e2ce22Schris } 44911e2ce22Schris 45011e2ce22Schris} 451