MediaWiki 1.43.1
BlockManager.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\Block;
22
23use LogicException;
37use MWCryptHash;
38use Psr\Log\LoggerInterface;
39use Wikimedia\IPSet;
40use Wikimedia\IPUtils;
41
52 public const CONSTRUCTOR_OPTIONS = [
62 ];
63
64 private ServiceOptions $options;
65 private UserFactory $userFactory;
66 private UserIdentityUtils $userIdentityUtils;
67 private LoggerInterface $logger;
68 private HookRunner $hookRunner;
69 private DatabaseBlockStore $blockStore;
70 private ProxyLookup $proxyLookup;
71
72 private BlockCache $userBlockCache;
73 private BlockCache $createAccountBlockCache;
74
75 public function __construct(
76 ServiceOptions $options,
77 UserFactory $userFactory,
78 UserIdentityUtils $userIdentityUtils,
79 LoggerInterface $logger,
80 HookContainer $hookContainer,
81 DatabaseBlockStore $blockStore,
82 ProxyLookup $proxyLookup
83 ) {
84 $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
85 $this->options = $options;
86 $this->userFactory = $userFactory;
87 $this->userIdentityUtils = $userIdentityUtils;
88 $this->logger = $logger;
89 $this->hookRunner = new HookRunner( $hookContainer );
90 $this->blockStore = $blockStore;
91 $this->proxyLookup = $proxyLookup;
92
93 $this->userBlockCache = new BlockCache;
94 $this->createAccountBlockCache = new BlockCache;
95 }
96
132 public function getUserBlock(
133 UserIdentity $user,
134 $request,
135 $fromReplica,
136 $disableIpBlockExemptChecking = false
137 ) {
138 // If this is the global user, they may be affected by IP blocks (case #1),
139 // or they may be exempt (case #2). If affected, look for additional blocks
140 // against the IP address and referenced in a cookie.
141 $checkIpBlocks = $request &&
142 // Because calling getBlock within Autopromote leads back to here,
143 // thus causing a infinite recursion. We fix this by not checking for
144 // ipblock-exempt when calling getBlock within Autopromote.
145 // See T270145.
146 !$disableIpBlockExemptChecking &&
147 !$this->isIpBlockExempt( $user );
148
149 return $this->getBlock(
150 $user,
151 $checkIpBlocks ? $request : null,
152 $fromReplica
153 );
154 }
155
173 public function getBlock(
174 UserIdentity $user,
175 ?WebRequest $request,
176 $fromReplica = true
177 ): ?AbstractBlock {
178 $fromPrimary = !$fromReplica;
179 $ip = null;
180
181 // TODO: normalise the fromPrimary parameter when replication is not configured.
182 // Maybe DatabaseBlockStore can tell us about the LoadBalancer configuration.
183 $cacheKey = new BlockCacheKey(
184 $request,
185 $user,
186 $fromPrimary
187 );
188 $block = $this->userBlockCache->get( $cacheKey );
189 if ( $block !== null ) {
190 $this->logger->debug( "Block cache hit with key {$cacheKey}" );
191 return $block ?: null;
192 }
193 $this->logger->debug( "Block cache miss with key {$cacheKey}" );
194
195 if ( $request ) {
196
197 // Case #1: checking the global user, including IP blocks
198 $ip = $request->getIP();
199 // For soft blocks, i.e. blocks that don't block logged-in users,
200 // temporary users are treated as anon users, and are blocked.
201 $applySoftBlocks = !$this->userIdentityUtils->isNamed( $user );
202
203 $xff = $request->getHeader( 'X-Forwarded-For' );
204
205 $blocks = array_merge(
206 $this->blockStore->newListFromTarget( $user, $ip, $fromPrimary ),
207 $this->getSystemIpBlocks( $ip, $applySoftBlocks ),
208 $this->getXffBlocks( $ip, $xff, $applySoftBlocks, $fromPrimary ),
209 $this->getCookieBlock( $user, $request )
210 );
211 } else {
212
213 // Case #2: checking the global user, but they are exempt from IP blocks
214 // and cookie blocks, so we only check for a user account block.
215 // Case #3: checking whether another user's account is blocked.
216 $blocks = $this->blockStore->newListFromTarget( $user, null, $fromPrimary );
217
218 }
219
220 $block = $this->createGetBlockResult( $ip, $blocks );
221
222 $legacyUser = $this->userFactory->newFromUserIdentity( $user );
223 $this->hookRunner->onGetUserBlock( clone $legacyUser, $ip, $block );
224
225 $this->userBlockCache->set( $cacheKey, $block ?: false );
226 return $block;
227 }
228
234 public function clearUserCache( UserIdentity $user ) {
235 $this->userBlockCache->clearUser( $user );
236 $this->createAccountBlockCache->clearUser( $user );
237 }
238
250 public function getCreateAccountBlock(
251 UserIdentity $user,
252 ?WebRequest $request,
253 $fromReplica
254 ) {
255 $key = new BlockCacheKey( $request, $user, $fromReplica );
256 $cachedBlock = $this->createAccountBlockCache->get( $key );
257 if ( $cachedBlock !== null ) {
258 $this->logger->debug( "Create account block cache hit with key {$key}" );
259 return $cachedBlock ?: null;
260 }
261 $this->logger->debug( "Create account block cache miss with key {$key}" );
262
263 $applicableBlocks = [];
264 $userBlock = $this->getBlock( $user, $request, $fromReplica );
265 if ( $userBlock ) {
266 $applicableBlocks = $userBlock->toArray();
267 }
268
269 // T15611: if the IP address the user is trying to create an account from is
270 // blocked with createaccount disabled, prevent new account creation there even
271 // when the user is logged in
272 if ( $request ) {
273 $ipBlock = $this->blockStore->newFromTarget(
274 null, $request->getIP()
275 );
276 if ( $ipBlock ) {
277 $applicableBlocks = array_merge( $applicableBlocks, $ipBlock->toArray() );
278 }
279 }
280
281 foreach ( $applicableBlocks as $i => $block ) {
282 if ( !$block->appliesToRight( 'createaccount' ) ) {
283 unset( $applicableBlocks[$i] );
284 }
285 }
286 $result = $this->createGetBlockResult(
287 $request ? $request->getIP() : null,
288 $applicableBlocks
289 );
290 $this->createAccountBlockCache->set( $key, $result ?: false );
291 return $result;
292 }
293
310 public function filter( ?Block $block, $callback ) {
311 if ( !$block ) {
312 return null;
313 } elseif ( $block instanceof CompositeBlock ) {
314 $blocks = $block->getOriginalBlocks();
315 $originalCount = count( $blocks );
316 foreach ( $blocks as $i => $originalBlock ) {
317 if ( !$callback( $originalBlock ) ) {
318 unset( $blocks[$i] );
319 }
320 }
321 if ( !$blocks ) {
322 return null;
323 } elseif ( count( $blocks ) === 1 ) {
324 return $blocks[ array_key_first( $blocks ) ];
325 } elseif ( count( $blocks ) === $originalCount ) {
326 return $block;
327 } else {
328 return $block->withOriginalBlocks( array_values( $blocks ) );
329 }
330 } elseif ( !$callback( $block ) ) {
331 return null;
332 } else {
333 return $block;
334 }
335 }
336
342 private function isIpBlockExempt( UserIdentity $user ) {
343 return MediaWikiServices::getInstance()->getPermissionManager()
344 ->userHasRight( $user, 'ipblock-exempt' );
345 }
346
352 private function createGetBlockResult( ?string $ip, array $blocks ): ?AbstractBlock {
353 // Filter out any duplicated blocks, e.g. from the cookie
354 $blocks = $this->getUniqueBlocks( $blocks );
355
356 if ( count( $blocks ) === 0 ) {
357 return null;
358 } elseif ( count( $blocks ) === 1 ) {
359 return $blocks[ 0 ];
360 } else {
361 $compositeBlock = CompositeBlock::createFromBlocks( ...$blocks );
362 $compositeBlock->setTarget( $ip );
363 return $compositeBlock;
364 }
365 }
366
376 public function getIpBlock( string $ip, bool $fromReplica ): ?AbstractBlock {
377 if ( !IPUtils::isValid( $ip ) ) {
378 return null;
379 }
380
381 $blocks = array_merge(
382 $this->blockStore->newListFromTarget( $ip, $ip, !$fromReplica ),
383 $this->getSystemIpBlocks( $ip, true )
384 );
385
386 return $this->createGetBlockResult( $ip, $blocks );
387 }
388
396 private function getCookieBlock( UserIdentity $user, WebRequest $request ): array {
397 $cookieBlock = $this->getBlockFromCookieValue( $user, $request );
398
399 return $cookieBlock instanceof DatabaseBlock ? [ $cookieBlock ] : [];
400 }
401
409 private function getSystemIpBlocks( string $ip, bool $applySoftBlocks ): array {
410 $blocks = [];
411
412 // Proxy blocking
413 if ( !in_array( $ip, $this->options->get( MainConfigNames::ProxyWhitelist ) ) ) {
414 // Local list
415 if ( $this->isLocallyBlockedProxy( $ip ) ) {
416 $blocks[] = new SystemBlock( [
417 'reason' => new Message( 'proxyblockreason' ),
418 'address' => $ip,
419 'systemBlock' => 'proxy',
420 ] );
421 } elseif ( $applySoftBlocks && $this->isDnsBlacklisted( $ip ) ) {
422 $blocks[] = new SystemBlock( [
423 'reason' => new Message( 'sorbsreason' ),
424 'address' => $ip,
425 'anonOnly' => true,
426 'systemBlock' => 'dnsbl',
427 ] );
428 }
429 }
430
431 // Soft blocking
432 if ( $applySoftBlocks && IPUtils::isInRanges( $ip, $this->options->get( MainConfigNames::SoftBlockRanges ) ) ) {
433 $blocks[] = new SystemBlock( [
434 'address' => $ip,
435 'reason' => new Message( 'softblockrangesreason', [ $ip ] ),
436 'anonOnly' => true,
437 'systemBlock' => 'wgSoftBlockRanges',
438 ] );
439 }
440
441 return $blocks;
442 }
443
455 private function getXffBlocks(
456 string $ip,
457 string $xff,
458 bool $applySoftBlocks,
459 bool $fromPrimary
460 ): array {
461 // (T25343) Apply IP blocks to the contents of XFF headers, if enabled
462 if ( $this->options->get( MainConfigNames::ApplyIpBlocksToXff )
463 && !in_array( $ip, $this->options->get( MainConfigNames::ProxyWhitelist ) )
464 ) {
465 $xff = array_map( 'trim', explode( ',', $xff ) );
466 $xff = array_diff( $xff, [ $ip ] );
467 $xffblocks = $this->getBlocksForIPList( $xff, $applySoftBlocks, $fromPrimary );
468
469 // (T285159) Exclude autoblocks from XFF headers to prevent spoofed
470 // headers uncovering the IPs of autoblocked users
471 $xffblocks = array_filter( $xffblocks, static function ( $block ) {
472 return $block->getType() !== Block::TYPE_AUTO;
473 } );
474
475 return $xffblocks;
476 }
477
478 return [];
479 }
480
493 public function getBlocksForIPList( array $ipChain, bool $applySoftBlocks, bool $fromPrimary ) {
494 if ( $ipChain === [] ) {
495 return [];
496 }
497
498 $ips = [];
499 foreach ( array_unique( $ipChain ) as $ipaddr ) {
500 // Discard invalid IP addresses. Since XFF can be spoofed and we do not
501 // necessarily trust the header given to us, make sure that we are only
502 // checking for blocks on well-formatted IP addresses (IPv4 and IPv6).
503 // Do not treat private IP spaces as special as it may be desirable for wikis
504 // to block those IP ranges in order to stop misbehaving proxies that spoof XFF.
505 if ( !IPUtils::isValid( $ipaddr ) ) {
506 continue;
507 }
508 // Don't check trusted IPs (includes local CDNs which will be in every request)
509 if ( $this->proxyLookup->isTrustedProxy( $ipaddr ) ) {
510 continue;
511 }
512 $ips[] = $ipaddr;
513 }
514 return $this->blockStore->newListFromIPs( $ips, $applySoftBlocks, $fromPrimary );
515 }
516
527 private function getUniqueBlocks( array $blocks ) {
528 $systemBlocks = [];
529 $databaseBlocks = [];
530
531 foreach ( $blocks as $block ) {
532 if ( $block instanceof SystemBlock ) {
533 $systemBlocks[] = $block;
534 } elseif ( $block->getType() === DatabaseBlock::TYPE_AUTO ) {
536 '@phan-var DatabaseBlock $block';
537 if ( !isset( $databaseBlocks[$block->getParentBlockId()] ) ) {
538 $databaseBlocks[$block->getParentBlockId()] = $block;
539 }
540 } else {
541 // @phan-suppress-next-line PhanTypeMismatchDimAssignment getId is not null here
542 $databaseBlocks[$block->getId()] = $block;
543 }
544 }
545
546 return array_values( array_merge( $systemBlocks, $databaseBlocks ) );
547 }
548
560 private function getBlockFromCookieValue(
561 UserIdentity $user,
562 WebRequest $request
563 ) {
564 $cookieValue = $request->getCookie( 'BlockID' );
565 if ( $cookieValue === null ) {
566 return false;
567 }
568
569 $blockCookieId = $this->getIdFromCookieValue( $cookieValue );
570 if ( $blockCookieId !== null ) {
571 $block = $this->blockStore->newFromID( $blockCookieId );
572 if (
573 $block instanceof DatabaseBlock &&
574 $this->shouldApplyCookieBlock( $block, !$user->isRegistered() )
575 ) {
576 return $block;
577 }
578 }
579
580 return false;
581 }
582
590 private function shouldApplyCookieBlock( DatabaseBlock $block, $isAnon ) {
591 if ( !$block->isExpired() ) {
592 switch ( $block->getType() ) {
593 case DatabaseBlock::TYPE_IP:
594 case DatabaseBlock::TYPE_RANGE:
595 // If block is type IP or IP range, load only
596 // if user is not logged in (T152462)
597 return $isAnon &&
598 $this->options->get( MainConfigNames::CookieSetOnIpBlock );
599 case DatabaseBlock::TYPE_USER:
600 return $block->isAutoblocking() &&
601 $this->options->get( MainConfigNames::CookieSetOnAutoblock );
602 default:
603 return false;
604 }
605 }
606 return false;
607 }
608
615 private function isLocallyBlockedProxy( $ip ) {
616 $proxyList = $this->options->get( MainConfigNames::ProxyList );
617 if ( !$proxyList ) {
618 return false;
619 }
620
621 if ( !is_array( $proxyList ) ) {
622 // Load values from the specified file
623 $proxyList = array_map( 'trim', file( $proxyList ) );
624 }
625
626 $proxyListIPSet = new IPSet( $proxyList );
627 return $proxyListIPSet->match( $ip );
628 }
629
637 public function isDnsBlacklisted( $ip, $checkAllowed = false ) {
638 if ( !$this->options->get( MainConfigNames::EnableDnsBlacklist ) ||
639 ( $checkAllowed && in_array( $ip, $this->options->get( MainConfigNames::ProxyWhitelist ) ) )
640 ) {
641 return false;
642 }
643
644 return $this->inDnsBlacklist( $ip, $this->options->get( MainConfigNames::DnsBlacklistUrls ) );
645 }
646
654 private function inDnsBlacklist( $ip, array $bases ) {
655 $found = false;
656 // @todo FIXME: IPv6 ??? (https://bugs.php.net/bug.php?id=33170)
657 if ( IPUtils::isIPv4( $ip ) ) {
658 // Reverse IP, T23255
659 $ipReversed = implode( '.', array_reverse( explode( '.', $ip ) ) );
660
661 foreach ( $bases as $base ) {
662 // Make hostname
663 // If we have an access key, use that too (ProjectHoneypot, etc.)
664 $basename = $base;
665 if ( is_array( $base ) ) {
666 if ( count( $base ) >= 2 ) {
667 // Access key is 1, base URL is 0
668 $hostname = "{$base[1]}.$ipReversed.{$base[0]}";
669 } else {
670 $hostname = "$ipReversed.{$base[0]}";
671 }
672 $basename = $base[0];
673 } else {
674 $hostname = "$ipReversed.$base";
675 }
676
677 // Send query
678 $ipList = $this->checkHost( $hostname );
679
680 if ( $ipList ) {
681 $this->logger->info(
682 'Hostname {hostname} is {ipList}, it\'s a proxy says {basename}!',
683 [
684 'hostname' => $hostname,
685 'ipList' => $ipList[0],
686 'basename' => $basename,
687 ]
688 );
689 $found = true;
690 break;
691 }
692
693 $this->logger->debug( "Requested $hostname, not found in $basename." );
694 }
695 }
696
697 return $found;
698 }
699
706 protected function checkHost( $hostname ) {
707 return gethostbynamel( $hostname );
708 }
709
729 public function trackBlockWithCookie( User $user, WebResponse $response ) {
730 if ( !$this->options->get( MainConfigNames::CookieSetOnIpBlock ) &&
731 !$this->options->get( MainConfigNames::CookieSetOnAutoblock ) ) {
732 // Cookie blocks are disabled, return early to prevent executing unnecessary logic.
733 return;
734 }
735
736 $request = $user->getRequest();
737
738 if ( $request->getCookie( 'BlockID' ) !== null ) {
739 $cookieBlock = $this->getBlockFromCookieValue( $user, $request );
740 if ( $cookieBlock && $this->shouldApplyCookieBlock( $cookieBlock, $user->isAnon() ) ) {
741 return;
742 }
743 // The block pointed to by the cookie is invalid or should not be tracked.
744 $this->clearBlockCookie( $response );
745 }
746
747 if ( !$user->isSafeToLoad() ) {
748 // Prevent a circular dependency by not allowing this method to be called
749 // before or while the user is being loaded.
750 // E.g. User > BlockManager > Block > Message > getLanguage > User.
751 // See also T180050 and T226777.
752 throw new LogicException( __METHOD__ . ' requires a loaded User object' );
753 }
754 if ( $response->headersSent() ) {
755 throw new LogicException( __METHOD__ . ' must be called pre-send' );
756 }
757
758 $block = $user->getBlock();
759 $isAnon = $user->isAnon();
760
761 if ( $block ) {
762 foreach ( $block->toArray() as $originalBlock ) {
763 // TODO: Improve on simply tracking the first trackable block (T225654)
764 if ( $originalBlock instanceof DatabaseBlock
765 && $this->shouldTrackBlockWithCookie( $originalBlock, $isAnon )
766 ) {
767 $this->setBlockCookie( $originalBlock, $response );
768 return;
769 }
770 }
771 }
772 }
773
782 private function setBlockCookie( DatabaseBlock $block, WebResponse $response ) {
783 // Calculate the default expiry time.
784 $maxExpiryTime = wfTimestamp( TS_MW, (int)wfTimestamp() + ( 24 * 60 * 60 ) );
785
786 // Use the block's expiry time only if it's less than the default.
787 $expiryTime = $block->getExpiry();
788 if ( $expiryTime === 'infinity' || $expiryTime > $maxExpiryTime ) {
789 $expiryTime = $maxExpiryTime;
790 }
791
792 // Set the cookie
793 $expiryValue = (int)wfTimestamp( TS_UNIX, $expiryTime );
794 $cookieOptions = [ 'httpOnly' => false ];
795 $cookieValue = $this->getCookieValue( $block );
796 $response->setCookie( 'BlockID', $cookieValue, $expiryValue, $cookieOptions );
797 }
798
806 private function shouldTrackBlockWithCookie( DatabaseBlock $block, $isAnon ) {
807 switch ( $block->getType() ) {
808 case DatabaseBlock::TYPE_IP:
809 case DatabaseBlock::TYPE_RANGE:
810 return $isAnon && $this->options->get( MainConfigNames::CookieSetOnIpBlock );
811 case DatabaseBlock::TYPE_USER:
812 return !$isAnon &&
813 $this->options->get( MainConfigNames::CookieSetOnAutoblock ) &&
814 $block->isAutoblocking();
815 default:
816 return false;
817 }
818 }
819
826 public static function clearBlockCookie( WebResponse $response ) {
827 $response->clearCookie( 'BlockID', [ 'httpOnly' => false ] );
828 }
829
838 private function getIdFromCookieValue( $cookieValue ) {
839 // The cookie value must start with a number
840 if ( !is_numeric( substr( $cookieValue, 0, 1 ) ) ) {
841 return null;
842 }
843
844 // Extract the ID prefix from the cookie value (may be the whole value, if no bang found).
845 $bangPos = strpos( $cookieValue, '!' );
846 $id = ( $bangPos === false ) ? $cookieValue : substr( $cookieValue, 0, $bangPos );
847 if ( !$this->options->get( MainConfigNames::SecretKey ) ) {
848 // If there's no secret key, just use the ID as given.
849 return (int)$id;
850 }
851 $storedHmac = substr( $cookieValue, $bangPos + 1 );
852 $calculatedHmac = MWCryptHash::hmac( $id, $this->options->get( MainConfigNames::SecretKey ), false );
853 if ( $calculatedHmac === $storedHmac ) {
854 return (int)$id;
855 } else {
856 return null;
857 }
858 }
859
869 private function getCookieValue( DatabaseBlock $block ) {
870 $id = (string)$block->getId();
871 if ( !$this->options->get( MainConfigNames::SecretKey ) ) {
872 // If there's no secret key, don't append a HMAC.
873 return $id;
874 }
875 $hmac = MWCryptHash::hmac( $id, $this->options->get( MainConfigNames::SecretKey ), false );
876 return $id . '!' . $hmac;
877 }
878}
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:81
static hmac( $data, $key, $raw=true)
Generate a keyed cryptographic hash value (HMAC) for a string, making use of the best hash algorithm ...
getExpiry()
Get the block expiry time.
A service class for checking blocks.
trackBlockWithCookie(User $user, WebResponse $response)
Set the 'BlockID' cookie depending on block type and user authentication status.
isDnsBlacklisted( $ip, $checkAllowed=false)
Whether the given IP is in a DNS blacklist.
getIpBlock(string $ip, bool $fromReplica)
Get the blocks that apply to an IP address.
__construct(ServiceOptions $options, UserFactory $userFactory, UserIdentityUtils $userIdentityUtils, LoggerInterface $logger, HookContainer $hookContainer, DatabaseBlockStore $blockStore, ProxyLookup $proxyLookup)
clearUserCache(UserIdentity $user)
Clear the cache of any blocks that refer to the specified user.
filter(?Block $block, $callback)
Remove elements of a block which fail a callback test.
checkHost( $hostname)
Wrapper for mocking in tests.
getBlocksForIPList(array $ipChain, bool $applySoftBlocks, bool $fromPrimary)
Get all blocks that match any IP from an array of IP addresses.
getCreateAccountBlock(UserIdentity $user, ?WebRequest $request, $fromReplica)
Get the block which applies to a create account action, if there is any.
getUserBlock(UserIdentity $user, $request, $fromReplica, $disableIpBlockExemptChecking=false)
Get the blocks that apply to a user.
static clearBlockCookie(WebResponse $response)
Unset the 'BlockID' cookie.
getBlock(UserIdentity $user, ?WebRequest $request, $fromReplica=true)
Get the blocks that apply to a user.
static createFromBlocks(AbstractBlock ... $blocks)
Helper method for merging multiple blocks into a composite block.
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
System blocks are temporary blocks that are created on enforcement (e.g.
A class for passing options to services.
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys,...
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
A class containing constants representing the names of configuration variables.
const DnsBlacklistUrls
Name constant for the DnsBlacklistUrls setting, for use with Config::get()
const SoftBlockRanges
Name constant for the SoftBlockRanges setting, for use with Config::get()
const CookieSetOnAutoblock
Name constant for the CookieSetOnAutoblock setting, for use with Config::get()
const EnableDnsBlacklist
Name constant for the EnableDnsBlacklist setting, for use with Config::get()
const ApplyIpBlocksToXff
Name constant for the ApplyIpBlocksToXff setting, for use with Config::get()
const ProxyList
Name constant for the ProxyList setting, for use with Config::get()
const ProxyWhitelist
Name constant for the ProxyWhitelist setting, for use with Config::get()
const CookieSetOnIpBlock
Name constant for the CookieSetOnIpBlock setting, for use with Config::get()
const SecretKey
Name constant for the SecretKey setting, for use with Config::get()
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition Message.php:156
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form,...
getHeader( $name, $flags=0)
Get a request header, or false if it isn't set.
getIP()
Work out the IP address based on various globals For trusted proxies, use the XFF client IP (first of...
Allow programs to request this object from WebRequest::response() and handle all outputting (or lack ...
headersSent()
Test if headers have been sent.
setCookie( $name, $value, $expire=0, $options=[])
Set the browser cookie.
clearCookie( $name, $options=[])
Unset a browser cookie.
Creates User objects.
Convenience functions for interpreting UserIdentity objects using additional services or config.
internal since 1.36
Definition User.php:94
isSafeToLoad()
Test if it's safe to load this User object.
Definition User.php:332
getBlock( $freshness=IDBAccessObject::READ_NORMAL, $disableIpBlockExemptChecking=false)
Get the block affecting the user, or null if the user is not blocked.
Definition User.php:1428
isAnon()
Get whether the user is anonymous.
Definition User.php:2132
getRequest()
Get the WebRequest object to use with this object.
Definition User.php:2230
Represents a block that may prevent users from performing specific operations.
Definition Block.php:45
Interface for objects representing user identity.