Extension:Prefix Security/PageRestrictionHooks v1.1.0

From MediaWiki.org

Jump to: navigation, search
  • Copy the code into a file (PageRestrictionHooks.php)
<?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 "";
}
 
?>
Personal tools