*/ // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'admin.php'); define('ACLAUDITOR_SCENARIODIR', DOKU_CONF.'aclauditor_scenarios'); class admin_plugin_aclauditor extends DokuWiki_Admin_Plugin { var $mode = 'single'; var $data = null; var $error = ''; var $test = null; var $who = null; var $what = null; var $scenario = ''; var $scenariofn = ''; var $scenarios = array(); function getInfo() { return array( 'author' => 'Etienne MELEARD', 'email' => 'etienne.meleard@free.fr', 'date' => @file_get_contents(DOKU_PLUGIN.'aclauditor/VERSION'), 'name' => 'ACL Auditor Admin Plugin', 'desc' => 'Functions to get info about user /group ACLs of a wiki page', 'url' => 'http://dokuwiki.org/plugin:aclauditor', ); } function getMenuSort() { return 200; } function getMenuText($language) { return $this->getLang('menu'); } function forAdminOnly() { return false; } function handle() { global $ID; $helper = $this->loadHelper('aclauditor', true); if(!$helper) return null; $this->mode = (isset($_GET['aclaudit_mode']) && in_array($_GET['aclaudit_mode'], array('single', 'scenario'))) ? $_GET['aclaudit_mode'] : 'single'; if($this->mode != 'scenario') { $what = (isset($_REQUEST['aclaudit_what']) && !empty($_REQUEST['aclaudit_what'])) ? $_REQUEST['aclaudit_what'] : null; $this->what = preg_match('`^(.*[^:])(\:\*)$`', $what, $m) ? cleanID($m[1]).$m[2] : $what; if(substr($this->what, -1) == ':') $this->what .= '*'; $this->who = (isset($_REQUEST['aclaudit_who']) && !empty($_REQUEST['aclaudit_who'])) ? $_REQUEST['aclaudit_who'] : null; if(isset($_REQUEST['aclaudit_testwho'])) { $this->test = 'who'; $this->data = $helper->getACL($this->who ? $this->who : $_SERVER['REMOTE_USER']); }elseif(isset($_REQUEST['aclaudit_testwhat'])) { $this->test = 'what'; $this->data = $helper->resourceACLs($this->what ? $this->what : $ID); }elseif(isset($_REQUEST['aclaudit_testboth'])) { $this->test = 'both'; $this->data = $helper->getACLon($this->who ? $this->who : $_SERVER['REMOTE_USER'], $this->what ? $this->what : $ID); } }else{ if(!@is_dir(ACLAUDITOR_SCENARIODIR)) mkdir(ACLAUDITOR_SCENARIODIR); foreach(scandir(ACLAUDITOR_SCENARIODIR) as $i) { if(!preg_match('`^[^\.].*\.csv$`', $i)) continue; $desc = ''; if($fp = fopen(ACLAUDITOR_SCENARIODIR.'/'.$i, 'r')) { $l = fgets($fp); if(preg_match('`^\s*"?\s*#\s*(.+)\s*"?,,,\s*$`', $l, $m)) $desc = str_replace('""', '"', $m[1]); fclose($fp); } $this->scenarios[$i] = trim($desc, '"'); } $this->scenario = isset($_POST['aclaudit_scenario_content']) ? trim($_POST['aclaudit_scenario_content']) : null; $fn = isset($_POST['aclaudit_scenario_save_filename']) ? trim($_POST['aclaudit_scenario_save_filename']) : null; if(preg_match('`^[^/\.]+(\.csv)?$`', $fn, $m)) $this->scenariofn = $fn.($m[1] ? '' : '.csv'); if(isset($_POST['aclaudit_scenario_load'])) { $fn = isset($_POST['aclaudit_scenario_load_filename']) ? trim($_POST['aclaudit_scenario_load_filename']) : null; if($fn && array_key_exists($fn, $this->scenarios)) $this->scenariofn = $fn; if($this->scenariofn && @file_exists(ACLAUDITOR_SCENARIODIR.'/'.$this->scenariofn)) { $this->scenario = @file_get_contents(ACLAUDITOR_SCENARIODIR.'/'.$this->scenariofn); msg($this->getLang('scenario_load_success'), 1); }else msg($this->getLang('scenario_load_badfile_error'), -1); }elseif(isset($_POST['aclaudit_scenario_upload'])) { if(isset($_FILES['aclaudit_scenario_upload_file']) && @is_uploaded_file($_FILES['aclaudit_scenario_upload_file']['tmp_name'])) { $this->scenariofn = ''; $this->scenario = @file_get_contents($_FILES['aclaudit_scenario_upload_file']['tmp_name']); msg($this->getLang('scenario_upload_success'), 1); }else msg($this->getLang('scenario_upload_error'), -1); }elseif(isset($_POST['aclaudit_scenario_save'])) { if($this->scenariofn) { if($this->scenario) { if($fp = fopen(ACLAUDITOR_SCENARIODIR.'/'.$this->scenariofn, 'w')) { fwrite($fp, $this->scenario); fclose($fp); msg($this->getLang('scenario_save_success'), 1); }else msg($this->getLang('scenario_save_failed_error'), -1); }elseif(@file_exists(ACLAUDITOR_SCENARIODIR.'/'.$this->scenariofn)) { if(unlink(ACLAUDITOR_SCENARIODIR.'/'.$this->scenariofn)) { msg($this->getLang('scenario_rm_success'), 1); $this->scenario = ''; $this->scenariofn = ''; }else msg($this->getLang('scenario_save_rmfailed_error'), -1); } }else msg($this->getLang('scenario_save_badfile_error'), -1); }elseif(isset($_POST['aclaudit_scenario_download'])) { if($this->scenario) { header('Content-type: application/force-download'); header('Content-Disposition: attachment; filename="'.($this->scenariofn ? $this->scenariofn : 'scenario_'.date('Ymd_His').'.csv').'"'); header('Content-Length: '.strlen($this->scenario)); echo $this->scenario; exit(); }else msg($this->getLang('scenario_download_nodata_error'), -1); } if(isset($_POST['aclaudit_scenario_run'])) { if($this->scenario) { $this->test = true; $this->data = array(); foreach(preg_split('`\s*\n\s*`', $this->scenario) as $l) { if(preg_match('`^\s*"?\s*#`', $l)) continue; list($id, $user, $group, $reqlvl) = array_map(create_function('$i', 'return trim(preg_match("`^\"(.+)\"$`", $i, $m) ? $m[1] : $i);'), preg_split('`\s*[,;]\s*`', $l)); $this->data[$l] = array('valid' => false); if(!$user && !$group) continue; if(!$id) $id = '*'; $this->data[$l]['id'] = $id; $u = $user ? $user : 'dummy_aclauditor_user_'.uniqid().'_'.time(); $this->data[$l]['user'] = $user; $grps = array_filter(explode('|', (string)$group), create_function('$g', 'return (bool)strlen($g);')); if($grps[0] == '*') { global $auth; if($auth && ($u = reset($auth->retrieveUsers(0, 1, array('user' => $u))))) { $grps = $u['grps']; }else $grps = array(); } if(!count($grps)) $grps[] = 'ALL'; $this->data[$l]['group'] = $grps; $law = '=='; if(preg_match('`^(\=\=?|\<\=?|\>\=?|\!\=?)\s*([0-9]+)$`', $reqlvl, $m)) { $law = $m[1]; $reqlvl = (int)$m[2]; }else $reqlvl = (int)$reqlvl; if(!preg_match('`^[0-9]+$`', $reqlvl)) continue; $this->data[$l]['law'] = $law; $this->data[$l]['reqlvl'] = $reqlvl; $this->data[$l]['required'] = ((($law != '==') && ($law != '=')) ? $law : '').$reqlvl; $syslvl = auth_aclcheck($id, $u, $grps); if(auth_isadmin($u, $grps)) $syslvl = 255; $this->data[$l]['found'] = $syslvl; $ok = false; switch($law) { case '<' : if($syslvl < $reqlvl) $ok = true; break; case '<=' : if($syslvl <= $reqlvl) $ok = true; break; case '>' : if($syslvl > $reqlvl) $ok = true; break; case '>=' : if($syslvl >= $reqlvl) $ok = true; break; case '!' : case '!=' : if($syslvl != $reqlvl) $ok = true; break; case '=' : case '==' : default : if($syslvl == $reqlvl) $ok = true; $law = ''; } $this->data[$l]['valid'] = true; $this->data[$l]['pass'] = $ok; $this->data[$l]['explanations'] = $ok ? null : $helper->resourceACLs($id); if(!$ok) $this->test = false; } }else msg($this->getLang('scenario_download_nodata_error'), -1); } } } function html() { global $ID; if($this->mode != 'scenario') { ptln('

