Difference between revisions of "Extension:SimpleSecurity2.1.php"
(done - now to debug it) |
(rv until fixed) |
||
Line 1: | Line 1: | ||
<? | <? | ||
# Simple security extension | # Simple security extension | ||
− | # - | + | # - [[Security:edit,delete,move,protect|sysop]] |
# - See [[[[MediaWiki Security]]]] article for installation and usage details | # - See [[[[MediaWiki Security]]]] article for installation and usage details | ||
# - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html) | # - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html) | ||
# - Needs apache's mod-rewrite for security on images, see code comments below | # - Needs apache's mod-rewrite for security on images, see code comments below | ||
− | # Handle moves | + | # Handle moves |
− | $ | + | $a = $action == 'submit' ? 'edit' : strtolower($action); |
− | if ($title == 'Special:Movepage' && $action == 'submit') { | + | if ($title=='Special:Movepage' && $action=='submit') { |
− | $ | + | $a = 'move'; |
$t = $wgRequest->getText('wpOldTitle',$wgRequest->getVal('target')); | $t = $wgRequest->getText('wpOldTitle',$wgRequest->getVal('target')); | ||
} else $t = $title; | } else $t = $title; | ||
+ | $securityAction = $a; | ||
− | + | $groups = $wgUser->getGroups(); | |
+ | foreach($groups as $k => $v) $groups[$k] = strtolower($v); | ||
if ($t) { | if ($t) { | ||
Line 28: | Line 30: | ||
} else $file = ''; | } else $file = ''; | ||
− | # | + | # Get security links from this article |
− | + | $secinfo = ''; | |
− | $ | + | $text = new Article(Title::newFromText($t)); |
− | $ | + | $text = $text->fetchContent(0,false,false); |
− | + | if (preg_match_all('/\\[{2}\\s*:?security\\s*:\\s*([^\\]]+?)\\s*\\|\\s*([^\\]]*)\\s*\\]{2}/i',$text,$seclinks,PREG_SET_ORDER)) | |
− | + | addSecurityInfo($seclinks,$secinfo); else $seclinks = array(); | |
− | + | # Get security links from article's categories | |
− | + | preg_match_all('/\\[{2}category:(.+?)(\\|.+?)?\\]]/i',$text,$cats); | |
− | + | foreach ($cats[1] as $i => $cat) { | |
− | + | $cats[1][$i] = $cat = 'Category:'.ucfirst($cat); | |
− | + | if (is_object($text = new Article(Title::newFromText($cat)))) { | |
− | + | if (preg_match_all('/\\[{2}\\s*security\\s*:\\s*([^\\]]+?)\\s*\\|\\s*([^\\]]*)\\s*\\]{2}/i',$text->fetchContent(0,false,false),$match,PREG_SET_ORDER)) { | |
− | + | $seclinks = array_merge($match,$seclinks); | |
− | + | addSecurityInfo($match,$secinfo,"this rule is inherited from [[:$cat]]"); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | $ | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | |||
} | } | ||
− | |||
} | } | ||
− | # | + | # Resolve permission for this action from the extracted security links |
− | + | $security = ''; | |
− | $ | + | foreach ($seclinks as $link) { |
− | + | if ($link[2]=='') $link[2] = 'sysop'; | |
+ | $actions = preg_split("/\\s*,\\s*/",strtolower($link[1])); | ||
+ | if (in_array($a,$actions)) $security = $link[2]; | ||
+ | if (in_array('*',$actions) && ($security == '')) $security = $link[2]; | ||
} | } | ||
− | + | # Validate extracted security against this user/groups | |
− | + | $deny = false; | |
− | + | if ($security && !in_array('sysop',$groups) && !in_array('director',$groups)) { | |
− | + | $security = preg_split("/\\s*,\\s*/",$security); | |
− | + | if (!in_array('*',$security)) { | |
− | + | $groups[] = ucwords($wgUser->mName); | |
− | + | if (count(array_intersect($groups,$security))==0) { | |
− | + | $action = 'view'; | |
− | + | $deny = true; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
} | } | ||
− | |||
− | |||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
if ($file) { | if ($file) { | ||
− | |||
# Log the download event if any security on file | # Log the download event if any security on file | ||
− | if | + | if ($secinfo) { |
$user = $wgUser->mName; | $user = $wgUser->mName; | ||
− | $entry = | + | if ($deny) $entry = "User:$user was denied access to \"$file\""; |
− | $ts = $wgLang->timeanddate(wfTimestampNow(),true); | + | else $entry = "User:$user accessed \"$file\""; |
+ | $ts = $GLOBALS['wgLang']->timeanddate(wfTimestampNow(),true); | ||
$la = new Article(Title::newFromText('Download log')); | $la = new Article(Title::newFromText('Download log')); | ||
$log = "{{Log entry". | $log = "{{Log entry". | ||
Line 148: | Line 88: | ||
$la->quickEdit($log.$la->fetchContent(0,false,false)); | $la->quickEdit($log.$la->fetchContent(0,false,false)); | ||
} | } | ||
− | |||
# Return the file to the client if security validates | # Return the file to the client if security validates | ||
− | if ($ | + | if ($deny) $title = $t; else { |
header("Content-Type: application/octet-stream"); | header("Content-Type: application/octet-stream"); | ||
header("Content-Disposition: attachment; filename=\"$file\""); | header("Content-Disposition: attachment; filename=\"$file\""); | ||
@readfile("$wgUploadDirectory/$path/$file"); | @readfile("$wgUploadDirectory/$path/$file"); | ||
die; | die; | ||
− | } | + | } |
+ | } | ||
+ | } | ||
+ | |||
+ | # Remove the security links and append security info before wiki-parsing | ||
+ | $wgHooks['ParserBeforeStrip'][] = 'securityBeforeParsing'; | ||
+ | function securityBeforeParsing(&$parser,&$text,&$strip_state) { | ||
+ | global $deny,$secinfo,$securityAction,$wgHooks; | ||
+ | if ($deny) { | ||
+ | $text = "{{Action not permitted|$securityAction}}"; | ||
+ | $deny = false; | ||
+ | $securityAction = 'view'; | ||
} | } | ||
+ | else $text = preg_replace("/\\[{2}\\s*:?security\\s*:[^\\]]+?\\]{2}[\r\n]?/i",'',$text); | ||
+ | if ($secinfo && 0 == $GLOBALS['rsi-done']++ && $securityAction == 'view') $text .= "\n{{Security info|1=\n$secinfo\n}}"; | ||
+ | return true; | ||
} | } | ||
+ | # Add security information item | ||
+ | function addSecurityInfo(&$links,&$info,$comment='') { | ||
+ | if ($comment) $comment = " ''($comment)''"; | ||
+ | foreach ($links as $link) { | ||
+ | $a = $link[1] == '*' ? 'Every action' : ucfirst($link[1]); | ||
+ | $b = $link[2] == '*' ? 'anybody' : $link[2]; | ||
+ | $info .= "*'''$a''' requires the user to be '''$b'''$comment\n"; | ||
+ | } | ||
+ | } | ||
?> | ?> |
Revision as of 11:13, 3 March 2007
<?
- Simple security extension
- - sysop
- - See [[MediaWiki Security]] article for installation and usage details
- - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
- - Needs apache's mod-rewrite for security on images, see code comments below
- Handle moves
$a = $action == 'submit' ? 'edit' : strtolower($action); if ($title=='Special:Movepage' && $action=='submit') { $a = 'move'; $t = $wgRequest->getText('wpOldTitle',$wgRequest->getVal('target')); } else $t = $title; $securityAction = $a;
$groups = $wgUser->getGroups(); foreach($groups as $k => $v) $groups[$k] = strtolower($v); if ($t) {
# Handle security on files (needs apache mod-rewrite) # - mod-rewrite redirects /wiki/images/... requests to article title Download/image-path... # - Use the following rewrite condition and rule (adjust to your wiki path if necessary) # RewriteCond %{REQUEST_URI} ^/wiki/images/.+ # RewriteRule ^/wiki/images/(.+) /wiki/index.php/Download/$1 [L] if (ereg('^Download/(.+)/([^/]+)$',$t,$m)) { $path = $m[1]; $file = $image = $m[2]; if (ereg('^thumb/.+/([^/]+)$',$path,$m)) $image = $m[1]; $t = "Image:$image"; } else $file = ;
# Get security links from this article $secinfo = ; $text = new Article(Title::newFromText($t)); $text = $text->fetchContent(0,false,false); if (preg_match_all('/\\[{2}\\s*:?security\\s*:\\s*([^\\]]+?)\\s*\\|\\s*([^\\]]*)\\s*\\]{2}/i',$text,$seclinks,PREG_SET_ORDER)) addSecurityInfo($seclinks,$secinfo); else $seclinks = array();
# Get security links from article's categories preg_match_all('/\\[{2}category:(.+?)(\\|.+?)?\\]]/i',$text,$cats); foreach ($cats[1] as $i => $cat) { $cats[1][$i] = $cat = 'Category:'.ucfirst($cat); if (is_object($text = new Article(Title::newFromText($cat)))) { if (preg_match_all('/\\[{2}\\s*security\\s*:\\s*([^\\]]+?)\\s*\\|\\s*([^\\]]*)\\s*\\]{2}/i',$text->fetchContent(0,false,false),$match,PREG_SET_ORDER)) { $seclinks = array_merge($match,$seclinks); addSecurityInfo($match,$secinfo,"this rule is inherited from $cat"); } } }
# Resolve permission for this action from the extracted security links $security = ; foreach ($seclinks as $link) { if ($link[2]==) $link[2] = 'sysop'; $actions = preg_split("/\\s*,\\s*/",strtolower($link[1])); if (in_array($a,$actions)) $security = $link[2]; if (in_array('*',$actions) && ($security == )) $security = $link[2]; }
# Validate extracted security against this user/groups $deny = false; if ($security && !in_array('sysop',$groups) && !in_array('director',$groups)) { $security = preg_split("/\\s*,\\s*/",$security); if (!in_array('*',$security)) { $groups[] = ucwords($wgUser->mName); if (count(array_intersect($groups,$security))==0) { $action = 'view'; $deny = true; } } } if ($file) { # Log the download event if any security on file if ($secinfo) { $user = $wgUser->mName; if ($deny) $entry = "User:$user was denied access to \"$file\""; else $entry = "User:$user accessed \"$file\""; $ts = $GLOBALS['wgLang']->timeanddate(wfTimestampNow(),true); $la = new Article(Title::newFromText('Download log')); $log = "{{Log entry". "|ts=$ts". "|entry=$entry". "|ip=".$_SERVER['REMOTE_ADDR']. "|ua=".$_SERVER['HTTP_USER_AGENT']. "|cookie=".$_SERVER['HTTP_COOKIE']. "|qs=".$_SERVER['QUERY_STRING']. "}}\n"; $la->quickEdit($log.$la->fetchContent(0,false,false)); } # Return the file to the client if security validates if ($deny) $title = $t; else { header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=\"$file\""); @readfile("$wgUploadDirectory/$path/$file"); die; } } }
- Remove the security links and append security info before wiki-parsing
$wgHooks['ParserBeforeStrip'][] = 'securityBeforeParsing'; function securityBeforeParsing(&$parser,&$text,&$strip_state) { global $deny,$secinfo,$securityAction,$wgHooks; if ($deny) {
$text = "
Sorry, action not permitted!
Your user rights do not permit the $securityAction action to be performed on this article.
";
$deny = false;
$securityAction = 'view';
}
else $text = preg_replace("/\\[{2}\\s*:?security\\s*:[^\\]]+?\\]{2}[\r\n]?/i",,$text);
if ($secinfo && 0 == $GLOBALS['rsi-done']++ && $securityAction == 'view') $text .= "\n
";
return true; }
- Add security information item
function addSecurityInfo(&$links,&$info,$comment=) { if ($comment) $comment = " ($comment)"; foreach ($links as $link) { $a = $link[1] == '*' ? 'Every action' : ucfirst($link[1]); $b = $link[2] == '*' ? 'anybody' : $link[2]; $info .= "*$a requires the user to be $b$comment\n"; } } ?>