Extension:ProtocolAccess/ProtocolAccess.php

From MediaWiki.org
Jump to navigation Jump to search
<?php

// ProtocolAccess MediaWiki extension.
// Access control for links of specific protocols 
 
// Copyright (C) 2009 - John Erling Blad.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
#----------------------------------------------------------------------------
#    Extension initialization
#----------------------------------------------------------------------------
 
#$wgProtocolAccess = array();
$wgProtocolAccessVersion = '0.1';
$wgExtensionCredits['parserhook'][] = array(
	'name'=>'ProtocolAccess',
	'version'=>$wgProtocolAccessVersion,
	'author'=>'John Erling Blad',
	'url'=>'http://www.mediawiki.org/wiki/Extension:ProtocolAccess',
	'description' => 'Access control for links of specific protocols'
    );
 
$dir = dirname(__FILE__) . '/';
$wgExtensionFunctions[] = 'wfProtocolAccessSetup';
$wgHooks['LinkerMakeExternalLink'][] = 'wfProtocolAccessCheck';
$wgExtensionMessagesFiles['ProtocolAccess'] = $dir . 'ProtocolAccess.i18n.php';
$wgProtocolAccess = array( );
#$wgProtocolAccesss = array( 'http://' => array());

# Setup the message catalog
function wfProtocolAccessSetup() {
	global $wgParser;
	wfLoadExtensionMessages('ProtocolAccess');
	return true;
}

# Change the row
function wfProtocolAccessCheck( &$url, &$text, &$link, &$attribs ) {
	global $wgProtocolAccess, $wgMemc;;

	# local caching for the duration of one page delivery
	static $acc;
	if (!isset($acc))
		$acc = array(); 

	#loop over each protocol, this is stored as the key in an associative array
	$sticky = 0;
	foreach ($wgProtocolAccess as $key => $arr) {

		# test if the array is within limits, if not pick next
		if (count($arr) < 1 || 2 < count($arr))
			continue;

		# test if the protocol is defined, if not pick next
		if (strncasecmp($url, $key, strlen($key)))
			continue;

		# we have a protocol to check
		$sticky++;
		$prot = preg_replace('/[^a-zA-Z0-9]/', '', $key);
		if (!isset($acc[$prot]))
			$acc[$prot] = array();

		# loop over each access rule
		$state = !($arr[0] == 'whitelist');
		foreach ($arr as $access) {

			# build processed version
			if (!isset($acc[$prot][$access])) {

				# try to fetch the message
				$id = wfMemcKey( "Protocol-access-$prot-$access" );
				$buff = $wgMemc->get( $id );
				if ( $buff === NULL ) {
					$buff = wfMsg( "Protocol-access-$prot-$access" );

					# check if the access rules are defined
					if ($buff == "&lt;Protocol-access-$prot-$access&gt;") {
						$tmp1 = preg_replace('/:/', '&#58;', $url);
						$tmp2 = preg_replace('/:/', '&#58;', $text);
						$link = wfMsg('protocol-access-unknown', $prot, $access, $tmp1, $mp2);
						return false;
					}

					# rewrite the rules
					$buff = preg_replace('/^\S.*$/m', '', $buff);
					$buff = preg_replace('/^\s+/m', '', $buff);
					$buff = preg_replace('/^#.+/m', '', $buff);
					$buff = preg_replace('/[\n\r]+/', "\n", $buff);
					$buff = preg_replace('/^\n+/', '', $buff);
					$buff = preg_replace('/\n+$/', '', $buff);
					$buff = str_replace('/', '\\/', $buff);
					$acc[$prot][$access] = $buff;

					#cache for a number of seconds, gets purged automatically
					$wgMemc->set( $id, $buff, 600 );
				}
			}

			# split the definition and loop
			$found = 0;
			$list = explode("\n", $acc[$prot][$access]);
			foreach($list as $entry) {
				$entry = trim($entry);
				if(preg_match('/'.$entry.'/i', $url)) {
					$found++;
					break;
				}
			}
			switch ($access) {
			case 'whitelist' :
				$state |= $found;
				break;
			case 'blacklist' :
				$state &= !$found;
				break;
			}
		}

		# did we find a rule that completed with true?
		if ($state)
			return true;
	}

	# check if we should have returned
	if ($sticky) {
		$tmp1 = preg_replace('/:/', '&#58;', $url);
		$tmp2 = preg_replace('/:/', '&#58;', $text);
		$link = wfMsg('protocol-access-failed', $tmp1, $tmp2);
		return false;
	}

	# no rule, do as usual
	return true;
}