'.$this->getLang('listform').'

'); ptln(''.$this->getLang('toscenario').'

'); ptln('
'); ptln(' '.$this->getLang('who').' :
'); ptln(' '.$this->getLang('what').' :
'); ptln(' '); ptln('
'); if($this->test) { ptln('

'.$this->getLang('list').'

'); ptln('
'); switch($this->test) { case 'who' : ptln('
'.$this->getLang('listwho').' : "'.($this->who ? $this->who : $_SERVER['REMOTE_USER']).'"'.'
'); foreach($this->data as $id => $list) { ptln(''); ptln(' '); ptln(' '); foreach($list as $rule => $dfn) { if($rule == '_lvl') continue; ptln(' '); } ptln(' '); ptln('
'.$this->getLang('permwhat').' "'.$id.'" :
'.$this->getLang('who').''.$this->getLang('what').''.$this->getLang('perm').'
'.$dfn['who'].''.$dfn['what'].''.$this->getLang('perm'.$dfn['lvl']).'
'.$this->getLang('resource_final_perm').' :'.$this->getLang('perm'.$list['_lvl']).'
'); } break; case 'what' : ptln('
'.$this->getLang('listwhat').' : "'.($this->what ? $this->what : $ID).'"'.'
'); foreach($this->data as $who => $list) { ptln(''); ptln(' '); ptln(' '); foreach($list as $rule => $dfn) { if($rule == '_lvl') continue; ptln(' '); } ptln(' '); ptln('
'.$this->getLang('permwho').' "'.$who.'" :
'.$this->getLang('who').''.$this->getLang('what').''.$this->getLang('perm').'
'.$dfn['who'].''.$dfn['what'].''.$this->getLang('perm'.$dfn['lvl']).'
'.$this->getLang('resource_final_perm').' :'.$this->getLang('perm'.$list['_lvl']).'
'); } break; case 'both' : ptln('
'.$this->getLang('listbothwho').' "'.($this->who ? $this->who : $_SERVER['REMOTE_USER']).'" '.$this->getLang('listbothwhat').' "'.($this->what ? $this->what : $ID).'"'.'
'); foreach($this->data as $id => $list) { if($id == '_lvl') continue; if($id == '_specificlvl') continue; ptln('
'); ptln('
'.$this->getLang('permbothwhat').' "'.$id.'" :
'); ptln(' '); ptln(' '); $data = $this->data; foreach($data as $tid => $tlist) { foreach($tlist as $who => $slist) { if($who == '_lvl') continue; if($who == '_specificlvl') continue; foreach($slist as $rule => $dfn) { if($rule == '_lvl') continue; if($rule == '_specificlvl') continue; ptln(' '); } } if($tid == $id) break; } if(count($list) <= 2) ptln('
'); $perm = ($list['_specificlvl'] >= 0) ? $list['_specificlvl'] : $list['_lvl']; ptln(' '); ptln('
'.$this->getLang('who').''.$this->getLang('what').''.$this->getLang('perm').'
'.$dfn['who'].''.$dfn['what'].''.$this->getLang('perm'.$dfn['lvl']).'
'.$this->getLang('bothresource_final_perm').' '.((($list['_specificlvl'] >= 0) && ($id != '*')) ? '('.$this->getLang('specific').') ' : '').':'.$this->getLang('perm'.$perm).'
'); ptln('
'); } $perm = ($this->data['_specificlvl'] >= 0) ? $this->data['_specificlvl'] : $this->data['_lvl']; ptln('
'.$this->getLang('resource_final_perm').' '.(($this->data['_specificlvl'] >= 0) ? '('.$this->getLang('specific').') ' : '').': '.$this->getLang('perm'.$perm).'
'); break; } ptln('
'); } }else{ ptln('

