2007-12-08 21:06:21 +00:00
|
|
|
<?php
|
2008-08-05 15:57:10 +00:00
|
|
|
/**
|
2008-08-08 23:26:44 +00:00
|
|
|
* Title Blacklist class
|
2010-11-08 21:55:05 +00:00
|
|
|
* @author Victor Vasiliev
|
|
|
|
* @copyright © 2007-2010 Victor Vasiliev et al
|
2008-08-09 01:54:39 +00:00
|
|
|
* @license GNU General Public License 2.0 or later
|
|
|
|
* @file
|
|
|
|
*/
|
|
|
|
|
|
|
|
//@{
|
|
|
|
/**
|
2010-06-06 15:12:22 +00:00
|
|
|
* @ingroup Extensions
|
2008-08-09 01:54:39 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements a title blacklist for MediaWiki
|
2007-12-08 21:06:21 +00:00
|
|
|
*/
|
|
|
|
class TitleBlacklist {
|
2008-01-08 18:00:59 +00:00
|
|
|
private $mBlacklist = null, $mWhitelist = null;
|
2012-05-24 23:55:22 +00:00
|
|
|
const VERSION = 3; // Blacklist format
|
2007-12-08 21:06:21 +00:00
|
|
|
|
2011-07-30 15:13:28 +00:00
|
|
|
/**
|
|
|
|
* Get an instance of this class
|
|
|
|
*
|
|
|
|
* @return TitleBlacklist
|
|
|
|
*/
|
|
|
|
public static function singleton() {
|
|
|
|
static $instance = null;
|
|
|
|
|
|
|
|
if ( $instance === null ) {
|
|
|
|
$instance = new self;
|
|
|
|
}
|
|
|
|
return $instance;
|
|
|
|
}
|
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
|
|
|
* Load all configured blacklist sources
|
2011-03-14 23:44:41 +00:00
|
|
|
*/
|
2007-12-08 21:06:21 +00:00
|
|
|
public function load() {
|
2015-04-29 21:25:24 +00:00
|
|
|
global $wgTitleBlacklistSources, $wgTitleBlacklistCaching;
|
|
|
|
|
|
|
|
$cache = ObjectCache::getMainWANInstance();
|
2012-08-29 13:53:38 +00:00
|
|
|
// Try to find something in the cache
|
2015-04-29 21:25:24 +00:00
|
|
|
$cachedBlacklist = $cache->get( wfMemcKey( "title_blacklist_entries" ) );
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( is_array( $cachedBlacklist ) && count( $cachedBlacklist ) > 0 && ( $cachedBlacklist[0]->getFormatVersion() == self::VERSION ) ) {
|
2007-12-19 18:35:44 +00:00
|
|
|
$this->mBlacklist = $cachedBlacklist;
|
|
|
|
return;
|
|
|
|
}
|
2007-12-23 09:47:36 +00:00
|
|
|
|
2007-12-09 12:15:13 +00:00
|
|
|
$sources = $wgTitleBlacklistSources;
|
2015-05-19 16:05:32 +00:00
|
|
|
$sources['local'] = array( 'type' => 'message' );
|
2007-12-09 12:15:13 +00:00
|
|
|
$this->mBlacklist = array();
|
2012-05-24 23:55:22 +00:00
|
|
|
foreach( $sources as $sourceName => $source ) {
|
|
|
|
$this->mBlacklist = array_merge( $this->mBlacklist, $this->parseBlacklist( $this->getBlacklistText( $source ), $sourceName ) );
|
2007-12-09 12:15:13 +00:00
|
|
|
}
|
2015-04-29 21:25:24 +00:00
|
|
|
$cache->set( wfMemcKey( "title_blacklist_entries" ), $this->mBlacklist, $wgTitleBlacklistCaching['expiry'] );
|
2015-01-06 00:38:46 +00:00
|
|
|
wfDebugLog( 'TitleBlacklist-cache', 'Updated ' . wfMemcKey( "title_blacklist_entries" )
|
|
|
|
. ' with ' . count( $this->mBlacklist ) . ' entries.' );
|
2007-12-08 21:06:21 +00:00
|
|
|
}
|
2008-01-08 18:00:59 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
2012-05-24 23:55:22 +00:00
|
|
|
* Load local whitelist
|
2011-03-14 23:44:41 +00:00
|
|
|
*/
|
2008-01-08 18:00:59 +00:00
|
|
|
public function loadWhitelist() {
|
2015-04-29 21:25:24 +00:00
|
|
|
global $wgTitleBlacklistCaching;
|
|
|
|
|
|
|
|
$cache = ObjectCache::getMainWANInstance();
|
|
|
|
$cachedWhitelist = $cache->get( wfMemcKey( "title_whitelist_entries" ) );
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( is_array( $cachedWhitelist ) && count( $cachedWhitelist ) > 0 && ( $cachedWhitelist[0]->getFormatVersion() != self::VERSION ) ) {
|
2008-01-08 18:00:59 +00:00
|
|
|
$this->mWhitelist = $cachedWhitelist;
|
|
|
|
return;
|
|
|
|
}
|
2012-08-29 13:53:38 +00:00
|
|
|
$this->mWhitelist = $this->parseBlacklist( wfMessage( 'titlewhitelist' )
|
2012-05-24 23:55:22 +00:00
|
|
|
->inContentLanguage()->text(), 'whitelist' );
|
2015-04-29 21:25:24 +00:00
|
|
|
$cache->set( wfMemcKey( "title_whitelist_entries" ), $this->mWhitelist, $wgTitleBlacklistCaching['expiry'] );
|
2008-01-08 18:00:59 +00:00
|
|
|
}
|
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
|
|
|
* Get the text of a blacklist from a specified source
|
|
|
|
*
|
|
|
|
* @param $source A blacklist source from $wgTitleBlacklistSources
|
|
|
|
* @return The content of the blacklist source as a string
|
2011-03-14 23:44:41 +00:00
|
|
|
*/
|
2008-08-09 01:54:39 +00:00
|
|
|
private static function getBlacklistText( $source ) {
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( !is_array( $source ) || count( $source ) <= 0 ) {
|
|
|
|
return ''; // Return empty string in error case
|
2007-12-09 12:15:13 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 16:05:32 +00:00
|
|
|
if ( $source['type'] == 'message' ) {
|
2012-08-29 13:53:38 +00:00
|
|
|
return wfMessage( 'titleblacklist' )->inContentLanguage()->text();
|
2015-05-19 16:05:32 +00:00
|
|
|
} elseif ( $source['type'] == 'localpage' && count( $source ) >= 2 ) {
|
2007-12-10 19:02:38 +00:00
|
|
|
$title = Title::newFromText( $source['src'] );
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( is_null( $title ) ) {
|
2007-12-09 12:15:13 +00:00
|
|
|
return '';
|
|
|
|
}
|
2012-09-24 09:24:32 +00:00
|
|
|
if ( $title->getNamespace() == NS_MEDIAWIKI ) {
|
2016-02-27 18:21:20 +00:00
|
|
|
$msg = wfMessage( $title->getText() )->inContentLanguage();
|
|
|
|
if ( !$msg->isDisabled() ) {
|
|
|
|
return $msg->text();
|
2007-12-09 12:15:13 +00:00
|
|
|
} else {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$article = new Article( $title );
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( $article->exists() ) {
|
2007-12-09 12:15:13 +00:00
|
|
|
$article->followRedirect();
|
|
|
|
return $article->getContent();
|
|
|
|
}
|
|
|
|
}
|
2015-05-19 16:05:32 +00:00
|
|
|
} elseif ( $source['type'] == 'url' && count( $source ) >= 2 ) {
|
2008-08-09 01:54:39 +00:00
|
|
|
return self::getHttp( $source['src'] );
|
2015-05-19 16:05:32 +00:00
|
|
|
} elseif ( $source['type'] == 'file' && count( $source ) >= 2 ) {
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( file_exists( $source['src'] ) ) {
|
2007-12-10 19:02:38 +00:00
|
|
|
return file_get_contents( $source['src'] );
|
2007-12-09 12:15:13 +00:00
|
|
|
} else {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
2007-12-08 21:06:21 +00:00
|
|
|
}
|
2011-03-22 23:07:21 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
|
|
|
* Parse blacklist from a string
|
|
|
|
*
|
2012-09-24 09:24:32 +00:00
|
|
|
* @param $list string Text of a blacklist source
|
|
|
|
* @return array of TitleBlacklistEntry entries
|
2011-03-14 23:44:41 +00:00
|
|
|
*/
|
2012-05-24 23:55:22 +00:00
|
|
|
public static function parseBlacklist( $list, $sourceName ) {
|
2007-12-08 21:06:21 +00:00
|
|
|
$lines = preg_split( "/\r?\n/", $list );
|
|
|
|
$result = array();
|
2011-03-22 23:07:21 +00:00
|
|
|
foreach ( $lines as $line ) {
|
2012-05-24 23:55:22 +00:00
|
|
|
$line = TitleBlacklistEntry :: newFromString( $line, $sourceName );
|
2007-12-10 19:02:38 +00:00
|
|
|
if ( $line ) {
|
|
|
|
$result[] = $line;
|
|
|
|
}
|
2007-12-08 21:06:21 +00:00
|
|
|
}
|
|
|
|
|
2008-01-14 13:52:05 +00:00
|
|
|
return $result;
|
2007-12-08 21:06:21 +00:00
|
|
|
}
|
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
2015-09-10 23:48:04 +00:00
|
|
|
* Check whether the blacklist restricts given user
|
2010-11-08 21:55:05 +00:00
|
|
|
* performing a specific action on the given Title
|
|
|
|
*
|
|
|
|
* @param $title Title to check
|
|
|
|
* @param $user User to check
|
2011-08-22 20:37:26 +00:00
|
|
|
* @param $action string Action to check; 'edit' if unspecified
|
|
|
|
* @param $override bool If set to true, overrides work
|
2012-09-24 09:24:32 +00:00
|
|
|
* @return TitleBlacklistEntry|bool The corresponding TitleBlacklistEntry if
|
|
|
|
* blacklisted; otherwise false
|
2011-03-14 23:44:41 +00:00
|
|
|
*/
|
2010-11-08 21:55:05 +00:00
|
|
|
public function userCannot( $title, $user, $action = 'edit', $override = true ) {
|
2015-09-10 23:48:04 +00:00
|
|
|
$entry = $this->isBlacklisted( $title, $action );
|
|
|
|
if ( !$entry ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
$params = $entry->getParams();
|
|
|
|
if ( isset( $params['autoconfirmed'] ) && $user->isAllowed( 'autoconfirmed' ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( $override && self::userCanOverride( $user, $action ) ) {
|
2010-11-08 21:55:05 +00:00
|
|
|
return false;
|
2011-08-22 20:37:26 +00:00
|
|
|
}
|
2015-09-10 23:48:04 +00:00
|
|
|
return $entry;
|
2010-11-08 21:55:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-03-22 22:30:23 +00:00
|
|
|
* Check whether the blacklist restricts
|
2008-08-09 01:54:39 +00:00
|
|
|
* performing a specific action on the given Title
|
|
|
|
*
|
|
|
|
* @param $title Title to check
|
2011-08-22 20:37:26 +00:00
|
|
|
* @param $action string Action to check; 'edit' if unspecified
|
2012-09-24 09:24:32 +00:00
|
|
|
* @return TitleBlacklistEntry|bool The corresponding TitleBlacklistEntry if blacklisted;
|
2008-08-09 01:54:39 +00:00
|
|
|
* otherwise FALSE
|
2011-03-14 23:44:41 +00:00
|
|
|
*/
|
2007-12-10 19:02:38 +00:00
|
|
|
public function isBlacklisted( $title, $action = 'edit' ) {
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( !( $title instanceof Title ) ) {
|
2009-05-17 14:12:38 +00:00
|
|
|
$title = Title::newFromText( $title );
|
2014-01-07 18:08:24 +00:00
|
|
|
if ( !( $title instanceof Title ) ) {
|
|
|
|
// The fact that the page name is invalid will stop whatever
|
|
|
|
// action is going through. No sense in doing more work here.
|
|
|
|
return false;
|
|
|
|
}
|
2007-12-08 21:06:21 +00:00
|
|
|
}
|
|
|
|
$blacklist = $this->getBlacklist();
|
2014-01-07 18:08:24 +00:00
|
|
|
$autoconfirmedItem = false;
|
2007-12-08 21:06:21 +00:00
|
|
|
foreach ( $blacklist as $item ) {
|
2013-09-08 04:24:56 +00:00
|
|
|
if ( $item->matches( $title->getFullText(), $action ) ) {
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( $this->isWhitelisted( $title, $action ) ) {
|
2008-01-08 18:00:59 +00:00
|
|
|
return false;
|
|
|
|
}
|
2014-01-07 18:08:24 +00:00
|
|
|
$params = $item->getParams();
|
|
|
|
if ( !isset( $params['autoconfirmed'] ) ) {
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
if ( !$autoconfirmedItem ) {
|
|
|
|
$autoconfirmedItem = $item;
|
|
|
|
}
|
2007-12-08 21:06:21 +00:00
|
|
|
}
|
|
|
|
}
|
2014-01-07 18:08:24 +00:00
|
|
|
return $autoconfirmedItem;
|
2007-12-08 21:06:21 +00:00
|
|
|
}
|
2011-03-22 22:30:23 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
2011-03-22 22:30:23 +00:00
|
|
|
* Check whether it has been explicitly whitelisted that the
|
2008-08-09 01:54:39 +00:00
|
|
|
* current User may perform a specific action on the given Title
|
|
|
|
*
|
|
|
|
* @param $title Title to check
|
2011-08-22 20:37:26 +00:00
|
|
|
* @param $action string Action to check; 'edit' if unspecified
|
2012-09-24 09:24:32 +00:00
|
|
|
* @return bool True if whitelisted; otherwise false
|
2011-03-14 23:44:41 +00:00
|
|
|
*/
|
2008-01-08 18:00:59 +00:00
|
|
|
public function isWhitelisted( $title, $action = 'edit' ) {
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( !( $title instanceof Title ) ) {
|
2009-05-17 14:12:38 +00:00
|
|
|
$title = Title::newFromText( $title );
|
2008-01-08 18:00:59 +00:00
|
|
|
}
|
|
|
|
$whitelist = $this->getWhitelist();
|
2012-08-29 13:53:38 +00:00
|
|
|
foreach ( $whitelist as $item ) {
|
2013-09-08 04:24:56 +00:00
|
|
|
if ( $item->matches( $title->getFullText(), $action ) ) {
|
2008-01-08 18:00:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2011-03-22 22:30:23 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
|
|
|
* Get the current blacklist
|
|
|
|
*
|
2015-09-11 00:08:09 +00:00
|
|
|
* @return TitleBlacklistEntry[]
|
2011-03-14 23:44:41 +00:00
|
|
|
*/
|
2007-12-08 21:06:21 +00:00
|
|
|
public function getBlacklist() {
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( is_null( $this->mBlacklist ) ) {
|
2007-12-08 21:06:21 +00:00
|
|
|
$this->load();
|
|
|
|
}
|
|
|
|
return $this->mBlacklist;
|
|
|
|
}
|
2011-03-22 22:30:23 +00:00
|
|
|
|
2011-08-22 20:37:26 +00:00
|
|
|
/**
|
2008-08-09 01:54:39 +00:00
|
|
|
* Get the current whitelist
|
|
|
|
*
|
|
|
|
* @return Array of TitleBlacklistEntry items
|
2011-03-14 23:44:41 +00:00
|
|
|
*/
|
2008-01-08 18:00:59 +00:00
|
|
|
public function getWhitelist() {
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( is_null( $this->mWhitelist ) ) {
|
2008-01-08 18:00:59 +00:00
|
|
|
$this->loadWhitelist();
|
|
|
|
}
|
|
|
|
return $this->mWhitelist;
|
|
|
|
}
|
2011-03-22 22:30:23 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
|
|
|
* Get the text of a blacklist source via HTTP
|
|
|
|
*
|
2011-08-22 20:37:26 +00:00
|
|
|
* @param $url string URL of the blacklist source
|
|
|
|
* @return string The content of the blacklist source as a string
|
2011-03-14 23:44:41 +00:00
|
|
|
*/
|
2008-08-09 01:54:39 +00:00
|
|
|
private static function getHttp( $url ) {
|
2007-12-31 23:02:22 +00:00
|
|
|
global $messageMemc, $wgTitleBlacklistCaching;
|
|
|
|
$key = "title_blacklist_source:" . md5( $url ); // Global shared
|
|
|
|
$warnkey = wfMemcKey( "titleblacklistwarning", md5( $url ) );
|
2007-12-19 18:35:44 +00:00
|
|
|
$result = $messageMemc->get( $key );
|
|
|
|
$warn = $messageMemc->get( $warnkey );
|
|
|
|
if ( !is_string( $result ) || ( !$warn && !mt_rand( 0, $wgTitleBlacklistCaching['warningchance'] ) ) ) {
|
|
|
|
$result = Http::get( $url );
|
|
|
|
$messageMemc->set( $warnkey, 1, $wgTitleBlacklistCaching['warningexpiry'] );
|
|
|
|
$messageMemc->set( $key, $result, $wgTitleBlacklistCaching['expiry'] );
|
|
|
|
}
|
|
|
|
return $result;
|
|
|
|
}
|
2011-03-22 22:30:23 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
|
|
|
* Invalidate the blacklist cache
|
|
|
|
*/
|
2007-12-23 09:47:36 +00:00
|
|
|
public function invalidate() {
|
2015-04-29 21:25:24 +00:00
|
|
|
$cache = ObjectCache::getMainWANInstance();
|
|
|
|
$cache->delete( wfMemcKey( "title_blacklist_entries" ) );
|
2007-12-23 09:47:36 +00:00
|
|
|
}
|
2011-08-22 20:37:26 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
|
|
|
* Validate a new blacklist
|
|
|
|
*
|
2011-08-22 20:37:26 +00:00
|
|
|
* @param $blacklist array
|
2008-08-09 01:54:39 +00:00
|
|
|
* @return Array of bad entries; empty array means blacklist is valid
|
|
|
|
*/
|
2007-12-23 09:47:36 +00:00
|
|
|
public function validate( $blacklist ) {
|
|
|
|
$badEntries = array();
|
2012-08-29 13:53:38 +00:00
|
|
|
foreach ( $blacklist as $e ) {
|
2007-12-23 09:47:36 +00:00
|
|
|
wfSuppressWarnings();
|
|
|
|
$regex = $e->getRegex();
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( preg_match( "/{$regex}/u", '' ) === false ) {
|
2007-12-23 09:47:36 +00:00
|
|
|
$badEntries[] = $e->getRaw();
|
2011-03-22 23:07:21 +00:00
|
|
|
}
|
2007-12-23 09:47:36 +00:00
|
|
|
wfRestoreWarnings();
|
|
|
|
}
|
|
|
|
return $badEntries;
|
|
|
|
}
|
2011-03-22 22:30:23 +00:00
|
|
|
|
2010-11-08 21:55:05 +00:00
|
|
|
/**
|
|
|
|
* Inidcates whether user can override blacklist on certain action.
|
2011-08-22 20:37:26 +00:00
|
|
|
*
|
2010-11-08 21:55:05 +00:00
|
|
|
* @param $action Action
|
2011-08-22 20:37:26 +00:00
|
|
|
*
|
|
|
|
* @return bool
|
2010-11-08 21:55:05 +00:00
|
|
|
*/
|
2011-09-22 06:10:45 +00:00
|
|
|
public static function userCanOverride( $user, $action ) {
|
|
|
|
return $user->isAllowed( 'tboverride' ) ||
|
|
|
|
( $action == 'new-account' && $user->isAllowed( 'tboverride-account' ) );
|
2010-11-08 21:55:05 +00:00
|
|
|
}
|
2007-12-10 19:02:38 +00:00
|
|
|
}
|
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents a title blacklist entry
|
|
|
|
*/
|
2007-12-10 19:02:38 +00:00
|
|
|
class TitleBlacklistEntry {
|
|
|
|
private
|
2012-05-24 23:55:22 +00:00
|
|
|
$mRaw, ///< Raw line
|
|
|
|
$mRegex, ///< Regular expression to match
|
|
|
|
$mParams, ///< Parameters for this entry
|
|
|
|
$mFormatVersion, ///< Entry format version
|
|
|
|
$mSource; ///< Source of this entry
|
2007-12-10 19:02:38 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
|
|
|
* Construct a new TitleBlacklistEntry.
|
|
|
|
*
|
2012-09-24 09:24:32 +00:00
|
|
|
* @param $regex string Regular expression to match
|
|
|
|
* @param $params array Parameters for this entry
|
|
|
|
* @param $raw string Raw contents of this line
|
2008-08-09 01:54:39 +00:00
|
|
|
*/
|
2012-05-24 23:55:22 +00:00
|
|
|
private function __construct( $regex, $params, $raw, $source ) {
|
2007-12-10 19:02:38 +00:00
|
|
|
$this->mRaw = $raw;
|
|
|
|
$this->mRegex = $regex;
|
|
|
|
$this->mParams = $params;
|
2008-01-08 18:00:59 +00:00
|
|
|
$this->mFormatVersion = TitleBlacklist::VERSION;
|
2012-05-24 23:55:22 +00:00
|
|
|
$this->mSource = $source;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns whether this entry is capable of filtering new accounts.
|
|
|
|
*/
|
|
|
|
private function filtersNewAccounts() {
|
|
|
|
global $wgTitleBlacklistUsernameSources;
|
|
|
|
|
|
|
|
if( $wgTitleBlacklistUsernameSources === '*' ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !$wgTitleBlacklistUsernameSources ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !is_array( $wgTitleBlacklistUsernameSources ) ) {
|
2015-01-10 03:09:06 +00:00
|
|
|
throw new Exception(
|
2012-05-24 23:55:22 +00:00
|
|
|
'$wgTitleBlacklistUsernameSources must be "*", false or an array' );
|
|
|
|
}
|
|
|
|
|
|
|
|
return in_array( $this->mSource, $wgTitleBlacklistUsernameSources, true );
|
2007-12-10 19:02:38 +00:00
|
|
|
}
|
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
2016-05-17 22:35:30 +00:00
|
|
|
* Check whether a user can perform the specified action on the specified Title
|
2008-08-09 01:54:39 +00:00
|
|
|
*
|
2016-05-17 22:35:30 +00:00
|
|
|
* @param string $title Title to check
|
|
|
|
* @param string $action Action to check
|
2011-08-22 20:37:26 +00:00
|
|
|
* @return bool TRUE if the the regex matches the title, and is not overridden
|
2011-03-23 16:30:49 +00:00
|
|
|
* else false if it doesn't match (or was overridden)
|
2008-08-09 01:54:39 +00:00
|
|
|
*/
|
2010-11-08 21:55:05 +00:00
|
|
|
public function matches( $title, $action ) {
|
2016-05-17 22:35:30 +00:00
|
|
|
if ( $title == '' ) {
|
2011-09-20 00:11:20 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-05-24 23:55:22 +00:00
|
|
|
|
2016-05-17 22:35:30 +00:00
|
|
|
if ( $action === 'new-account' && !$this->filtersNewAccounts() ) {
|
2012-05-24 23:55:22 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-05-17 22:35:30 +00:00
|
|
|
if ( isset( $this->mParams['antispoof'] )
|
|
|
|
&& is_callable( 'AntiSpoof::checkUnicodeString' )
|
|
|
|
) {
|
|
|
|
if ( $action === 'edit' ) {
|
|
|
|
// Use process cache for frequently edited pages
|
|
|
|
$cache = ObjectCache::getMainWANInstance();
|
|
|
|
list( $ok, $norm ) = $cache->getWithSetCallback(
|
|
|
|
$cache->makeKey( 'titleblacklist', 'normalized-unicode', md5( $title ) ),
|
|
|
|
$cache::TTL_MONTH,
|
|
|
|
function () use ( $title ) {
|
|
|
|
return AntiSpoof::checkUnicodeString( $title );
|
|
|
|
}
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
list( $ok, $norm ) = AntiSpoof::checkUnicodeString( $title );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( $ok === "OK" ) {
|
2013-09-08 04:24:56 +00:00
|
|
|
list( $ver, $title ) = explode( ':', $norm, 2 );
|
|
|
|
} else {
|
|
|
|
wfDebugLog( 'TitleBlacklist', 'AntiSpoof could not normalize "' . $title . '".' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-23 09:47:36 +00:00
|
|
|
wfSuppressWarnings();
|
2016-05-17 22:35:30 +00:00
|
|
|
$match = preg_match(
|
|
|
|
"/^(?:{$this->mRegex})$/us" . ( isset( $this->mParams['casesensitive'] ) ? '' : 'i' ),
|
|
|
|
$title
|
|
|
|
);
|
2007-12-23 09:47:36 +00:00
|
|
|
wfRestoreWarnings();
|
2011-03-14 20:51:13 +00:00
|
|
|
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( $match ) {
|
|
|
|
if ( isset( $this->mParams['moveonly'] ) && $action != 'move' ) {
|
2011-03-22 23:07:21 +00:00
|
|
|
return false;
|
2008-05-21 23:23:24 +00:00
|
|
|
}
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( isset( $this->mParams['newaccountonly'] ) && $action != 'new-account' ) {
|
2011-03-22 23:07:21 +00:00
|
|
|
return false;
|
2008-08-09 01:54:39 +00:00
|
|
|
}
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( !isset( $this->mParams['noedit'] ) && $action == 'edit' ) {
|
2011-03-22 23:07:21 +00:00
|
|
|
return false;
|
2007-12-10 19:02:38 +00:00
|
|
|
}
|
2008-05-22 01:35:48 +00:00
|
|
|
if ( isset( $this->mParams['reupload'] ) && $action == 'upload' ) {
|
|
|
|
// Special:Upload also checks 'create' permissions when not reuploading
|
2011-03-22 23:07:21 +00:00
|
|
|
return false;
|
2008-04-20 21:21:16 +00:00
|
|
|
}
|
2011-03-22 23:07:21 +00:00
|
|
|
return true;
|
2007-12-10 19:02:38 +00:00
|
|
|
}
|
2016-05-17 22:35:30 +00:00
|
|
|
|
2011-03-22 23:07:21 +00:00
|
|
|
return false;
|
2007-12-10 19:02:38 +00:00
|
|
|
}
|
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
|
|
|
* Create a new TitleBlacklistEntry from a line of text
|
|
|
|
*
|
|
|
|
* @param $line String containing a line of blacklist text
|
2012-09-24 09:24:32 +00:00
|
|
|
* @return TitleBlacklistEntry
|
2008-08-09 01:54:39 +00:00
|
|
|
*/
|
2012-05-24 23:55:22 +00:00
|
|
|
public static function newFromString( $line, $source ) {
|
2007-12-29 04:23:57 +00:00
|
|
|
$raw = $line; // Keep line for raw data
|
2007-12-10 19:02:38 +00:00
|
|
|
$options = array();
|
2007-12-29 04:23:57 +00:00
|
|
|
// Strip comments
|
2007-12-10 19:02:38 +00:00
|
|
|
$line = preg_replace( "/^\\s*([^#]*)\\s*((.*)?)$/", "\\1", $line );
|
|
|
|
$line = trim( $line );
|
2007-12-29 04:23:57 +00:00
|
|
|
// Parse the rest of message
|
2008-05-29 20:23:05 +00:00
|
|
|
preg_match( '/^(.*?)(\s*<([^<>]*)>)?$/', $line, $pockets );
|
2007-12-10 19:02:38 +00:00
|
|
|
@list( $full, $regex, $null, $opts_str ) = $pockets;
|
|
|
|
$regex = trim( $regex );
|
2008-01-03 00:58:52 +00:00
|
|
|
$regex = str_replace( '_', ' ', $regex ); // We'll be matching against text form
|
2007-12-10 19:02:38 +00:00
|
|
|
$opts_str = trim( $opts_str );
|
2007-12-29 04:23:57 +00:00
|
|
|
// Parse opts
|
2007-12-10 19:02:38 +00:00
|
|
|
$opts = preg_split( '/\s*\|\s*/', $opts_str );
|
2012-08-29 13:53:38 +00:00
|
|
|
foreach ( $opts as $opt ) {
|
2007-12-14 17:54:06 +00:00
|
|
|
$opt2 = strtolower( $opt );
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( $opt2 == 'autoconfirmed' ) {
|
2007-12-10 19:02:38 +00:00
|
|
|
$options['autoconfirmed'] = true;
|
|
|
|
}
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( $opt2 == 'moveonly' ) {
|
2008-05-21 23:23:24 +00:00
|
|
|
$options['moveonly'] = true;
|
|
|
|
}
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( $opt2 == 'newaccountonly' ) {
|
2008-08-09 01:54:39 +00:00
|
|
|
$options['newaccountonly'] = true;
|
|
|
|
}
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( $opt2 == 'noedit' ) {
|
2007-12-10 19:02:38 +00:00
|
|
|
$options['noedit'] = true;
|
|
|
|
}
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( $opt2 == 'casesensitive' ) {
|
2007-12-14 17:54:06 +00:00
|
|
|
$options['casesensitive'] = true;
|
|
|
|
}
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( $opt2 == 'reupload' ) {
|
2008-04-20 21:21:16 +00:00
|
|
|
$options['reupload'] = true;
|
|
|
|
}
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( preg_match( '/errmsg\s*=\s*(.+)/i', $opt, $matches ) ) {
|
2007-12-17 18:38:34 +00:00
|
|
|
$options['errmsg'] = $matches[1];
|
|
|
|
}
|
2013-09-08 04:24:56 +00:00
|
|
|
if ( $opt2 == 'antispoof' ) {
|
|
|
|
$options['antispoof'] = true;
|
|
|
|
}
|
2007-12-14 17:54:06 +00:00
|
|
|
}
|
2007-12-29 04:23:57 +00:00
|
|
|
// Process magic words
|
2007-12-17 18:38:34 +00:00
|
|
|
preg_match_all( '/{{\s*([a-z]+)\s*:\s*(.+?)\s*}}/', $regex, $magicwords, PREG_SET_ORDER );
|
2012-08-29 13:53:38 +00:00
|
|
|
foreach ( $magicwords as $mword ) {
|
2007-12-29 04:23:57 +00:00
|
|
|
global $wgParser; // Functions we're calling don't need, nevertheless let's use it
|
2007-12-14 17:54:06 +00:00
|
|
|
switch( strtolower( $mword[1] ) ) {
|
|
|
|
case 'ns':
|
|
|
|
$cpf_result = CoreParserFunctions::ns( $wgParser, $mword[2] );
|
2012-08-29 13:53:38 +00:00
|
|
|
if ( is_string( $cpf_result ) ) {
|
2007-12-29 04:23:57 +00:00
|
|
|
$regex = str_replace( $mword[0], $cpf_result, $regex ); // All result will have the same value, so we can just use str_seplace()
|
2007-12-14 17:54:06 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'int':
|
2012-08-29 13:53:38 +00:00
|
|
|
$cpf_result = wfMessage( $mword[2] )->inContentLanguage()->text();
|
|
|
|
if ( is_string( $cpf_result ) ) {
|
2007-12-14 17:54:06 +00:00
|
|
|
$regex = str_replace( $mword[0], $cpf_result, $regex );
|
|
|
|
}
|
|
|
|
}
|
2007-12-10 19:02:38 +00:00
|
|
|
}
|
2007-12-29 04:23:57 +00:00
|
|
|
// Return result
|
2012-05-24 23:55:22 +00:00
|
|
|
if( $regex ) {
|
|
|
|
return new TitleBlacklistEntry( $regex, $options, $raw, $source );
|
2007-12-10 19:02:38 +00:00
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2011-04-12 00:16:04 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
2012-09-24 09:24:32 +00:00
|
|
|
* @return string This entry's regular expression
|
2008-08-09 01:54:39 +00:00
|
|
|
*/
|
2007-12-10 19:02:38 +00:00
|
|
|
public function getRegex() {
|
|
|
|
return $this->mRegex;
|
|
|
|
}
|
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
2012-09-24 09:24:32 +00:00
|
|
|
* @return string This entry's raw line
|
2008-08-09 01:54:39 +00:00
|
|
|
*/
|
2007-12-10 19:02:38 +00:00
|
|
|
public function getRaw() {
|
|
|
|
return $this->mRaw;
|
|
|
|
}
|
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
2014-01-07 18:08:24 +00:00
|
|
|
* @return array This entry's parameters
|
2008-08-09 01:54:39 +00:00
|
|
|
*/
|
2014-01-07 18:08:24 +00:00
|
|
|
public function getParams() {
|
|
|
|
return $this->mParams;
|
2007-12-10 19:02:38 +00:00
|
|
|
}
|
2007-12-17 18:38:34 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
2012-09-24 09:24:32 +00:00
|
|
|
* @return string Custom message for this entry
|
2008-08-09 01:54:39 +00:00
|
|
|
*/
|
2007-12-17 18:38:34 +00:00
|
|
|
public function getCustomMessage() {
|
|
|
|
return isset( $this->mParams['errmsg'] ) ? $this->mParams['errmsg'] : null;
|
|
|
|
}
|
2011-04-12 00:16:04 +00:00
|
|
|
|
2008-08-09 01:54:39 +00:00
|
|
|
/**
|
2012-09-24 09:24:32 +00:00
|
|
|
* @return string The format version
|
2008-08-09 01:54:39 +00:00
|
|
|
*/
|
2007-12-19 18:35:44 +00:00
|
|
|
public function getFormatVersion() { return $this->mFormatVersion; }
|
2008-08-09 01:54:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the format version
|
|
|
|
*
|
2012-09-24 09:24:32 +00:00
|
|
|
* @param $v string New version to set
|
2008-08-09 01:54:39 +00:00
|
|
|
*/
|
2007-12-19 18:35:44 +00:00
|
|
|
public function setFormatVersion( $v ) { $this->mFormatVersion = $v; }
|
2011-04-12 00:16:04 +00:00
|
|
|
|
2010-11-08 21:55:05 +00:00
|
|
|
/**
|
|
|
|
* Return the error message name for the blacklist entry.
|
2011-08-22 20:37:26 +00:00
|
|
|
*
|
2012-09-24 09:24:32 +00:00
|
|
|
* @param $operation string Operation name (as in titleblacklist-forbidden message name)
|
2011-08-22 20:37:26 +00:00
|
|
|
*
|
2012-09-24 09:24:32 +00:00
|
|
|
* @return string The error message name
|
2010-11-08 21:55:05 +00:00
|
|
|
*/
|
|
|
|
public function getErrorMessage( $operation ) {
|
|
|
|
$message = $this->getCustomMessage();
|
2014-09-24 15:35:26 +00:00
|
|
|
// For grep:
|
|
|
|
// titleblacklist-forbidden-edit, titleblacklist-forbidden-move,
|
|
|
|
// titleblacklist-forbidden-upload, titleblacklist-forbidden-new-account
|
2010-11-08 21:55:05 +00:00
|
|
|
return $message ? $message : "titleblacklist-forbidden-{$operation}";
|
|
|
|
}
|
2008-01-08 18:00:59 +00:00
|
|
|
}
|
2008-08-09 01:54:39 +00:00
|
|
|
|
2010-11-08 21:55:05 +00:00
|
|
|
//@}
|