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);
}