MediaWiki REL1_34
TitleBlacklist.php
Go to the documentation of this file.
1<?php
11
21 private $mBlacklist = null;
22
24 private $mWhitelist = null;
25
27 protected static $instance = null;
28
29 const VERSION = 3; // Blacklist format
30
36 public static function singleton() {
37 if ( self::$instance === null ) {
38 self::$instance = new self;
39 }
40 return self::$instance;
41 }
42
49 public static function destroySingleton() {
50 if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
51 throw new MWException(
52 'Can not invoke ' . __METHOD__ . '() ' .
53 'out of tests (MW_PHPUNIT_TEST not set).'
54 );
55 }
56
57 self::$instance = null;
58 }
59
63 public function load() {
64 global $wgTitleBlacklistSources, $wgTitleBlacklistCaching;
65
66 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
67 // Try to find something in the cache
68 $cachedBlacklist = $cache->get( $cache->makeKey( 'title_blacklist_entries' ) );
69 if ( is_array( $cachedBlacklist ) && count( $cachedBlacklist ) > 0
70 && ( $cachedBlacklist[0]->getFormatVersion() == self::VERSION )
71 ) {
72 $this->mBlacklist = $cachedBlacklist;
73 return;
74 }
75
76 $sources = $wgTitleBlacklistSources;
77 $sources['local'] = [ 'type' => 'message' ];
78 $this->mBlacklist = [];
79 foreach ( $sources as $sourceName => $source ) {
80 $this->mBlacklist = array_merge(
81 $this->mBlacklist,
82 self::parseBlacklist( self::getBlacklistText( $source ), $sourceName )
83 );
84 }
85 $cache->set( $cache->makeKey( 'title_blacklist_entries' ),
86 $this->mBlacklist, $wgTitleBlacklistCaching['expiry'] );
87 wfDebugLog( 'TitleBlacklist-cache', 'Updated ' . $cache->makeKey( 'title_blacklist_entries' )
88 . ' with ' . count( $this->mBlacklist ) . ' entries.' );
89 }
90
94 public function loadWhitelist() {
95 global $wgTitleBlacklistCaching;
96
97 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
98 $cachedWhitelist = $cache->get( $cache->makeKey( 'title_whitelist_entries' ) );
99 if ( is_array( $cachedWhitelist ) && count( $cachedWhitelist ) > 0
100 && ( $cachedWhitelist[0]->getFormatVersion() != self::VERSION )
101 ) {
102 $this->mWhitelist = $cachedWhitelist;
103 return;
104 }
105 $this->mWhitelist = self::parseBlacklist( wfMessage( 'titlewhitelist' )
106 ->inContentLanguage()->text(), 'whitelist' );
107 $cache->set( $cache->makeKey( 'title_whitelist_entries' ),
108 $this->mWhitelist, $wgTitleBlacklistCaching['expiry'] );
109 }
110
117 private static function getBlacklistText( $source ) {
118 if ( !is_array( $source ) || count( $source ) <= 0 ) {
119 return ''; // Return empty string in error case
120 }
121
122 if ( $source['type'] == 'message' ) {
123 return wfMessage( 'titleblacklist' )->inContentLanguage()->text();
124 } elseif ( $source['type'] == 'localpage' && count( $source ) >= 2 ) {
125 $title = Title::newFromText( $source['src'] );
126 if ( is_null( $title ) ) {
127 return '';
128 }
129 if ( $title->getNamespace() == NS_MEDIAWIKI ) {
130 $msg = wfMessage( $title->getText() )->inContentLanguage();
131 if ( !$msg->isDisabled() ) {
132 return $msg->text();
133 } else {
134 return '';
135 }
136 } else {
137 $page = WikiPage::factory( $title );
138 if ( $page->exists() ) {
139 return ContentHandler::getContentText( $page->getContent() );
140 }
141 }
142 } elseif ( $source['type'] == 'url' && count( $source ) >= 2 ) {
143 return self::getHttp( $source['src'] );
144 } elseif ( $source['type'] == 'file' && count( $source ) >= 2 ) {
145 if ( file_exists( $source['src'] ) ) {
146 return file_get_contents( $source['src'] );
147 } else {
148 return '';
149 }
150 }
151
152 return '';
153 }
154
162 public static function parseBlacklist( $list, $sourceName ) {
163 $lines = preg_split( "/\r?\n/", $list );
164 $result = [];
165 foreach ( $lines as $line ) {
166 $entry = TitleBlacklistEntry::newFromString( $line, $sourceName );
167 if ( $entry ) {
168 $result[] = $entry;
169 }
170 }
171
172 return $result;
173 }
174
186 public function userCannot( $title, $user, $action = 'edit', $override = true ) {
187 $entry = $this->isBlacklisted( $title, $action );
188 if ( !$entry ) {
189 return false;
190 }
191 $params = $entry->getParams();
192 if ( isset( $params['autoconfirmed'] ) && $user->isAllowed( 'autoconfirmed' ) ) {
193 return false;
194 }
195 if ( $override && self::userCanOverride( $user, $action ) ) {
196 return false;
197 }
198 return $entry;
199 }
200
210 public function isBlacklisted( $title, $action = 'edit' ) {
211 if ( !( $title instanceof Title ) ) {
212 $title = Title::newFromText( $title );
213 if ( !( $title instanceof Title ) ) {
214 // The fact that the page name is invalid will stop whatever
215 // action is going through. No sense in doing more work here.
216 return false;
217 }
218 }
219 $blacklist = $this->getBlacklist();
220 $autoconfirmedItem = false;
221 foreach ( $blacklist as $item ) {
222 if ( $item->matches( $title->getFullText(), $action ) ) {
223 if ( $this->isWhitelisted( $title, $action ) ) {
224 return false;
225 }
226 $params = $item->getParams();
227 if ( !isset( $params['autoconfirmed'] ) ) {
228 return $item;
229 }
230 if ( !$autoconfirmedItem ) {
231 $autoconfirmedItem = $item;
232 }
233 }
234 }
235 return $autoconfirmedItem;
236 }
237
246 public function isWhitelisted( $title, $action = 'edit' ) {
247 if ( !( $title instanceof Title ) ) {
248 $title = Title::newFromText( $title );
249 }
250 $whitelist = $this->getWhitelist();
251 foreach ( $whitelist as $item ) {
252 if ( $item->matches( $title->getFullText(), $action ) ) {
253 return true;
254 }
255 }
256 return false;
257 }
258
264 public function getBlacklist() {
265 if ( is_null( $this->mBlacklist ) ) {
266 $this->load();
267 }
268 return $this->mBlacklist;
269 }
270
276 public function getWhitelist() {
277 if ( is_null( $this->mWhitelist ) ) {
278 $this->loadWhitelist();
279 }
280 return $this->mWhitelist;
281 }
282
289 private static function getHttp( $url ) {
290 global $messageMemc, $wgTitleBlacklistCaching;
291
292 $key = 'title_blacklist_source:' . md5( $url ); // Global shared
293 $warnkey = $messageMemc->makeKey( 'titleblacklistwarning', md5( $url ) );
294 $result = $messageMemc->get( $key );
295 $warn = $messageMemc->get( $warnkey );
296
297 if ( !is_string( $result )
298 || ( !$warn && !mt_rand( 0, $wgTitleBlacklistCaching['warningchance'] ) )
299 ) {
300 $result = Http::get( $url );
301 $messageMemc->set( $warnkey, 1, $wgTitleBlacklistCaching['warningexpiry'] );
302 $messageMemc->set( $key, $result, $wgTitleBlacklistCaching['expiry'] );
303 }
304
305 return $result;
306 }
307
311 public function invalidate() {
312 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
313 $cache->delete( $cache->makeKey( 'title_blacklist_entries' ) );
314 }
315
323 public function validate( array $blacklist ) {
324 $badEntries = [];
325 foreach ( $blacklist as $e ) {
326 Wikimedia\suppressWarnings();
327 $regex = $e->getRegex();
328 if ( preg_match( "/{$regex}/u", '' ) === false ) {
329 $badEntries[] = $e->getRaw();
330 }
331 Wikimedia\restoreWarnings();
332 }
333 return $badEntries;
334 }
335
344 public static function userCanOverride( $user, $action ) {
345 return $user->isAllowed( 'tboverride' ) ||
346 ( $action == 'new-account' && $user->isAllowed( 'tboverride-account' ) );
347 }
348}
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
$messageMemc
Definition Setup.php:791
$line
Definition cdb.php:59
MediaWiki exception.
MediaWikiServices is the service locator for the application scope of MediaWiki.
Represents a title blacklist entry.
static newFromString( $line, $source)
Create a new TitleBlacklistEntry from a line of text.
Implements a title blacklist for MediaWiki.
static destroySingleton()
Destroy/reset the current singleton instance.
TitleBlacklistEntry[] $mWhitelist
getBlacklist()
Get the current blacklist.
getWhitelist()
Get the current whitelist.
invalidate()
Invalidate the blacklist cache.
static singleton()
Get an instance of this class.
userCannot( $title, $user, $action='edit', $override=true)
Check whether the blacklist restricts given user performing a specific action on the given Title.
static userCanOverride( $user, $action)
Inidcates whether user can override blacklist on certain action.
static parseBlacklist( $list, $sourceName)
Parse blacklist from a string.
static getHttp( $url)
Get the text of a blacklist source via HTTP.
load()
Load all configured blacklist sources.
TitleBlacklistEntry[] $mBlacklist
static TitleBlacklist $instance
validate(array $blacklist)
Validate a new blacklist.
isWhitelisted( $title, $action='edit')
Check whether it has been explicitly whitelisted that the current User may perform a specific action ...
loadWhitelist()
Load local whitelist.
isBlacklisted( $title, $action='edit')
Check whether the blacklist restricts performing a specific action on the given Title.
static getBlacklistText( $source)
Get the text of a blacklist from a specified source.
Represents a title within MediaWiki.
Definition Title.php:42
const NS_MEDIAWIKI
Definition Defines.php:77
$cache
Definition mcc.php:33
$source
$lines
Definition router.php:61