Text=$text
\n"; } if (preg_match_all("/^\\s*(?P[\\w%@]+)\\s*=\\s*(?P.*)\\s*$/m", $text, $m, PREG_SET_ORDER)) { foreach ($m as $aka) { dbg($d*2, "$func: alias=$aka[alias], auth=$aka[val]"); $aka['alias'] = trim($aka['alias']); foreach (explode(",", $aka['val']) as $val) $alias[$aka['alias']][] = trim($val); } } dbg($d*1, "ALIAS:"); dbg($d*1, $alias); if (preg_match_all("/^(?P[^:\n]+):(?P[^:\n]*)(?::(?P[^:\n]*)(?::(?P[^:\n]*))?)?$/m", $text, $m, PREG_SET_ORDER)) { foreach ($m as $pagerec) { dbg($d*2, "$func: pats=$pagerec[pattern], auth=$pagerec[auth], priority=$pagerec[priority], users=$pagerec[user]"); $priority = ($pagerec['priority'] ? $pagerec['priority'] : $slDefaultPriority); slAddAuth($authtable, $pagerec['pattern'], $pagerec['auth'], $priority, $pagerec['user']); } } return($authtable); } function slAddAuth(&$authtable, $pattern, $authlev, $priority=0, $userlist='') { global $slDebug; $func = 'slAddAuth()'; $d = 1*$slDebug; dbg(4*$d, "$func: Entering pattern=$pattern, authlev=$authlev, priority=$priority, user=$user"); if (!@$authtable) $authtable = array('sorted'=>false, 'auth'=>array(), 'alias'=>array()); $authref = &$authtable['auth']; $alias = &$authtable['alias']; $pats = slExpandAlias(explode(",", $pattern), $alias, ''); $auths= slExpandAlias(explode(",", $authlev), $alias, ''); dbg($d*2, "$func: auths after slExpandAlias follows:"); dbg($d*2,$auths); $users = ($userlist ? slExpandAlias(explode(",", $userlist), $alias, '') :array('*')); # Handle the "@group,-fred" exclusion case $inclusers = $exclusers = array(); foreach ((array)$users as $user) { dbg($d*2, "$func: INIT user=$user"); $user = trim($user); if ($user{0} == '-' || $user{0} == '!') $exclusers[] = substr($user, 1); else $inclusers[] = $user; } $users = array_diff($inclusers, $exclusers); $priority = ($priority ? $priority : $slDefaultPriority); dbg(1*$d,'PATS'); dbg(1*$d,$pats); dbg(1*$d,'AUTH'); dbg(1*$d,$auths); dbg(1*$d,'USER'); dbg(1*$d,$users); foreach ($pats as $p) { dbg($d*4, "$func: LOOPY pat=$p"); $p = trim($p); foreach ($auths as $a) { dbg($d*4, "$func: LOOPY auth=$a"); $a = trim($a); foreach ((array)$users as $u) { dbg($d*1, "$func: Pat=$p, auth=$a, user=$u, priority=$priority"); foreach ((array)$authref as $x) if ($x['pat'] == $p && $x['auth'] == $a && $x['user'] == $u && $x['priority'] == $priority) continue 2; $authref[] = array('pat'=>$p, 'auth'=>$a, 'user'=>$u, 'priority'=>$priority); } } } $authtable['sorted'] = false; } # slDisplayAuth() # Display authorization for debug purposes # Enable via a markup such as this: # # Markup('xyzauthpage', '<{$var}', # '/\(:xyzAuthPage:\)/ie', # 'slDisplayAuth($pagename, $GLOBALS["xyzAuthPage"])'); # function slDisplayAuth($pagename, $authtable) { $rtn = "* ALIASES\n"; if (is_array($authtable['alias'])) foreach ($authtable['alias'] as $k => $a) { $rtn .= "** $k ="; foreach($a as $x) { $rtn .= " $x"; $rtn .= slUnpackAlias($authtable['alias'], $x); } $rtn .= "\n"; } $rtn .= "* SORTED: " . ($authtable['sorted']?"TRUE":"FALSE")."\n"; $rtn .= "* AUTHORIZATIONS\n"; $rtn .= "||border=1 style=\"margin-left:10pct;\"\n"; $rtn .= "||!Wildcard Pattern ||!Authorizations ||!User ||!Priority ||\n"; if (is_array($authtable['auth'])) foreach ($authtable['auth'] as $k => $a) { #$rtn .= "** $k = $a\n"; foreach($a as $x) $rtn .= "||$x "; $rtn .= "||\n"; } return($rtn); } function slUnpackAlias($ary, $idx, $already=array()) { $rtn = ''; if (@$ary[$idx]) { $rtn .= "=("; $first = true; foreach ($ary[$idx] as $x) { $rtn .= ($first?"":",")."$x"; $first = false; if (in_array($x, $already)) $rtn .= " (INFINITE RECURSION!)"; else $rtn .= slUnpackAlias($ary, $x, array_merge($already, (array)$x)); } $rtn .= ")"; } return($rtn); } # slExpandAlias() # Expand aliases for a given list function slExpandAlias($List, $Alias, $Prefix) { global $slDebug; $func = 'slExpandAlias()'; $d = 1*$slDebug; dbg($d*4,"$func: Entering"); $rtn = array(); foreach ($List as $l) { $l = trim($l); if ($l{0} == '-' || $l{0} == '!') { // Theoretically one - should cancel another, but that's a pain. // We'll just leave it with a single level of negativity. $Prefix = $l{0}; $l = substr($l, 1); } else $Prefix = ''; if (@$Alias[$l]) { // array_diff_key() is necessary to prevent circular references // and infinite loops $rtn = array_merge($rtn, slExpandAlias($Alias[$l], array_diff_key($Alias,array($l=>0)), $Prefix)); } else $rtn[] = $Prefix . $l; } return($rtn); } # Comparison function for usort() - compares by 3rd column function slCmpColPriority($a, $b) { if ($a['priority'] == $b['priority']) { return 0; } return ($a['priority'] < $b['priority']) ? -1 : 1; } # For a given priority level if you have found an inclusive and no exclusive # then you are authorized. If you have found an exclusive then you are not # authorized. If you found no inclusive then check the next priority level. # If you have checked all priority levels and found no inclusive match then # you are not authorized. function slAuthorized($pagename, &$authtable, $authlev, $allowslash=false) { global $AuthId, $slDebug; $func = 'slAuthorized()'; $d = 1*$slDebug; dbg($d*4, "$func: Entering for page=$pagename, auth=$authlev"); if (!@$authtable) { dbg($d*3, "$func: Exiting because of empty authtable"); return(false); } if (!@$authtable['sorted']) { dbg(1*$d,"$func: before sort"); dbg(1*$d,$authtable); usort($authtable['auth'], "slCmpColPriority"); dbg(1*$d,"$func: after sort"); dbg(1*$d,$authtable); $authtable['sorted'] = true; } if (!isset($AuthId) && (@$_SESSION['authid'])) $AuthId = @end($_SESSION['authid']); $MatchedInclusive = false; $lastpriority = 0; $authpats = $authtable['auth']; foreach((array)$authpats as $authrec) { dbg($d*1, "$func: entering loop with pat=$authrec[pat], auth=$authrec[auth], user=$authrec[user]"); if (!$authrec['pat']) continue; if (!preg_match("/^" . preg_quote($AuthId) . "$|^\*$/", $authrec['user'])) continue; if (!preg_match("/^[!-]?" . preg_quote($authlev) . "$/", $authrec['auth'])) continue; dbg($d*1, "$func: got in loop with pat=$authrec[pat], auth=$authrec[auth], user=$authrec[user]"); # Calculate the "break" in priority -- if we had a match and we're # moving now to lower priority then we have a valid match and can get # out if ($lastpriority != $authrec['priority']) { dbg($d*3, "$func: break? lastpri=$lastpriority, matched=$MatchedInclusive"); if ($lastpriority != 0 && $MatchedInclusive) return(true); dbg($d*2, "$func: no break..."); $lastpriority = $authrec['priority']; } # if exclude-pat && exclude-auth == include? invalid? # if exclude-pat && include-auth == exclude? # if include-pat && exclude-auth == exclude? # if include-pat && include-auth == include? $posauth = ($authrec['auth']{0} != '-' && $authrec['auth']{0} != '!'); dbg($d*1, "$func: posauth = $posauth"); $p = FmtPageName($authrec['pat'], $pagename); switch ($p{0}) { case '/': if (preg_match($p, $pagename)) { if ($posauth) $MatchedInclusive = true; // pos + pos else return(false); // pos + neg } continue; case '!': if (preg_match($p, $pagename)) { if ($posauth) return(false); // neg + pos else $MatchedInclusive = true; // neg + neg (???) } continue; default: dbg(2*$d,"Checking wildcard match"); if ($allowslash) list($inclp, $exclp) = GlobToPCRE($p); else list($inclp, $exclp) = GlobToPCRE(str_replace('/', '.', $p)); if ($exclp && preg_match("/$exclp/i", $pagename)) { if ($posauth) return(false); // neg + pos else $MatchedInclusive = true; // neg + neg (???) } if ($inclp && preg_match("/$inclp/i", $pagename)) { dbg(2*$d,"MATCH"); if ($posauth) $MatchedInclusive = true; // pos + pos else return(false); // pos + neg } } dbg($d*1, "End of loop: Matched=$MatchedInclusive"); } return $MatchedInclusive; } # slUpdatePage() # This function enforces valid SecLayer authorization before calling # UpdatePage() # SecLayer authorization is assumed to be 'edit' unless over-ridden in $slauth function slUpdatePage($pagename, $opage, $npage, $autharray, $slauth='edit') { if (!slAuthorized($pagename, $autharray, $slauth)) return(false); return(UpdatePage($pagename, $opage, $npage)); } # slUpdateAuthPage() # This function enforces valid SecLayer authorization AND valid PmWiki # authorization before calling UpdatePage(). # ARGUMENTS # $pagename - the page to be updated # $opage - the array holding old (current) page info (or false to read it) # $npage - the array holding new page info (or just the new text) # $autharray- the SecLayer authorizations array to be checked # SecLayer authorization is assumed to be 'edit' unless over-ridden in $slauth # PmWiki authorization is assumed to be 'edit' unless over-ridden via $pmauth # # Note that $opage and $npage are overloaded. They can use the standard array # definitions or $opage can be false/null (the page will be read again to get # the old values) and $npage just a textual value (the array will be used from # $opage). # # If you need $AuthPrompt or $Level or $Since parameters then you cannot use # slUpdateAuthPage(). It just gets too many optional parameters and too # confusing # function slUpdateAuthPage($pagename, $opage, $npage, $autharray, $slauth='edit', $pmauth='edit') { if (!slAuthorized($pagename, $autharray, $slauth)) return(false); if ($opage && is_array($npage)) { if (!CondAuth($pagename, $pmauth)) return(false); } else { // if $opage not set then read it in if (!$opage) $opage = RetrieveAuthPage($pagename, $pmauth); if (!$opage) return(false); if (!is_array($npage)) { $x = $npage; $npage = $opage; $npage['text'] = $x; } } return(UpdatePage($pagename, $opage, $npage)); } # slRetrieveAuthPage() # This function enforces valid SecLayer authorization prior to calling # RetrieveAuthPage(). function slRetrieveAuthPage($pagename, $authlev, $prompt=true, $since=0, $autharray, $slauth='') { if (!$slauth) $slauth = $authlev; if (!slAuthorized($pagename, $autharray, $slauth)) return(false); return(RetrieveAuthPage($pagename, $authlev, $prompt, $since)); } # For testing purposes... /* commented out for security Markup_e("SecLayer", '<{$var}', '/\(:seclayer\s+([^:]*):\)/i', 'slTest(\$pagename, \$m[1])'); end of comment out for security */ function slTest($pagename, $cmd) { global $slTestTable; $rtn = "slTest...\n"; $opt = ParseArgs($cmd); #dbg(1, $opt); if ($opt['load']) { slParsePage($pagename, $opt['load'], $slTestTable); $rtn .= "->Loaded $opt[load]\n"; } if ($opt['test']) { if ($opt['auth']) $auth = $opt['auth']; else $auth = 'edit'; if (slAuthorized($opt['test'], $slTestTable, $auth)) $rtn .= "->$opt[test]: YES! ($auth)\n"; else $rtn .= "->$opt[test]: NO... ($auth)\n"; } return($rtn); }