34use Psr\Log\LoggerInterface;
62 'CookieSetOnAutoblock',
97 $this->hookRunner =
new HookRunner( $hookContainer );
136 $disableIpBlockExemptChecking =
false
138 $fromPrimary = !$fromReplica;
144 $checkIpBlocks = $request &&
149 !$disableIpBlockExemptChecking &&
150 !$this->permissionManager->userHasRight( $user,
'ipblock-exempt' );
152 if ( $request && $checkIpBlocks ) {
155 $ip = $request->getIP();
175 if ( count( $blocks ) > 0 ) {
176 if ( count( $blocks ) === 1 ) {
177 $block = $blocks[ 0 ];
181 'reason' =>
new Message(
'blockedtext-composite-reason' ),
182 'originalBlocks' => $blocks,
187 $legacyUser = $this->userFactory->newFromUserIdentity( $user );
188 $this->hookRunner->onGetUserBlock( clone $legacyUser, $ip, $block );
204 $blocks[] = $cookieBlock;
218 $ip = $request->
getIP();
221 if ( !in_array( $ip, $this->options->get(
'ProxyWhitelist' ) ) ) {
225 'reason' =>
new Message(
'proxyblockreason' ),
227 'systemBlock' =>
'proxy',
231 'reason' =>
new Message(
'sorbsreason' ),
234 'systemBlock' =>
'dnsbl',
240 if ( $isAnon && IPUtils::isInRanges( $ip, $this->options->get(
'SoftBlockRanges' ) ) ) {
243 'reason' =>
new Message(
'softblockrangesreason', [ $ip ] ),
245 'systemBlock' =>
'wgSoftBlockRanges',
250 if ( $this->options->get(
'ApplyIpBlocksToXff' )
251 && !in_array( $ip, $this->options->get(
'ProxyWhitelist' ) )
253 $xff = $request->
getHeader(
'X-Forwarded-For' );
254 $xff = array_map(
'trim', explode(
',', $xff ) );
255 $xff = array_diff( $xff, [ $ip ] );
258 $blocks = array_merge( $blocks, $xffblocks );
274 $databaseBlocks = [];
276 foreach ( $blocks as $block ) {
278 $systemBlocks[] = $block;
281 '@phan-var DatabaseBlock $block';
282 if ( !isset( $databaseBlocks[$block->getParentBlockId()] ) ) {
283 $databaseBlocks[$block->getParentBlockId()] = $block;
286 $databaseBlocks[$block->getId()] = $block;
290 return array_values( array_merge( $systemBlocks, $databaseBlocks ) );
308 $cookieValue = $request->
getCookie(
'BlockID' );
309 if ( $cookieValue ===
null ) {
314 if ( $blockCookieId !==
null ) {
343 $this->options->get(
'CookieSetOnIpBlock' );
346 $this->options->get(
'CookieSetOnAutoblock' );
361 $proxyList = $this->options->get(
'ProxyList' );
366 if ( !is_array( $proxyList ) ) {
368 $proxyList = array_map(
'trim', file( $proxyList ) );
371 $proxyListIPSet =
new IPSet( $proxyList );
372 return $proxyListIPSet->match( $ip );
383 if ( !$this->options->get(
'EnableDnsBlacklist' ) ||
384 ( $checkAllowed && in_array( $ip, $this->options->get(
'ProxyWhitelist' ) ) )
389 return $this->
inDnsBlacklist( $ip, $this->options->get(
'DnsBlacklistUrls' ) );
402 if ( IPUtils::isIPv4( $ip ) ) {
404 $ipReversed = implode(
'.', array_reverse( explode(
'.', $ip ) ) );
406 foreach ( $bases as
$base ) {
410 if ( is_array(
$base ) ) {
411 if ( count(
$base ) >= 2 ) {
413 $hostname =
"{$base[1]}.$ipReversed.{$base[0]}";
415 $hostname =
"$ipReversed.{$base[0]}";
417 $basename =
$base[0];
419 $hostname =
"$ipReversed.$base";
427 'Hostname {hostname} is {ipList}, it\'s a proxy says {basename}!',
429 'hostname' => $hostname,
430 'ipList' => $ipList[0],
431 'basename' => $basename,
438 $this->logger->debug(
"Requested $hostname, not found in $basename." );
452 return gethostbynamel( $hostname );
477 if ( $request->getCookie(
'BlockID' ) !==
null ) {
491 throw new LogicException( __METHOD__ .
' requires a loaded User object' );
494 throw new LogicException( __METHOD__ .
' must be called pre-send' );
498 $isAnon = $user->
isAnon();
503 foreach ( $block->getOriginalBlocks() as $originalBlock ) {
505 '@phan-var DatabaseBlock $originalBlock';
512 '@phan-var DatabaseBlock $block';
535 if ( $expiryTime ===
'infinity' || $expiryTime > $maxExpiryTime ) {
536 $expiryTime = $maxExpiryTime;
540 $expiryValue = DateTime::createFromFormat(
543 new DateTimeZone(
'UTC' )
545 $cookieOptions = [
'httpOnly' => false ];
547 $response->
setCookie(
'BlockID', $cookieValue, $expiryValue, $cookieOptions );
562 return $isAnon && $this->options->get(
'CookieSetOnIpBlock' );
565 $this->options->get(
'CookieSetOnAutoblock' ) &&
566 $block->isAutoblocking();
581 $response->
clearCookie(
'BlockID', [
'httpOnly' =>
false ] );
596 if ( !is_numeric( substr( $cookieValue, 0, 1 ) ) ) {
601 $bangPos = strpos( $cookieValue,
'!' );
602 $id = ( $bangPos === false ) ? $cookieValue : substr( $cookieValue, 0, $bangPos );
603 if ( !$this->options->get(
'SecretKey' ) ) {
607 $storedHmac = substr( $cookieValue, $bangPos + 1 );
608 $calculatedHmac =
MWCryptHash::hmac( $id, $this->options->get(
'SecretKey' ),
false );
609 if ( $calculatedHmac === $storedHmac ) {
628 $id = $block->
getId();
629 if ( !$this->options->get(
'SecretKey' ) ) {
634 $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,...
getBlock( $freshness=self::READ_NORMAL, $disableIpBlockExemptChecking=false)
Get the block affecting the user, or null if the user is not blocked.
getRequest()
Get the WebRequest object to use with this object.
isSafeToLoad()
Test if it's safe to load this User object.
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.