<?php
/**
* An extension hook "PageRestrictionHooks" task's are:
* - Page restrictions defined in PrefixAdministration extension
* - <RESTRICT> tag which can hide parts of the article
* - <ALLOW> tag for allowing user to read article
* - <FORBID> tag for forbiding user to read article
*
* Note: <ALLOW> and <FORBID> tags works independent on PrefixAdministration extension unless both do nothing.
*
* @package MediaWiki version 1.6.3 or later
* @subpackage Extensions
*
* @author Borut Tomažin (debijan@gmail.com)
* @url http://www.mediawiki.org/wiki/Extension:Prefix_Security
* @copyright Copyright © 2006, Borut Tomažin
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public Licence 2.0 or later
*/
define( "RESTRICT_TAG", "RESTRICT" );
define( "ALLOW_TAG", "ALLOW" );
define( "FORBID_TAG", "FORBID" );
$wgExtensionFunctions[] = 'efPageRestrictionHooks';
$wgExtensionCredits['pagerestricthook'][] = array(
'name' => 'Page Restrict Hook',
'author' => 'Borut Tomažin',
'url' => 'http://www.mediawiki.org/wiki/Extension:Prefix_Security'
);
/**
* Function: efPageRestrictionHooks
* - Adds one tag hook and two event hooks
*/
function efPageRestrictionHooks() {
global $wgHooks;
global $wgMessageCache;
global $wgParser;
$wgMessageCache->addMessages(
array(
'page_no_access' => " This area is protected. You are not allowed to edit this content.",
)
);
$wgHooks[ 'userCan' ][] = 'RestrictHookRead';
$wgHooks[ 'AlternateEdit' ][] = 'RestrictHookEdit';
$wgHooks[ 'ArticleSaveComplete' ][] = 'CheckAllowAndForbidTags';
$wgHooks[ 'ParserAfterTidy' ][] = 'DescribeRestrictionsHook';
$wgParser->setHook( RESTRICT_TAG, "TagRestrictHookRead" );
$wgParser->setHook( ALLOW_TAG, "TagRestrictHookAllow" );
$wgParser->setHook( FORBID_TAG, "TagRestrictHookForbid" );
}
/**
* Function: getRights
* - Returns user or group role
*
* @param $page
* @param $user_name_id
* $param $field
*/
function getRights( $page, $user_name_id, $field ) {
global $wgWhitelistRead;
global $wgGroupPermissions;
global $wgTitle;
$page_title = $wgTitle->getPrefixedText();
$dbr =& wfGetDB( DB_SLAVE );
$res = $dbr->query( "
SELECT page_title
FROM page_prefixes_auto
WHERE page_title = '$page_title' and
tag_type = 'RESTRICT'
" );
// the page is restricted: the user must be explicitly allowed access before we check further
if ( $dbr->numRows( $res ) ) {
$res = $dbr->query( "
SELECT page_title, group_name
FROM page_prefixes_auto
WHERE page_title = '$page_title' and
user_id = '$user_name_id' and
tag_type = 'RESTRICT'
" );
// the page is restricted, and the user is not explicitly allowed in
if( !$dbr->numRows( $res ) ) {
$res = $dbr->query( "
SELECT *
FROM page_prefixes_auto, user_groups
WHERE page_prefixes_auto.group_name = user_groups.ug_group
AND page_prefixes_auto.page_title = '$page_title'
AND user_groups.ug_user = '$user_name_id'
AND tag_type = 'RESTRICT'
");
if( !$dbr->numRows( $res ) )
return false;
}
}
#if( in_array( $page, $wgWhitelistRead ) )
#return True;
// checking for ALLOW & FORBID tags
if( $field == 'read_permission' ) {
# FORBID guest
if( !$user_name_id ) {
$res = $dbr->query( "
SELECT page_title, user_id
FROM page_prefixes_auto
WHERE page_title = '$page_title'
AND user_id = '-2' AND tag_type = 'FORBID'
" );
if( $dbr->numRows( $res ) > 0 ) {
return false;
}
}
$res = $dbr->query( "
SELECT page_title, user_id
FROM page_prefixes_auto
WHERE page_title = '$page_title'
AND user_id = '$user_name_id' AND tag_type = 'FORBID'
" );
// if user is on forbid list deny access
if( $dbr->numRows( $res ) > 0 ) {
return false;
}
// else try if user is in any group
else {
$groups = array();
while( $row = $dbr->fetchObject( $res ) ) {
$groups[] = $row->group_name;
}
$dbr->freeResult( $res );
foreach( $groups as $group ) {
$res = $dbr->query( "
SELECT * FROM ".DatabasePrefixExists()."user_groups
WHERE ug_group = '$group'
");
if( $dbr->numRows( $res ) > 0 ) {
while( $row = $dbr->fetchObject( $res ) ) {
if( $row->ug_user == $user_name_id )
return false;
}
$dbr->freeResult( $res );
}
}
}
# ALLOW guest
if( !$user_name_id ) {
$res = $dbr->query( "
SELECT page_title, user_id
FROM page_prefixes_auto
WHERE page_title = '$page_title'
AND user_id = '-2' AND tag_type = 'ALLOW'
" );
if( $dbr->numRows( $res ) > 0 ) {
return true;
}
}
# ALLOW logged in
else {
$res = $dbr->query( "
SELECT page_title, user_id
FROM page_prefixes_auto
WHERE page_title = '$page_title'
AND user_id = '-1' AND tag_type = 'ALLOW'
" );
if( $dbr->numRows( $res ) > 0 ) {
return true;
}
$res = $dbr->query( "
SELECT page_title, group_name
FROM page_prefixes_auto
WHERE page_title = '$page_title'
AND user_id = '$user_name_id' AND tag_type = 'ALLOW'
" );
// if user is on allow list grant acces
if( $dbr->numRows( $res ) > 0 ) {
return true;
}
// else try if user is in any group
else {
$groups = array();
while( $row = $dbr->fetchObject( $res ) ) {
$groups[] = $row->group_name;
}
$dbr->freeResult( $res );
foreach( $groups as $group ) {
$res = $dbr->query( "
SELECT * FROM ".DatabasePrefixExists()."user_groups
WHERE ug_group = '$group'
");
if( $dbr->numRows( $res ) > 0 ) {
while( $row = $dbr->fetchObject( $res ) ) {
if( $row->ug_user == $user_name_id )
return true;
}
$dbr->freeResult( $res );
}
}
}
}
}
// if ALLOW & FORBID tags are not set then check for prefix permissions
$res = $dbr->query( "
SELECT page_prefix
FROM page_prefixes
WHERE LOCATE(page_prefix, '$page')=1
ORDER BY LENGTH(page_prefix) DESC LIMIT 1
" );
$row = $dbr->fetchRow( $res );
if( $row ) {
$page_prefix = $row[0];
// find specific settings for this user for the prefix
$res = $dbr->query( "
SELECT $field
FROM page_prefixes
WHERE user_id = '$user_name_id' AND page_prefix = '$page_prefix'
" );
$row = $dbr->fetchRow( $res );
if( !$row ) {
// find the group which this user is a member of and sort them in decreasing order (y > n)
$res = $dbr->query( "
SELECT $field
FROM page_prefixes, ".DatabasePrefixExists()."user_groups
WHERE page_prefixes.page_prefix = '$page_prefix'
AND page_prefixes.group_name = ".DatabasePrefixExists()."user_groups.ug_group
AND ".DatabasePrefixExists()."user_groups.ug_user = '$user_name_id'
ORDER BY page_prefixes.$field DESC LIMIT 1
" );
$row = $dbr->fetchRow( $res );
}
if( !$row ) {
// settings for user_id=-1 give the defaults for this prefix
$act_id = $user_name_id ? -1 : -2;
$res = $dbr->query( "
SELECT $field
FROM page_prefixes
WHERE user_id ='$act_id' AND page_prefix = '$page_prefix'
" );
$row = $dbr->fetchRow( $res );
}
// if the user was not given the access through its settings, stop her; else see what we have in the $row
return $row and ( $row[0] == 'y' );
}
// if we came here, something is wrong with the database (the empty prefix is missing)
return True;
}
/**
* Function: RestrictHookRead
* - Prevent users which are not on allow list from reading
*
* @param $title: Title object being checked against
* @param $user: Current user object
* @param $action: Action being checked
* @param $result: Pointer to result returned if hook returns false. If null is returned, UserCan checks are continued by internal code
*/
function RestrictHookRead( &$title, &$user, $action, &$result ) {
global $wgUser;
if( !getRights( $title->getPrefixedText(), $wgUser->idFromName( $wgUser->getName() ), 'read_permission' ) ) {
$result = false;
return false;
}
return True;
}
/**
* Function: RestrictHookEdit
* - Prevent users which are not on allow list from editing
*
* @param $editpage: the editpage (object) being called
*/
function RestrictHookEdit( &$editpage ) {
global $wgUser;
global $wgTitle;
global $wgOut;
return getRights( $wgTitle->getPrefixedText(), $wgUser->idFromName( $wgUser->getName() ), 'edit_permission' )
? $editpage
: $wgOut->addWikiText( wfMsg( 'page_no_access' ) );
}
/**
* Function: DescribeRestrictionHook
* - Add's some extra text before an article
*
* @param &$parser Object
* @param &$text
*/
function DescribeRestrictionsHook( &$parser, &$text ) {
global $wgTitle;
$page = $wgTitle->getPrefixedText();
$dbr =& wfGetDB( DB_SLAVE );
$res = $dbr->query( "
SELECT page_prefix
FROM page_prefixes
WHERE LOCATE(page_prefix, '$page')=1
ORDER BY LENGTH(page_prefix) DESC LIMIT 1
" );
if( $dbr->numRows( $res ) > 0 ) {
$prefix = $dbr->fetchObject( $res );
$prefix = $prefix->page_prefix;
if( strlen( trim( $prefix ) ) )
$text = " <pre><font color=\"red\">Access to this page is regulated with a prefix <b><a href=\"index.php?title=Special:PrefixAdministration&action=edit_prefixed_page&page_prefix=$prefix\">$prefix</a></b>.</font></pre>" . $text;
}
}
/**
* Function: TagRestrictHook <RESTRICT users="" groups=""></restrict>
* - Accepts an input text and array of arguments
* - Check user for reading
*
* @param $input: The user input text
* @param $argv: An array of passed arguments
* @param $parser:
*/
function TagRestrictHookRead( $input, $argv, &$parser ) {
global $wgUser;
global $wgOut;
global $action;
global $wgTitle;
if( !strlen( trim( $input ) ) ) {
$users = trim( $argv["users"] );
$groups = trim( $argv["groups"] );
if( strlen( $users ) ) {
if( strlen( $groups ) )
return " <font color=\"red\">Access to this page is restricted to user(s) <B>$users</B> and <a href=\"index.php?title=Special:GroupsAdministration\">group(s)</a> <B>$groups</B>.</font>";
else
return " <font color=\"red\">Access to this page is restricted to user(s) <B>$users</B>.</font>";
}
else if (strlen($groups))
return " <font color=\"red\">Access to this page is restricted to <a href=\"index.php?title=Special:GroupsAdministration\">group(s)</a> <B>$groups</B>.</font>";
else
return "";
}
$parser->disableCache();
$user_name = $wgUser->getName();
$user_name_id = $wgUser->idFromName( $user_name );
$page = $wgTitle->getText();
# if both 'users' and 'groups' parameters are given
if( count( $argv ) == 2 ) {
if( in_array( $user_name, returnUsers( $argv["users"] ) ) ) {
return $input;
}
else {
if( returnGroups( $argv["groups"] ) ) {
return $input;
}
}
return " This text is protected. You are not allowed to read it!";
}
# if 'users' or 'groups' parameter is given
else if( count( $argv ) == 1 ) {
# if 'users' paramater is given
if( count( $argv["users"] ) > 0 ) {
if( in_array( $user_name, returnUsers( $argv["users"] ) ) ) {
return $input;
}
else {
return " This text is protected. You are not allowed to read it!";
}
}
# if 'groups' parameter is given
else {
if( returnGroups( $argv["groups"] ) ) {
return $input;
}
else {
return " This text is protected. You are not allowed to read it!";
}
}
}
# if no parameter is given
else {
return $input;
}
}
/**
* Function: returnUsers
* - Returns users listed in users="" tag
*
* @param $users_s: String of al users divided by comma
*/
function returnUsers( $users_s ) {
$user_list = explode( ",", $users_s );
$users = array();
foreach( $user_list as $user ) {
$user = trim( $user );
if( strlen( $user ) > 0 ) {
$users[] = $user;
}
}
return $users;
}
/**
* Function: returnGroups
* - Returns true if user exists in group, else false
*
* @param $groups_s: String of al groups divided by comma
*/
function returnGroups( $groups_s ) {
global $wgUser;
$group_list = explode( ",", $groups_s );
foreach( $group_list as $group ) {
$group = trim( $group );
if( strlen( $group ) > 0 ) {
if( in_array( $group, $wgUser->mGroups ) )
return true;
else
continue;
}
}
return false;
}
/**
* Function: userNameToId
* - Returns the id of the username
*
* @param $name: String username
*/
function userNameToId( $name ) {
if( $name == "*" )
return -2;
if( $name == "@" )
return -1;
global $wgUser;
return $wgUser->idFromName( $name );
}
/**
* Function CheckAllowAndForbidTags
* - Check for <ALLOW> tag and extract its parameters
* - Tags should look like this: <ALLOW users="..." groups="...">
* - Check for <FORBID> tag and extract its parameters
* - Tags should look like this: <FORBID users="..." groups="...">
*
* @param $article: the article (object) saved
* @param $user: the user (object) who saved the article
* @param $text: the new article text
* @param $summary: the article summary (comment)
* @param $isminor: minor flag
* @param $iswatch: watch flag
* @param $section: section #
*/
function CheckAllowAndForbidTags( &$article, &$user, &$text, &$summary, &$minoredit, &$watchthis, &$sectionanchor ) {
global $wgUser;
$title = $article->getTitle()->getPrefixedText();
$dbr =& wfGetDB( DB_MASTER );
$dbr->query( "DELETE FROM page_prefixes_auto WHERE page_title='$title'" );
$total = preg_match_all( '%\<</span>(?i)RESTRICT([^>]*)\>(.*?)\<</span>\/(?i)RESTRICT\>%', $text, $matches);
if( $total > 0 ) {
foreach( $matches[1] as $attributes ) {
preg_match_all( '%(?i)users="(.*?)"%', $attributes, $match );
$users = explode( ",", $match[1][0] );
preg_match_all( '%(?i)groups="(.*?)"%', $attributes, $match );
$groups = explode( ",", $match[1][0] );
foreach( $users as $username ) {
if( strlen( trim( $username ) ) > 0 ) {
$user_id = userNameToId( $username );
$dbr->query( "
INSERT INTO page_prefixes_auto ( page_title, user_id, group_name, tag_type )
VALUES ( '$title', '$user_id', '', 'RESTRICT' )
" );
}
}
foreach( $groups as $groupname ) {
if( strlen( trim( $groupname ) ) > 0 ) {
$dbr->query( "
INSERT INTO page_prefixes_auto ( page_title, user_id, group_name, tag_type )
VALUES ( '$title', '', '$groupname', 'RESTRICT' )
" );
}
}
}
}
$total = preg_match_all( '%\<</span>(?i)ALLOW([^>]*)\>(.*?)\<</span>\/(?i)ALLOW\>%', $text, $matches);
if( $total > 0 ) {
foreach($matches[1] as $attributes) {
preg_match_all( '%(?i)users="(.*?)"%', $attributes, $match );
$users = explode( ",", $match[1][0] );
preg_match_all( '%(?i)groups="(.*?)"%', $attributes, $match );
$groups = explode( ",", $match[1][0] );
foreach( $users as $username ) {
if( strlen( trim( $username ) ) > 0 ) {
$user_id = userNameToId( $username );
$dbr->query( "
INSERT INTO page_prefixes_auto ( page_title, user_id, group_name, tag_type )
VALUES ( '$title', '$user_id', '', 'ALLOW' )
" );
}
}
foreach( $groups as $groupname ) {
if( strlen( trim( $groupname ) ) > 0 ) {
$dbr->query( "
INSERT INTO page_prefixes_auto ( page_title, user_id, group_name, tag_type )
VALUES ( '$title', '', '$groupname', 'ALLOW' )
" );
}
}
}
}
$total = preg_match_all( '%\<</span>(?i)FORBID([^>]*)\>(.*?)\<</span>\/(?i)FORBID\>%', $text, $matches);
if( $total > 0 ) {
foreach($matches[1] as $attributes) {
preg_match_all( '%(?i)users="(.*?)"%', $attributes, $match );
$users = explode( ",", $match[1][0] );
preg_match_all( '%(?i)groups="(.*?)"%', $attributes, $match );
$groups = explode( ",", $match[1][0] );
foreach( $users as $username ) {
if( strlen( trim( $username ) ) > 0 ) {
$user_id = userNameToId( $username );
$dbr->query( "
INSERT INTO page_prefixes_auto ( page_title, user_id, group_name, tag_type )
VALUES ( '$title', '$user_id', '', 'FORBID' )
" );
}
}
foreach( $groups as $groupname ) {
if( strlen( trim( $groupname ) ) > 0 ) {
$dbr->query( "
INSERT INTO page_prefixes_auto ( page_title, user_id, group_name, tag_type )
VALUES ( '$title', '', '$groupname', 'FORBID' )
" );
}
}
}
}
}
/**
* Function: TagRestrictHookAllow
* - Returns the input text insert in the middle of the <ALLOW> tag
*/
function TagRestrictHookAllow( $input, $argv, &$parser ) {
return $input;
}
/**
* Function: TagRestrictHookForbid
* - Returns the input text insert in the middle of the <FORBID> tag
*/
function TagRestrictHookForbid( $input, $argv, &$parser ) {
return $input;
}
/**
* Function: DatabasePrefixExists
* - Returns the database table prefix if exist, else returns ""
*/
function DatabasePrefixExists() {
global $wgGroupPermissions;
if( isset( $wgGroupPermissions['logged']['databasePrefix'] ) )
return $wgGroupPermissions['logged']['databasePrefix'];
return "";
}
?>