33use Psr\Log\LoggerInterface;
57 public const CONSTRUCTOR_OPTIONS = [
59 'CookieSetOnAutoblock',
91 $this->hookRunner =
new HookRunner( $hookContainer );
126 public function getUserBlock(
User $user, $request, $fromReplica, $disableIpBlockExemptChecking =
false ) {
127 $fromMaster = !$fromReplica;
133 $checkIpBlocks = $request &&
138 !$disableIpBlockExemptChecking &&
139 !$this->permissionManager->userHasRight( $user,
'ipblock-exempt' );
141 if ( $request && $checkIpBlocks ) {
144 $ip = $request->getIP();
164 if ( count( $blocks ) > 0 ) {
165 if ( count( $blocks ) === 1 ) {
166 $block = $blocks[ 0 ];
170 'reason' =>
new Message(
'blockedtext-composite-reason' ),
171 'originalBlocks' => $blocks,
176 $this->hookRunner->onGetUserBlock( clone $user, $ip, $block );
192 $blocks[] = $cookieBlock;
206 $ip = $request->
getIP();
209 if ( !in_array( $ip, $this->options->get(
'ProxyWhitelist' ) ) ) {
213 'reason' =>
new Message(
'proxyblockreason' ),
215 'systemBlock' =>
'proxy',
219 'reason' =>
new Message(
'sorbsreason' ),
221 'systemBlock' =>
'dnsbl',
227 if ( $isAnon && IPUtils::isInRanges( $ip, $this->options->get(
'SoftBlockRanges' ) ) ) {
230 'reason' =>
new Message(
'softblockrangesreason', [ $ip ] ),
232 'systemBlock' =>
'wgSoftBlockRanges',
237 if ( $this->options->get(
'ApplyIpBlocksToXff' )
238 && !in_array( $ip, $this->options->get(
'ProxyWhitelist' ) )
240 $xff = $request->
getHeader(
'X-Forwarded-For' );
241 $xff = array_map(
'trim', explode(
',', $xff ) );
242 $xff = array_diff( $xff, [ $ip ] );
248 $xffblocks = array_filter( $xffblocks,
static function ( $block ) {
252 $blocks = array_merge( $blocks, $xffblocks );
268 $databaseBlocks = [];
270 foreach ( $blocks as $block ) {
272 $systemBlocks[] = $block;
275 '@phan-var DatabaseBlock $block';
276 if ( !isset( $databaseBlocks[$block->getParentBlockId()] ) ) {
277 $databaseBlocks[$block->getParentBlockId()] = $block;
280 $databaseBlocks[$block->getId()] = $block;
284 return array_values( array_merge( $systemBlocks, $databaseBlocks ) );
302 $cookieValue = $request->
getCookie(
'BlockID' );
303 if ( $cookieValue ===
null ) {
308 if ( $blockCookieId !==
null ) {
337 $this->options->get(
'CookieSetOnIpBlock' );
340 $this->options->get(
'CookieSetOnAutoblock' );
355 $proxyList = $this->options->get(
'ProxyList' );
360 if ( !is_array( $proxyList ) ) {
362 $proxyList = array_map(
'trim', file( $proxyList ) );
365 $proxyListIPSet =
new IPSet( $proxyList );
366 return $proxyListIPSet->match( $ip );
377 if ( !$this->options->get(
'EnableDnsBlacklist' ) ||
378 ( $checkWhitelist && in_array( $ip, $this->options->get(
'ProxyWhitelist' ) ) )
383 return $this->
inDnsBlacklist( $ip, $this->options->get(
'DnsBlacklistUrls' ) );
396 if ( IPUtils::isIPv4( $ip ) ) {
398 $ipReversed = implode(
'.', array_reverse( explode(
'.', $ip ) ) );
400 foreach ( $bases as
$base ) {
404 if ( is_array(
$base ) ) {
405 if ( count(
$base ) >= 2 ) {
407 $hostname =
"{$base[1]}.$ipReversed.{$base[0]}";
409 $hostname =
"$ipReversed.{$base[0]}";
411 $basename =
$base[0];
413 $hostname =
"$ipReversed.$base";
421 "Hostname $hostname is {$ipList[0]}, it's a proxy says $basename!"
427 $this->logger->debug(
"Requested $hostname, not found in $basename." );
441 return gethostbynamel( $hostname );
466 if ( $request->getCookie(
'BlockID' ) !==
null ) {
480 throw new LogicException( __METHOD__ .
' requires a loaded User object' );
483 throw new LogicException( __METHOD__ .
' must be called pre-send' );
487 $isAnon = $user->
isAnon();
492 foreach ( $block->getOriginalBlocks() as $originalBlock ) {
494 '@phan-var DatabaseBlock $originalBlock';
501 '@phan-var DatabaseBlock $block';
524 if ( $expiryTime ===
'infinity' || $expiryTime > $maxExpiryTime ) {
525 $expiryTime = $maxExpiryTime;
529 $expiryValue = DateTime::createFromFormat(
532 new DateTimeZone(
'UTC' )
534 $cookieOptions = [
'httpOnly' => false ];
536 $response->
setCookie(
'BlockID', $cookieValue, $expiryValue, $cookieOptions );
551 return $isAnon && $this->options->get(
'CookieSetOnIpBlock' );
554 $this->options->get(
'CookieSetOnAutoblock' ) &&
555 $block->isAutoblocking();
570 $response->
clearCookie(
'BlockID', [
'httpOnly' =>
false ] );
585 if ( !is_numeric( substr( $cookieValue, 0, 1 ) ) ) {
590 $bangPos = strpos( $cookieValue,
'!' );
591 $id = ( $bangPos === false ) ? $cookieValue : substr( $cookieValue, 0, $bangPos );
592 if ( !$this->options->get(
'SecretKey' ) ) {
596 $storedHmac = substr( $cookieValue, $bangPos + 1 );
597 $calculatedHmac =
MWCryptHash::hmac( $id, $this->options->get(
'SecretKey' ),
false );
598 if ( $calculatedHmac === $storedHmac ) {
617 $id = $block->
getId();
618 if ( !$this->options->get(
'SecretKey' ) ) {
623 $cookieValue = $id .
'!' . $hmac;
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
static hmac( $data, $key, $raw=true)
Generate an acceptably unstable one-way-hmac of some text making use of the best hash algorithm that ...
The Message class deals with fetching and processing of interface message into a variety of formats.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
getRequest()
Get the WebRequest object to use with this object.
isRegistered()
Alias of isLoggedIn() with a name that describes its actual functionality.
isSafeToLoad()
Test if it's safe to load this User object.
getBlock( $fromReplica=true, $disableIpBlockExemptChecking=false)
Get the block affecting the user, or null if the user is not blocked.
isAnon()
Get whether the user is anonymous.
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
getIP()
Work out the IP address based on various globals For trusted proxies, use the XFF client IP (first of...
getCookie( $key, $prefix=null, $default=null)
Get a cookie from the $_COOKIE jar.
getHeader( $name, $flags=0)
Get a request header, or false if it isn't set.
Allow programs to request this object from WebRequest::response() and handle all outputting (or lack ...
setCookie( $name, $value, $expire=0, $options=[])
Set the browser cookie.
clearCookie( $name, $options=[])
Unset a browser cookie.
headersSent()
Test if headers have been sent.