'.$this->getLang('scenarioform').'

'); ptln(''.$this->getLang('tosingle').'

'); ptln('
'); ptln(' '.$this->getLang('scenario_load').' :
'); ptln(' '.$this->getLang('scenario_upload').' :
'); ptln('
'); ptln(' '.$this->getLang('scenario_save').' :
'); ptln(' '.$this->getLang('scenario_download').' :
'); ptln(' '); ptln('
'); if(!is_null($this->data)) { ptln('

'.$this->getLang('scenario_results').'

'); ptln('
'.$this->getLang($this->test ? 'scenario_passed' : 'scenario_failed').'
'); if(!$this->test) { ptln(''); ptln(' '); ptln(' '); ptln(' '); ptln(' '); ptln(' '); ptln(' '); ptln(' '); foreach($this->data as $rule => $r) { if($r['pass']) continue; if(!$r['valid']) { ptln(' '); ptln(' '); ptln(' '); ptln(' '); continue; } $on = $r['user'] ? $r['user'] : ''; if($on && $r['group']) $on .= '
'; $on .= $r['group'] ? implode(', ', array_map(create_function('$g', 'return "@".$g;'), $r['group'])) : ''; ptln(' '); ptln(' '); ptln(' '); ptln(' '); $lvlstr = $this->getLang('perm'.$r['reqlvl']); switch($r['law']) { case '<' : $l = 'lt'; break; case '<=' : $l = 'lte'; break; case '>' : $l = 'gt'; break; case '>=' : $l = 'gte'; break; case '!' : case '!=' : $l = 'ne'; break; case '=' : case '==' : default : $l = 'eq'; break; } ptln(' '); ptln(' '); ptln(' '); ptln(' '); ptln(' '); ptln(' '); } ptln('
'.$this->getLang('scenario_rule').''.$this->getLang('scenario_testid').''.$this->getLang('scenario_teston').''.$this->getLang('scenario_required').''.$this->getLang('scenario_found').'
'.$rule.''.$this->getLang('invalid_rule').'
'.$rule.''.$r['id'].''.$on.''.$r['required'].($lvlstr ? ' ('.$this->getLang('req_'.$l).' '.$lvlstr.')' : '').''.$r['found'].' ('.$this->getLang('perm'.$r['found']).')
');
						foreach($r['explanations'] as $who => $list) {
							if(substr($who, 0, 1) == '_') continue;
							$rules = array();
							foreach($list as $crule => $parts) {
								if(substr($id, 0, 1) == '_') continue;
								if(($r['user'] && $parts['who'] == $r['user']) || ($r['group'] && in_array($parts['who'], array_map(create_function('$g', 'return "@".$g;'), $r['group'])))) {
									$rules[] = '	'.$crule.' => '.$parts['lvl'];
								}
							}
							if(count($rules)) {
								ptln($this->getLang('permwho').' : '.$who);
								foreach($rules as $d) ptln($d);
							}
						}
						ptln('
'.$this->getLang('more_details').'
'); } } } } }