MediaWiki  master
DatabaseBlock.php
Go to the documentation of this file.
1 <?php
23 namespace MediaWiki\Block;
24 
25 use ActorMigration;
27 use CommentStore;
28 use DeferredUpdates;
29 use Hooks;
30 use Html;
36 use MWException;
37 use RequestContext;
38 use stdClass;
39 use Title;
40 use User;
41 use WebResponse;
42 use Wikimedia\IPUtils;
45 
59  public $mAuto;
60 
66 
68  private $mId;
69 
71  private $mFromMaster;
72 
74  private $forcedTargetID;
75 
77  private $isHardblock;
78 
80  private $isAutoblocking;
81 
83  private $restrictions;
84 
86  private $blocker;
87 
108  public function __construct( array $options = [] ) {
109  parent::__construct( $options );
110 
111  $defaults = [
112  'user' => null,
113  'auto' => false,
114  'expiry' => '',
115  'anonOnly' => false,
116  'createAccount' => false,
117  'enableAutoblock' => false,
118  'blockEmail' => false,
119  'allowUsertalk' => false,
120  'sitewide' => true,
121  'by' => null,
122  'byText' => '',
123  ];
124 
125  $options += $defaults;
126 
127  if ( $this->target instanceof User && $options['user'] ) {
128  # Needed for foreign users
129  $this->forcedTargetID = $options['user'];
130  }
131 
132  if ( $options['by'] ) {
133  # Local user
134  $this->setBlocker( User::newFromId( $options['by'] ) );
135  } else {
136  # Foreign user
137  $this->setBlocker( $options['byText'] );
138  }
139 
140  $this->setExpiry( wfGetDB( DB_REPLICA )->decodeExpiry( $options['expiry'] ) );
141 
142  # Boolean settings
143  $this->mAuto = (bool)$options['auto'];
144  $this->isHardblock( !$options['anonOnly'] );
145  $this->isAutoblocking( (bool)$options['enableAutoblock'] );
146  $this->isSitewide( (bool)$options['sitewide'] );
147  $this->isEmailBlocked( (bool)$options['blockEmail'] );
148  $this->isCreateAccountBlocked( (bool)$options['createAccount'] );
149  $this->isUsertalkEditAllowed( (bool)$options['allowUsertalk'] );
150 
151  $this->mFromMaster = false;
152  }
153 
160  public static function newFromID( $id ) {
161  $dbr = wfGetDB( DB_REPLICA );
162  $blockQuery = self::getQueryInfo();
163  $res = $dbr->selectRow(
164  $blockQuery['tables'],
165  $blockQuery['fields'],
166  [ 'ipb_id' => $id ],
167  __METHOD__,
168  [],
169  $blockQuery['joins']
170  );
171  if ( $res ) {
172  return self::newFromRow( $res );
173  } else {
174  return null;
175  }
176  }
177 
187  public static function getQueryInfo() {
188  $commentQuery = CommentStore::getStore()->getJoin( 'ipb_reason' );
189  $actorQuery = ActorMigration::newMigration()->getJoin( 'ipb_by' );
190  return [
191  'tables' => [ 'ipblocks' ] + $commentQuery['tables'] + $actorQuery['tables'],
192  'fields' => [
193  'ipb_id',
194  'ipb_address',
195  'ipb_timestamp',
196  'ipb_auto',
197  'ipb_anon_only',
198  'ipb_create_account',
199  'ipb_enable_autoblock',
200  'ipb_expiry',
201  'ipb_deleted',
202  'ipb_block_email',
203  'ipb_allow_usertalk',
204  'ipb_parent_block_id',
205  'ipb_sitewide',
206  ] + $commentQuery['fields'] + $actorQuery['fields'],
207  'joins' => $commentQuery['joins'] + $actorQuery['joins'],
208  ];
209  }
210 
218  public function equals( DatabaseBlock $block ) {
219  return (
220  (string)$this->target == (string)$block->target
221  && $this->type == $block->type
222  && $this->mAuto == $block->mAuto
223  && $this->isHardblock() == $block->isHardblock()
224  && $this->isCreateAccountBlocked() == $block->isCreateAccountBlocked()
225  && $this->getExpiry() == $block->getExpiry()
226  && $this->isAutoblocking() == $block->isAutoblocking()
227  && $this->getHideName() == $block->getHideName()
228  && $this->isEmailBlocked() == $block->isEmailBlocked()
229  && $this->isUsertalkEditAllowed() == $block->isUsertalkEditAllowed()
230  && $this->getReasonComment()->text == $block->getReasonComment()->text
231  && $this->isSitewide() == $block->isSitewide()
232  // DatabaseBlock::getRestrictions() may perform a database query, so
233  // keep it at the end.
234  && $this->getBlockRestrictionStore()->equals(
235  $this->getRestrictions(), $block->getRestrictions()
236  )
237  );
238  }
239 
252  protected static function newLoad(
253  $specificTarget,
254  $specificType,
255  $fromMaster,
256  $vagueTarget = null
257  ) {
258  $db = wfGetDB( $fromMaster ? DB_MASTER : DB_REPLICA );
259 
260  if ( $specificType !== null ) {
261  $conds = [ 'ipb_address' => [ (string)$specificTarget ] ];
262  } else {
263  $conds = [ 'ipb_address' => [] ];
264  }
265 
266  # Be aware that the != '' check is explicit, since empty values will be
267  # passed by some callers (T31116)
268  if ( $vagueTarget != '' ) {
269  list( $target, $type ) = self::parseTarget( $vagueTarget );
270  switch ( $type ) {
271  case self::TYPE_USER:
272  # Slightly weird, but who are we to argue?
273  $conds['ipb_address'][] = (string)$target;
274  break;
275 
276  case self::TYPE_IP:
277  $conds['ipb_address'][] = (string)$target;
278  $conds['ipb_address'] = array_unique( $conds['ipb_address'] );
279  $conds[] = self::getRangeCond( IPUtils::toHex( $target ) );
280  $conds = $db->makeList( $conds, LIST_OR );
281  break;
282 
283  case self::TYPE_RANGE:
284  list( $start, $end ) = IPUtils::parseRange( $target );
285  $conds['ipb_address'][] = (string)$target;
286  $conds[] = self::getRangeCond( $start, $end );
287  $conds = $db->makeList( $conds, LIST_OR );
288  break;
289 
290  default:
291  throw new MWException( "Tried to load block with invalid type" );
292  }
293  }
294 
295  $blockQuery = self::getQueryInfo();
296  $res = $db->select(
297  $blockQuery['tables'],
298  $blockQuery['fields'],
299  $conds,
300  __METHOD__,
301  [],
302  $blockQuery['joins']
303  );
304 
305  $blocks = [];
306  $blockIds = [];
307  $autoBlocks = [];
308  foreach ( $res as $row ) {
309  $block = self::newFromRow( $row );
310 
311  # Don't use expired blocks
312  if ( $block->isExpired() ) {
313  continue;
314  }
315 
316  # Don't use anon only blocks on users
317  if ( $specificType == self::TYPE_USER && !$block->isHardblock() ) {
318  continue;
319  }
320 
321  // Check for duplicate autoblocks
322  if ( $block->getType() === self::TYPE_AUTO ) {
323  $autoBlocks[] = $block;
324  } else {
325  $blocks[] = $block;
326  $blockIds[] = $block->getId();
327  }
328  }
329 
330  // Only add autoblocks that aren't duplicates
331  foreach ( $autoBlocks as $block ) {
332  if ( !in_array( $block->mParentBlockId, $blockIds ) ) {
333  $blocks[] = $block;
334  }
335  }
336 
337  return $blocks;
338  }
339 
352  protected static function chooseMostSpecificBlock( array $blocks ) {
353  if ( count( $blocks ) === 1 ) {
354  return $blocks[0];
355  }
356 
357  # This result could contain a block on the user, a block on the IP, and a russian-doll
358  # set of rangeblocks. We want to choose the most specific one, so keep a leader board.
359  $bestBlock = null;
360 
361  # Lower will be better
362  $bestBlockScore = 100;
363  foreach ( $blocks as $block ) {
364  if ( $block->getType() == self::TYPE_RANGE ) {
365  # This is the number of bits that are allowed to vary in the block, give
366  # or take some floating point errors
367  $target = $block->getTarget();
368  $max = IPUtils::isIPv6( $target ) ? 128 : 32;
369  list( $network, $bits ) = IPUtils::parseCIDR( $target );
370  $size = $max - $bits;
371 
372  # Rank a range block covering a single IP equally with a single-IP block
373  $score = self::TYPE_RANGE - 1 + ( $size / $max );
374 
375  } else {
376  $score = $block->getType();
377  }
378 
379  if ( $score < $bestBlockScore ) {
380  $bestBlockScore = $score;
381  $bestBlock = $block;
382  }
383  }
384 
385  return $bestBlock;
386  }
387 
394  public static function getRangeCond( $start, $end = null ) {
395  if ( $end === null ) {
396  $end = $start;
397  }
398  # Per T16634, we want to include relevant active rangeblocks; for
399  # rangeblocks, we want to include larger ranges which enclose the given
400  # range. We know that all blocks must be smaller than $wgBlockCIDRLimit,
401  # so we can improve performance by filtering on a LIKE clause
402  $chunk = self::getIpFragment( $start );
403  $dbr = wfGetDB( DB_REPLICA );
404  $like = $dbr->buildLike( $chunk, $dbr->anyString() );
405 
406  # Fairly hard to make a malicious SQL statement out of hex characters,
407  # but stranger things have happened...
408  $safeStart = $dbr->addQuotes( $start );
409  $safeEnd = $dbr->addQuotes( $end );
410 
411  return $dbr->makeList(
412  [
413  "ipb_range_start $like",
414  "ipb_range_start <= $safeStart",
415  "ipb_range_end >= $safeEnd",
416  ],
417  LIST_AND
418  );
419  }
420 
427  protected static function getIpFragment( $hex ) {
428  global $wgBlockCIDRLimit;
429  if ( substr( $hex, 0, 3 ) == 'v6-' ) {
430  return 'v6-' . substr( substr( $hex, 3 ), 0, floor( $wgBlockCIDRLimit['IPv6'] / 4 ) );
431  } else {
432  return substr( $hex, 0, floor( $wgBlockCIDRLimit['IPv4'] / 4 ) );
433  }
434  }
435 
441  protected function initFromRow( $row ) {
442  $this->setTarget( $row->ipb_address );
443 
444  $this->setTimestamp( wfTimestamp( TS_MW, $row->ipb_timestamp ) );
445  $this->mAuto = (bool)$row->ipb_auto;
446  $this->setHideName( (bool)$row->ipb_deleted );
447  $this->mId = (int)$row->ipb_id;
448  $this->mParentBlockId = (int)$row->ipb_parent_block_id;
449 
451  $row->ipb_by, $row->ipb_by_text, $row->ipb_by_actor ?? null
452  ) );
453 
454  // I wish I didn't have to do this
455  $db = wfGetDB( DB_REPLICA );
456  $this->setExpiry( $db->decodeExpiry( $row->ipb_expiry ) );
457  $this->setReason(
459  // Legacy because $row may have come from self::selectFields()
460  ->getCommentLegacy( $db, 'ipb_reason', $row )
461  );
462 
463  $this->isHardblock( !$row->ipb_anon_only );
464  $this->isAutoblocking( (bool)$row->ipb_enable_autoblock );
465  $this->isSitewide( (bool)$row->ipb_sitewide );
466 
467  $this->isCreateAccountBlocked( (bool)$row->ipb_create_account );
468  $this->isEmailBlocked( (bool)$row->ipb_block_email );
469  $this->isUsertalkEditAllowed( (bool)$row->ipb_allow_usertalk );
470  }
471 
477  public static function newFromRow( $row ) {
478  $block = new DatabaseBlock;
479  $block->initFromRow( $row );
480  return $block;
481  }
482 
489  public function delete() {
490  if ( wfReadOnly() ) {
491  return false;
492  }
493 
494  if ( !$this->getId() ) {
495  throw new MWException(
496  __METHOD__ . " requires that the mId member be filled\n"
497  );
498  }
499 
500  $dbw = wfGetDB( DB_MASTER );
501 
502  $this->getBlockRestrictionStore()->deleteByParentBlockId( $this->getId() );
503  $dbw->delete( 'ipblocks', [ 'ipb_parent_block_id' => $this->getId() ], __METHOD__ );
504 
505  $this->getBlockRestrictionStore()->deleteByBlockId( $this->getId() );
506  $dbw->delete( 'ipblocks', [ 'ipb_id' => $this->getId() ], __METHOD__ );
507 
508  return $dbw->affectedRows() > 0;
509  }
510 
519  public function insert( IDatabase $dbw = null ) {
520  global $wgBlockDisablesLogin;
521 
522  if ( !$this->getBlocker() || $this->getBlocker()->getName() === '' ) {
523  throw new MWException( 'Cannot insert a block without a blocker set' );
524  }
525 
526  wfDebug( __METHOD__ . "; timestamp {$this->mTimestamp}" );
527 
528  if ( $dbw === null ) {
529  $dbw = wfGetDB( DB_MASTER );
530  }
531 
533 
534  $row = $this->getDatabaseArray( $dbw );
535 
536  $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
537  $affected = $dbw->affectedRows();
538  if ( $affected ) {
539  $this->setId( $dbw->insertId() );
540  if ( $this->restrictions ) {
541  $this->getBlockRestrictionStore()->insert( $this->restrictions );
542  }
543  }
544 
545  # Don't collide with expired blocks.
546  # Do this after trying to insert to avoid locking.
547  if ( !$affected ) {
548  # T96428: The ipb_address index uses a prefix on a field, so
549  # use a standard SELECT + DELETE to avoid annoying gap locks.
550  $ids = $dbw->selectFieldValues( 'ipblocks',
551  'ipb_id',
552  [
553  'ipb_address' => $row['ipb_address'],
554  'ipb_user' => $row['ipb_user'],
555  'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() )
556  ],
557  __METHOD__
558  );
559  if ( $ids ) {
560  $dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], __METHOD__ );
561  $this->getBlockRestrictionStore()->deleteByBlockId( $ids );
562  $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
563  $affected = $dbw->affectedRows();
564  $this->setId( $dbw->insertId() );
565  if ( $this->restrictions ) {
566  $this->getBlockRestrictionStore()->insert( $this->restrictions );
567  }
568  }
569  }
570 
571  if ( $affected ) {
572  $auto_ipd_ids = $this->doRetroactiveAutoblock();
573 
574  if ( $wgBlockDisablesLogin && $this->target instanceof User ) {
575  // Change user login token to force them to be logged out.
576  $this->target->setToken();
577  $this->target->saveSettings();
578  }
579 
580  return [ 'id' => $this->mId, 'autoIds' => $auto_ipd_ids ];
581  }
582 
583  return false;
584  }
585 
593  public function update() {
594  wfDebug( __METHOD__ . "; timestamp {$this->mTimestamp}" );
595  $dbw = wfGetDB( DB_MASTER );
596 
597  $dbw->startAtomic( __METHOD__ );
598 
599  $result = $dbw->update(
600  'ipblocks',
601  $this->getDatabaseArray( $dbw ),
602  [ 'ipb_id' => $this->getId() ],
603  __METHOD__
604  );
605 
606  // Only update the restrictions if they have been modified.
607  if ( $this->restrictions !== null ) {
608  // An empty array should remove all of the restrictions.
609  if ( empty( $this->restrictions ) ) {
610  $success = $this->getBlockRestrictionStore()->deleteByBlockId( $this->getId() );
611  } else {
612  $success = $this->getBlockRestrictionStore()->update( $this->restrictions );
613  }
614  // Update the result. The first false is the result, otherwise, true.
615  $result = $result && $success;
616  }
617 
618  if ( $this->isAutoblocking() ) {
619  // update corresponding autoblock(s) (T50813)
620  $dbw->update(
621  'ipblocks',
622  $this->getAutoblockUpdateArray( $dbw ),
623  [ 'ipb_parent_block_id' => $this->getId() ],
624  __METHOD__
625  );
626 
627  // Only update the restrictions if they have been modified.
628  if ( $this->restrictions !== null ) {
629  $this->getBlockRestrictionStore()->updateByParentBlockId( $this->getId(), $this->restrictions );
630  }
631  } else {
632  // autoblock no longer required, delete corresponding autoblock(s)
633  $this->getBlockRestrictionStore()->deleteByParentBlockId( $this->getId() );
634  $dbw->delete(
635  'ipblocks',
636  [ 'ipb_parent_block_id' => $this->getId() ],
637  __METHOD__
638  );
639  }
640 
641  $dbw->endAtomic( __METHOD__ );
642 
643  if ( $result ) {
644  $auto_ipd_ids = $this->doRetroactiveAutoblock();
645  return [ 'id' => $this->mId, 'autoIds' => $auto_ipd_ids ];
646  }
647 
648  return $result;
649  }
650 
656  protected function getDatabaseArray( IDatabase $dbw ) {
657  $expiry = $dbw->encodeExpiry( $this->getExpiry() );
658 
659  if ( $this->forcedTargetID ) {
660  $uid = $this->forcedTargetID;
661  } else {
662  $uid = $this->target instanceof User ? $this->target->getId() : 0;
663  }
664 
665  $a = [
666  'ipb_address' => (string)$this->target,
667  'ipb_user' => $uid,
668  'ipb_timestamp' => $dbw->timestamp( $this->getTimestamp() ),
669  'ipb_auto' => $this->mAuto,
670  'ipb_anon_only' => !$this->isHardblock(),
671  'ipb_create_account' => $this->isCreateAccountBlocked(),
672  'ipb_enable_autoblock' => $this->isAutoblocking(),
673  'ipb_expiry' => $expiry,
674  'ipb_range_start' => $this->getRangeStart(),
675  'ipb_range_end' => $this->getRangeEnd(),
676  'ipb_deleted' => intval( $this->getHideName() ), // typecast required for SQLite
677  'ipb_block_email' => $this->isEmailBlocked(),
678  'ipb_allow_usertalk' => $this->isUsertalkEditAllowed(),
679  'ipb_parent_block_id' => $this->mParentBlockId,
680  'ipb_sitewide' => $this->isSitewide(),
681  ] + CommentStore::getStore()->insert( $dbw, 'ipb_reason', $this->getReasonComment() )
682  + ActorMigration::newMigration()->getInsertValues( $dbw, 'ipb_by', $this->getBlocker() );
683 
684  return $a;
685  }
686 
691  protected function getAutoblockUpdateArray( IDatabase $dbw ) {
692  return [
693  'ipb_create_account' => $this->isCreateAccountBlocked(),
694  'ipb_deleted' => (int)$this->getHideName(), // typecast required for SQLite
695  'ipb_allow_usertalk' => $this->isUsertalkEditAllowed(),
696  'ipb_sitewide' => $this->isSitewide(),
697  ] + CommentStore::getStore()->insert( $dbw, 'ipb_reason', $this->getReasonComment() )
698  + ActorMigration::newMigration()->getInsertValues( $dbw, 'ipb_by', $this->getBlocker() );
699  }
700 
707  protected function doRetroactiveAutoblock() {
708  $blockIds = [];
709  # If autoblock is enabled, autoblock the LAST IP(s) used
710  if ( $this->isAutoblocking() && $this->getType() == self::TYPE_USER ) {
711  wfDebug( "Doing retroactive autoblocks for " . $this->getTarget() );
712 
713  $continue = Hooks::runner()->onPerformRetroactiveAutoblock( $this, $blockIds );
714 
715  if ( $continue ) {
716  self::defaultRetroactiveAutoblock( $this, $blockIds );
717  }
718  }
719  return $blockIds;
720  }
721 
729  protected static function defaultRetroactiveAutoblock( DatabaseBlock $block, array &$blockIds ) {
730  global $wgPutIPinRC;
731 
732  // No IPs are in recentchanges table, so nothing to select
733  if ( !$wgPutIPinRC ) {
734  return;
735  }
736 
737  // Autoblocks only apply to TYPE_USER
738  if ( $block->getType() !== self::TYPE_USER ) {
739  return;
740  }
741  $target = $block->getTarget(); // TYPE_USER => always a User object
742 
743  $dbr = wfGetDB( DB_REPLICA );
744  $rcQuery = ActorMigration::newMigration()->getWhere( $dbr, 'rc_user', $target, false );
745 
746  $options = [ 'ORDER BY' => 'rc_timestamp DESC' ];
747 
748  // Just the last IP used.
749  $options['LIMIT'] = 1;
750 
751  $res = $dbr->select(
752  [ 'recentchanges' ] + $rcQuery['tables'],
753  [ 'rc_ip' ],
754  $rcQuery['conds'],
755  __METHOD__,
756  $options,
757  $rcQuery['joins']
758  );
759 
760  if ( !$res->numRows() ) {
761  # No results, don't autoblock anything
762  wfDebug( "No IP found to retroactively autoblock" );
763  } else {
764  foreach ( $res as $row ) {
765  if ( $row->rc_ip ) {
766  $id = $block->doAutoblock( $row->rc_ip );
767  if ( $id ) {
768  $blockIds[] = $id;
769  }
770  }
771  }
772  }
773  }
774 
782  public static function isWhitelistedFromAutoblocks( $ip ) {
783  // Try to get the autoblock_whitelist from the cache, as it's faster
784  // than getting the msg raw and explode()'ing it.
785  $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
786  $lines = $cache->getWithSetCallback(
787  $cache->makeKey( 'ip-autoblock', 'whitelist' ),
788  $cache::TTL_DAY,
789  function ( $curValue, &$ttl, array &$setOpts ) {
791 
792  return explode( "\n",
793  wfMessage( 'autoblock_whitelist' )->inContentLanguage()->plain() );
794  }
795  );
796 
797  wfDebug( "Checking the autoblock whitelist.." );
798 
799  foreach ( $lines as $line ) {
800  # List items only
801  if ( substr( $line, 0, 1 ) !== '*' ) {
802  continue;
803  }
804 
805  $wlEntry = substr( $line, 1 );
806  $wlEntry = trim( $wlEntry );
807 
808  wfDebug( "Checking $ip against $wlEntry..." );
809 
810  # Is the IP in this range?
811  if ( IPUtils::isInRange( $ip, $wlEntry ) ) {
812  wfDebug( " IP $ip matches $wlEntry, not autoblocking" );
813  return true;
814  } else {
815  wfDebug( " No match" );
816  }
817  }
818 
819  return false;
820  }
821 
828  public function doAutoblock( $autoblockIP ) {
829  # If autoblocks are disabled, go away.
830  if ( !$this->isAutoblocking() ) {
831  return false;
832  }
833 
834  # Check for presence on the autoblock whitelist.
835  if ( self::isWhitelistedFromAutoblocks( $autoblockIP ) ) {
836  return false;
837  }
838 
839  # Allow hooks to cancel the autoblock.
840  if ( !Hooks::runner()->onAbortAutoblock( $autoblockIP, $this ) ) {
841  wfDebug( "Autoblock aborted by hook." );
842  return false;
843  }
844 
845  # It's okay to autoblock. Go ahead and insert/update the block...
846 
847  # Do not add a *new* block if the IP is already blocked.
848  $ipblock = self::newFromTarget( $autoblockIP );
849  if ( $ipblock ) {
850  # Check if the block is an autoblock and would exceed the user block
851  # if renewed. If so, do nothing, otherwise prolong the block time...
852  if ( $ipblock->mAuto && // @todo Why not compare $ipblock->mExpiry?
853  $this->getExpiry() > self::getAutoblockExpiry( $ipblock->getTimestamp() )
854  ) {
855  # Reset block timestamp to now and its expiry to
856  # $wgAutoblockExpiry in the future
857  $ipblock->updateTimestamp();
858  }
859  return false;
860  }
861 
862  # Make a new block object with the desired properties.
863  $autoblock = new DatabaseBlock;
864  wfDebug( "Autoblocking {$this->getTarget()}@" . $autoblockIP );
865  $autoblock->setTarget( $autoblockIP );
866  $autoblock->setBlocker( $this->getBlocker() );
867  $autoblock->setReason(
868  wfMessage(
869  'autoblocker',
870  (string)$this->getTarget(),
871  $this->getReasonComment()->text
872  )->inContentLanguage()->plain()
873  );
874  $timestamp = wfTimestampNow();
875  $autoblock->setTimestamp( $timestamp );
876  $autoblock->mAuto = true;
877  $autoblock->isCreateAccountBlocked( $this->isCreateAccountBlocked() );
878  # Continue suppressing the name if needed
879  $autoblock->setHideName( $this->getHideName() );
880  $autoblock->isUsertalkEditAllowed( $this->isUsertalkEditAllowed() );
881  $autoblock->mParentBlockId = $this->mId;
882  $autoblock->isSitewide( $this->isSitewide() );
883  $autoblock->setRestrictions( $this->getRestrictions() );
884 
885  if ( $this->getExpiry() == 'infinity' ) {
886  # Original block was indefinite, start an autoblock now
887  $autoblock->setExpiry( self::getAutoblockExpiry( $timestamp ) );
888  } else {
889  # If the user is already blocked with an expiry date, we don't
890  # want to pile on top of that.
891  $autoblock->setExpiry( min( $this->getExpiry(), self::getAutoblockExpiry( $timestamp ) ) );
892  }
893 
894  # Insert the block...
895  $status = $autoblock->insert();
896  return $status
897  ? $status['id']
898  : false;
899  }
900 
907  public function deleteIfExpired() {
908  wfDeprecated( __METHOD__, '1.35' );
909  if ( $this->isExpired() ) {
910  wfDebug( __METHOD__ . " -- deleting" );
911  $this->delete();
912  $retVal = true;
913  } else {
914  wfDebug( __METHOD__ . " -- not expired" );
915  $retVal = false;
916  }
917 
918  return $retVal;
919  }
920 
925  public function isExpired() {
926  $timestamp = wfTimestampNow();
927  wfDebug( __METHOD__ . " checking current " . $timestamp . " vs $this->mExpiry" );
928 
929  if ( !$this->getExpiry() ) {
930  return false;
931  } else {
932  return $timestamp > $this->getExpiry();
933  }
934  }
935 
939  public function updateTimestamp() {
940  if ( $this->mAuto ) {
941  $this->setTimestamp( wfTimestamp() );
942  $this->setExpiry( self::getAutoblockExpiry( $this->getTimestamp() ) );
943 
944  $dbw = wfGetDB( DB_MASTER );
945  $dbw->update( 'ipblocks',
946  [ /* SET */
947  'ipb_timestamp' => $dbw->timestamp( $this->getTimestamp() ),
948  'ipb_expiry' => $dbw->timestamp( $this->getExpiry() ),
949  ],
950  [ /* WHERE */
951  'ipb_id' => $this->getId(),
952  ],
953  __METHOD__
954  );
955  }
956  }
957 
963  public function getRangeStart() {
964  switch ( $this->type ) {
965  case self::TYPE_USER:
966  return '';
967  case self::TYPE_IP:
968  return IPUtils::toHex( $this->target );
969  case self::TYPE_RANGE:
970  list( $start, /*...*/ ) = IPUtils::parseRange( $this->target );
971  return $start;
972  default:
973  throw new MWException( "Block with invalid type" );
974  }
975  }
976 
982  public function getRangeEnd() {
983  switch ( $this->type ) {
984  case self::TYPE_USER:
985  return '';
986  case self::TYPE_IP:
987  return IPUtils::toHex( $this->target );
988  case self::TYPE_RANGE:
989  list( /*...*/, $end ) = IPUtils::parseRange( $this->target );
990  return $end;
991  default:
992  throw new MWException( "Block with invalid type" );
993  }
994  }
995 
1000  public function getReason() {
1001  if ( $this->getType() === self::TYPE_AUTO ) {
1002  return $this->reason->message->inContentLanguage()->plain();
1003  }
1004  return $this->reason->text;
1005  }
1006 
1010  public function getId() {
1011  return $this->mId;
1012  }
1013 
1020  private function setId( $blockId ) {
1021  $this->mId = (int)$blockId;
1022 
1023  if ( is_array( $this->restrictions ) ) {
1024  $this->restrictions = $this->getBlockRestrictionStore()->setBlockId(
1025  $blockId, $this->restrictions
1026  );
1027  }
1028 
1029  return $this;
1030  }
1031 
1036  public function getParentBlockId() {
1037  return $this->mParentBlockId;
1038  }
1039 
1047  public function fromMaster( $x = null ) {
1048  wfDeprecated( __METHOD__, '1.35' );
1049  return wfSetVar( $this->mFromMaster, $x );
1050  }
1051 
1057  public function isHardblock( $x = null ) {
1058  wfSetVar( $this->isHardblock, $x );
1059 
1060  # You can't *not* hardblock a user
1061  return $this->getType() == self::TYPE_USER
1062  ? true
1064  }
1065 
1070  public function isAutoblocking( $x = null ) {
1071  wfSetVar( $this->isAutoblocking, $x );
1072 
1073  # You can't put an autoblock on an IP or range as we don't have any history to
1074  # look over to get more IPs from
1075  return $this->getType() == self::TYPE_USER
1076  ? $this->isAutoblocking
1077  : false;
1078  }
1079 
1084  public function getRedactedName() {
1085  if ( $this->mAuto ) {
1086  return Html::element(
1087  'span',
1088  [ 'class' => 'mw-autoblockid' ],
1089  wfMessage( 'autoblockid', $this->mId )->text()
1090  );
1091  } else {
1092  return htmlspecialchars( $this->getTarget() );
1093  }
1094  }
1095 
1102  public static function getAutoblockExpiry( $timestamp ) {
1103  global $wgAutoblockExpiry;
1104 
1105  return wfTimestamp( TS_MW, (int)wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
1106  }
1107 
1111  public static function purgeExpired() {
1112  if ( wfReadOnly() ) {
1113  return;
1114  }
1115 
1117  wfGetDB( DB_MASTER ),
1118  __METHOD__,
1119  function ( IDatabase $dbw, $fname ) {
1120  $ids = $dbw->selectFieldValues( 'ipblocks',
1121  'ipb_id',
1122  [ 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ],
1123  $fname
1124  );
1125  if ( $ids ) {
1126  $blockRestrictionStore = MediaWikiServices::getInstance()->getBlockRestrictionStore();
1127  $blockRestrictionStore->deleteByBlockId( $ids );
1128 
1129  $dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], $fname );
1130  }
1131  }
1132  ) );
1133  }
1134 
1155  public static function newFromTarget( $specificTarget, $vagueTarget = null, $fromMaster = false ) {
1156  $blocks = self::newListFromTarget( $specificTarget, $vagueTarget, $fromMaster );
1157  return self::chooseMostSpecificBlock( $blocks );
1158  }
1159 
1169  public static function newListFromTarget(
1170  $specificTarget,
1171  $vagueTarget = null,
1172  $fromMaster = false
1173  ) {
1174  list( $target, $type ) = self::parseTarget( $specificTarget );
1175  if ( $type == self::TYPE_ID || $type == self::TYPE_AUTO ) {
1176  $block = self::newFromID( $target );
1177  return $block ? [ $block ] : [];
1178  } elseif ( $target === null && $vagueTarget == '' ) {
1179  # We're not going to find anything useful here
1180  # Be aware that the == '' check is explicit, since empty values will be
1181  # passed by some callers (T31116)
1182  return [];
1183  } elseif ( in_array(
1184  $type,
1185  [ self::TYPE_USER, self::TYPE_IP, self::TYPE_RANGE, null ] )
1186  ) {
1187  return self::newLoad( $target, $type, $fromMaster, $vagueTarget );
1188  }
1189  return [];
1190  }
1191 
1202  public static function getBlocksForIPList( array $ipChain, $isAnon, $fromMaster = false ) {
1203  if ( $ipChain === [] ) {
1204  return [];
1205  }
1206 
1207  $conds = [];
1208  $proxyLookup = MediaWikiServices::getInstance()->getProxyLookup();
1209  foreach ( array_unique( $ipChain ) as $ipaddr ) {
1210  # Discard invalid IP addresses. Since XFF can be spoofed and we do not
1211  # necessarily trust the header given to us, make sure that we are only
1212  # checking for blocks on well-formatted IP addresses (IPv4 and IPv6).
1213  # Do not treat private IP spaces as special as it may be desirable for wikis
1214  # to block those IP ranges in order to stop misbehaving proxies that spoof XFF.
1215  if ( !IPUtils::isValid( $ipaddr ) ) {
1216  continue;
1217  }
1218  # Don't check trusted IPs (includes local CDNs which will be in every request)
1219  if ( $proxyLookup->isTrustedProxy( $ipaddr ) ) {
1220  continue;
1221  }
1222  # Check both the original IP (to check against single blocks), as well as build
1223  # the clause to check for rangeblocks for the given IP.
1224  $conds['ipb_address'][] = $ipaddr;
1225  $conds[] = self::getRangeCond( IPUtils::toHex( $ipaddr ) );
1226  }
1227 
1228  if ( $conds === [] ) {
1229  return [];
1230  }
1231 
1232  if ( $fromMaster ) {
1233  $db = wfGetDB( DB_MASTER );
1234  } else {
1235  $db = wfGetDB( DB_REPLICA );
1236  }
1237  $conds = $db->makeList( $conds, LIST_OR );
1238  if ( !$isAnon ) {
1239  $conds = [ $conds, 'ipb_anon_only' => 0 ];
1240  }
1241  $blockQuery = self::getQueryInfo();
1242  $rows = $db->select(
1243  $blockQuery['tables'],
1244  array_merge( [ 'ipb_range_start', 'ipb_range_end' ], $blockQuery['fields'] ),
1245  $conds,
1246  __METHOD__,
1247  [],
1248  $blockQuery['joins']
1249  );
1250 
1251  $blocks = [];
1252  foreach ( $rows as $row ) {
1253  $block = self::newFromRow( $row );
1254  if ( !$block->isExpired() ) {
1255  $blocks[] = $block;
1256  }
1257  }
1258 
1259  return $blocks;
1260  }
1261 
1285  public static function chooseBlock( array $blocks, array $ipChain ) {
1286  wfDeprecated( __METHOD__, '1.35' );
1287  if ( $blocks === [] ) {
1288  return null;
1289  } elseif ( count( $blocks ) == 1 ) {
1290  return $blocks[0];
1291  }
1292 
1293  // Sort hard blocks before soft ones and secondarily sort blocks
1294  // that disable account creation before those that don't.
1295  usort( $blocks, function ( DatabaseBlock $a, DatabaseBlock $b ) {
1296  $aWeight = (int)$a->isHardblock() . (int)$a->appliesToRight( 'createaccount' );
1297  $bWeight = (int)$b->isHardblock() . (int)$b->appliesToRight( 'createaccount' );
1298  return strcmp( $bWeight, $aWeight ); // highest weight first
1299  } );
1300 
1301  $blocksListExact = [
1302  'hard' => false,
1303  'disable_create' => false,
1304  'other' => false,
1305  'auto' => false
1306  ];
1307  $blocksListRange = [
1308  'hard' => false,
1309  'disable_create' => false,
1310  'other' => false,
1311  'auto' => false
1312  ];
1313  $ipChain = array_reverse( $ipChain );
1314 
1315  foreach ( $blocks as $block ) {
1316  // Stop searching if we have already have a "better" block. This
1317  // is why the order of the blocks matters
1318  if ( !$block->isHardblock() && $blocksListExact['hard'] ) {
1319  break;
1320  } elseif ( !$block->appliesToRight( 'createaccount' ) && $blocksListExact['disable_create'] ) {
1321  break;
1322  }
1323 
1324  foreach ( $ipChain as $checkip ) {
1325  $checkipHex = IPUtils::toHex( $checkip );
1326  if ( (string)$block->getTarget() === $checkip ) {
1327  if ( $block->isHardblock() ) {
1328  $blocksListExact['hard'] = $blocksListExact['hard'] ?: $block;
1329  } elseif ( $block->appliesToRight( 'createaccount' ) ) {
1330  $blocksListExact['disable_create'] = $blocksListExact['disable_create'] ?: $block;
1331  } elseif ( $block->mAuto ) {
1332  $blocksListExact['auto'] = $blocksListExact['auto'] ?: $block;
1333  } else {
1334  $blocksListExact['other'] = $blocksListExact['other'] ?: $block;
1335  }
1336  // We found closest exact match in the ip list, so go to the next block
1337  break;
1338  } elseif ( array_filter( $blocksListExact ) == []
1339  && $block->getRangeStart() <= $checkipHex
1340  && $block->getRangeEnd() >= $checkipHex
1341  ) {
1342  if ( $block->isHardblock() ) {
1343  $blocksListRange['hard'] = $blocksListRange['hard'] ?: $block;
1344  } elseif ( $block->appliesToRight( 'createaccount' ) ) {
1345  $blocksListRange['disable_create'] = $blocksListRange['disable_create'] ?: $block;
1346  } elseif ( $block->mAuto ) {
1347  $blocksListRange['auto'] = $blocksListRange['auto'] ?: $block;
1348  } else {
1349  $blocksListRange['other'] = $blocksListRange['other'] ?: $block;
1350  }
1351  break;
1352  }
1353  }
1354  }
1355 
1356  if ( array_filter( $blocksListExact ) == [] ) {
1357  $blocksList = &$blocksListRange;
1358  } else {
1359  $blocksList = &$blocksListExact;
1360  }
1361 
1362  $chosenBlock = null;
1363  if ( $blocksList['hard'] ) {
1364  $chosenBlock = $blocksList['hard'];
1365  } elseif ( $blocksList['disable_create'] ) {
1366  $chosenBlock = $blocksList['disable_create'];
1367  } elseif ( $blocksList['other'] ) {
1368  $chosenBlock = $blocksList['other'];
1369  } elseif ( $blocksList['auto'] ) {
1370  $chosenBlock = $blocksList['auto'];
1371  } else {
1372  throw new MWException( "Proxy block found, but couldn't be classified." );
1373  }
1374 
1375  return $chosenBlock;
1376  }
1377 
1384  public function getType() {
1385  return $this->mAuto
1386  ? self::TYPE_AUTO
1387  : parent::getType();
1388  }
1389 
1398  public function setCookie( WebResponse $response ) {
1399  wfDeprecated( __METHOD__, '1.34' );
1400  MediaWikiServices::getInstance()->getBlockManager()->setBlockCookie( $this, $response );
1401  }
1402 
1410  public static function clearCookie( WebResponse $response ) {
1411  wfDeprecated( __METHOD__, '1.34' );
1412  MediaWikiServices::getInstance()->getBlockManager()->clearBlockCookie( $response );
1413  }
1414 
1425  public function getCookieValue() {
1426  wfDeprecated( __METHOD__, '1.34' );
1427  return MediaWikiServices::getInstance()->getBlockManager()->getCookieValue( $this );
1428  }
1429 
1439  public static function getIdFromCookieValue( $cookieValue ) {
1440  wfDeprecated( __METHOD__, '1.34' );
1441  return MediaWikiServices::getInstance()->getBlockManager()->getIdFromCookieValue( $cookieValue );
1442  }
1443 
1447  public function getIdentifier() {
1448  return $this->getId();
1449  }
1450 
1460  public function getRestrictions() {
1461  if ( $this->restrictions === null ) {
1462  // If the block id has not been set, then do not attempt to load the
1463  // restrictions.
1464  if ( !$this->mId ) {
1465  return [];
1466  }
1467  $this->restrictions = $this->getBlockRestrictionStore()->loadByBlockId( $this->mId );
1468  }
1469 
1470  return $this->restrictions;
1471  }
1472 
1480  public function setRestrictions( array $restrictions ) {
1481  $this->restrictions = array_filter( $restrictions, function ( $restriction ) {
1482  return $restriction instanceof Restriction;
1483  } );
1484 
1485  return $this;
1486  }
1487 
1491  public function appliesToTitle( Title $title ) {
1492  if ( $this->isSitewide() ) {
1493  return true;
1494  }
1495 
1496  $restrictions = $this->getRestrictions();
1497  foreach ( $restrictions as $restriction ) {
1498  if ( $restriction->matches( $title ) ) {
1499  return true;
1500  }
1501  }
1502 
1503  return false;
1504  }
1505 
1509  public function appliesToNamespace( $ns ) {
1510  if ( $this->isSitewide() ) {
1511  return true;
1512  }
1513 
1514  // Blocks do not apply to virtual namespaces.
1515  if ( $ns < 0 ) {
1516  return false;
1517  }
1518 
1519  $restriction = $this->findRestriction( NamespaceRestriction::TYPE, $ns );
1520 
1521  return (bool)$restriction;
1522  }
1523 
1527  public function appliesToPage( $pageId ) {
1528  if ( $this->isSitewide() ) {
1529  return true;
1530  }
1531 
1532  // If the pageId is not over zero, the block cannot apply to it.
1533  if ( $pageId <= 0 ) {
1534  return false;
1535  }
1536 
1537  $restriction = $this->findRestriction( PageRestriction::TYPE, $pageId );
1538 
1539  return (bool)$restriction;
1540  }
1541 
1549  private function findRestriction( $type, $value ) {
1550  $restrictions = $this->getRestrictions();
1551  foreach ( $restrictions as $restriction ) {
1552  if ( $restriction->getType() !== $type ) {
1553  continue;
1554  }
1555 
1556  if ( $restriction->getValue() === $value ) {
1557  return $restriction;
1558  }
1559  }
1560 
1561  return null;
1562  }
1563 
1569  public function shouldTrackWithCookie( $isAnon ) {
1570  wfDeprecated( __METHOD__, '1.34' );
1571  $config = RequestContext::getMain()->getConfig();
1572  switch ( $this->getType() ) {
1573  case self::TYPE_IP:
1574  case self::TYPE_RANGE:
1575  return $isAnon && $config->get( 'CookieSetOnIpBlock' );
1576  case self::TYPE_USER:
1577  return !$isAnon && $config->get( 'CookieSetOnAutoblock' ) && $this->isAutoblocking();
1578  default:
1579  return false;
1580  }
1581  }
1582 
1589  return MediaWikiServices::getInstance()->getBlockRestrictionStore();
1590  }
1591 
1595  public function getBy() {
1596  return ( $this->blocker ) ? $this->blocker->getId() : 0;
1597  }
1598 
1602  public function getByName() {
1603  return ( $this->blocker ) ? $this->blocker->getName() : '';
1604  }
1605 
1611  public function getBlocker() {
1612  return $this->blocker;
1613  }
1614 
1620  public function setBlocker( $user ) {
1621  if ( is_string( $user ) ) {
1622  $user = User::newFromName( $user, false );
1623  }
1624 
1625  if ( $user->isAnon() && User::isUsableName( $user->getName() ) ) {
1626  // Temporarily log some block details to debug T192964
1627  $logger = LoggerFactory::getInstance( 'BlockManager' );
1628  $logger->warning(
1629  'Blocker is neither a local user nor an invalid username',
1630  [
1631  'blocker' => (string)$user,
1632  'blockId' => $this->getId(),
1633  ]
1634  );
1635  throw new \InvalidArgumentException(
1636  'Blocker must be a local user or a name that cannot be a local user'
1637  );
1638  }
1639 
1640  $this->blocker = $user;
1641  }
1642 }
1643 
1647 class_alias( DatabaseBlock::class, 'Block' );
MediaWiki\Block\DatabaseBlock\setBlocker
setBlocker( $user)
Set the user who implemented (or will implement) this block.
Definition: DatabaseBlock.php:1620
MediaWiki\Block\DatabaseBlock\getIpFragment
static getIpFragment( $hex)
Get the component of an IP address which is certain to be the same between an IP address and a rangeb...
Definition: DatabaseBlock.php:427
Wikimedia\Rdbms\Database
Relational database abstraction object.
Definition: Database.php:50
User\newFromId
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:557
MediaWiki\Block\DatabaseBlock\setCookie
setCookie(WebResponse $response)
Set the 'BlockID' cookie to this block's ID and expiry time.
Definition: DatabaseBlock.php:1398
MediaWiki\Block\DatabaseBlock\getAutoblockUpdateArray
getAutoblockUpdateArray(IDatabase $dbw)
Definition: DatabaseBlock.php:691
MediaWiki\Block\AbstractBlock\$target
User string null $target
Definition: AbstractBlock.php:75
MediaWiki\Block\DatabaseBlock\equals
equals(DatabaseBlock $block)
Check if two blocks are effectively equal.
Definition: DatabaseBlock.php:218
User\getId
getId()
Get the user's ID.
Definition: User.php:2042
MediaWiki\Block
Definition: AbstractBlock.php:21
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:152
MediaWiki\Block\DatabaseBlock\getCookieValue
getCookieValue()
Get the BlockID cookie's value for this block.
Definition: DatabaseBlock.php:1425
MediaWiki\Block\DatabaseBlock\chooseBlock
static chooseBlock(array $blocks, array $ipChain)
From a list of multiple blocks, find the most exact and strongest block.
Definition: DatabaseBlock.php:1285
MediaWiki\Block\DatabaseBlock\initFromRow
initFromRow( $row)
Given a database row from the ipblocks table, initialize member variables.
Definition: DatabaseBlock.php:441
wfSetVar
wfSetVar(&$dest, $source, $force=false)
Sets dest to source and returns the original value of dest If source is NULL, it just returns the val...
Definition: GlobalFunctions.php:1546
if
if(ini_get( 'mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition: Setup.php:85
AutoCommitUpdate
Deferrable Update for closure/callback updates that should use auto-commit mode.
Definition: AutoCommitUpdate.php:9
MediaWiki\Logger\LoggerFactory\getInstance
static getInstance( $channel)
Get a named logger instance from the currently configured logger factory.
Definition: LoggerFactory.php:92
MediaWiki\Block\DatabaseBlock\getRangeStart
getRangeStart()
Get the IP address at the start of the range in Hex form.
Definition: DatabaseBlock.php:963
MediaWiki\Block\DatabaseBlock\$mParentBlockId
int $mParentBlockId
Definition: DatabaseBlock.php:65
true
return true
Definition: router.php:90
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1811
$wgAutoblockExpiry
$wgAutoblockExpiry
Number of seconds before autoblock entries expire.
Definition: DefaultSettings.php:5409
MediaWiki\Block\DatabaseBlock\shouldTrackWithCookie
shouldTrackWithCookie( $isAnon)
Definition: DatabaseBlock.php:1569
Wikimedia\Rdbms\IDatabase\encodeExpiry
encodeExpiry( $expiry)
Encode an expiry time into the DBMS dependent format.
MediaWiki\Block\DatabaseBlock\getType
getType()
Get the type of target for this particular block.int|null AbstractBlock::TYPE_ constant,...
Definition: DatabaseBlock.php:1384
MediaWiki\Block\Restriction\NamespaceRestriction\TYPE
const TYPE
Definition: NamespaceRestriction.php:30
DeferredUpdates\addUpdate
static addUpdate(DeferrableUpdate $update, $stage=self::POSTSEND)
Add an update to the deferred update queue for execution at the appropriate time.
Definition: DeferredUpdates.php:106
MediaWiki\Block\AbstractBlock\isCreateAccountBlocked
isCreateAccountBlocked( $x=null)
Get or set the flag indicating whether this block blocks the target from creating an account.
Definition: AbstractBlock.php:227
MediaWiki\Block\DatabaseBlock\getBlocker
getBlocker()
Get the user who implemented this block.
Definition: DatabaseBlock.php:1611
MediaWiki\Block\DatabaseBlock\__construct
__construct(array $options=[])
Create a new block with specified option parameters on a user, IP or IP range.
Definition: DatabaseBlock.php:108
MediaWiki\Block\DatabaseBlock\doRetroactiveAutoblock
doRetroactiveAutoblock()
Retroactively autoblocks the last IP used by the user (if it is a user) blocked by this block.
Definition: DatabaseBlock.php:707
MediaWiki\Block\DatabaseBlock\getDatabaseArray
getDatabaseArray(IDatabase $dbw)
Get an array suitable for passing to $dbw->insert() or $dbw->update()
Definition: DatabaseBlock.php:656
MediaWiki\Block\AbstractBlock\TYPE_AUTO
const TYPE_AUTO
Definition: AbstractBlock.php:90
CommentStore
CommentStore handles storage of comments (edit summaries, log reasons, etc) in the database.
Definition: CommentStore.php:31
wfReadOnly
wfReadOnly()
Check whether the wiki is in read-only mode.
Definition: GlobalFunctions.php:1128
User\newFromName
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:533
MediaWiki\Block\DatabaseBlock\appliesToNamespace
appliesToNamespace( $ns)
Checks if a block applies to a particular namespace.1.33bool
Definition: DatabaseBlock.php:1509
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1222
MediaWiki\Block\DatabaseBlock\getByName
getByName()
Get the username of the blocking sysop.string
Definition: DatabaseBlock.php:1602
$success
$success
Definition: NoLocalSettings.php:42
ActorMigration
This class handles the logic for the actor table migration.
Definition: ActorMigration.php:38
$res
$res
Definition: testCompression.php:57
ActorMigration\newMigration
static newMigration()
Static constructor.
Definition: ActorMigration.php:139
LIST_AND
const LIST_AND
Definition: Defines.php:48
$wgPutIPinRC
$wgPutIPinRC
Log IP addresses in the recentchanges table; can be accessed only by extensions (e....
Definition: DefaultSettings.php:6191
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
$dbr
$dbr
Definition: testCompression.php:54
MediaWiki\Block\DatabaseBlock\deleteIfExpired
deleteIfExpired()
Check if a block has expired.
Definition: DatabaseBlock.php:907
MediaWiki\MediaWikiServices\getInstance
static getInstance()
Returns the global default instance of the top level service locator.
Definition: MediaWikiServices.php:183
MediaWiki\Block\AbstractBlock\TYPE_RANGE
const TYPE_RANGE
Definition: AbstractBlock.php:89
MediaWiki\Block\DatabaseBlock\appliesToPage
appliesToPage( $pageId)
Checks if a block applies to a particular page.This check does not consider whether $this->isUsertalk...
Definition: DatabaseBlock.php:1527
MediaWiki\Block\DatabaseBlock
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
Definition: DatabaseBlock.php:54
MediaWiki\Block\DatabaseBlock\setRestrictions
setRestrictions(array $restrictions)
Set Restrictions.
Definition: DatabaseBlock.php:1480
Wikimedia\Rdbms\IDatabase\timestamp
timestamp( $ts=0)
Convert a timestamp in one of the formats accepted by ConvertibleTimestamp to the format used for ins...
LIST_OR
const LIST_OR
Definition: Defines.php:51
MWException
MediaWiki exception.
Definition: MWException.php:26
MediaWiki\Block\DatabaseBlock\getBlocksForIPList
static getBlocksForIPList(array $ipChain, $isAnon, $fromMaster=false)
Get all blocks that match any IP from an array of IP addresses.
Definition: DatabaseBlock.php:1202
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1029
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
MediaWiki\Block\DatabaseBlock\$blocker
User $blocker
Definition: DatabaseBlock.php:86
Wikimedia\Rdbms\Database\getCacheSetOptions
static getCacheSetOptions(IDatabase $db1, IDatabase $db2=null)
Merge the result of getSessionLagStatus() for several DBs using the most pessimistic values to estima...
Definition: Database.php:4656
MediaWiki\Block\DatabaseBlock\$mFromMaster
bool $mFromMaster
Definition: DatabaseBlock.php:71
Config\get
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
MediaWiki\Block\DatabaseBlock\purgeExpired
static purgeExpired()
Purge expired blocks from the ipblocks table.
Definition: DatabaseBlock.php:1111
MediaWiki\Block\DatabaseBlock\defaultRetroactiveAutoblock
static defaultRetroactiveAutoblock(DatabaseBlock $block, array &$blockIds)
Retroactively autoblocks the last IP used by the user (if it is a user) blocked by this block.
Definition: DatabaseBlock.php:729
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2464
DeferredUpdates
Class for managing the deferred updates.
Definition: DeferredUpdates.php:62
MediaWiki\Block\AbstractBlock\isEmailBlocked
isEmailBlocked( $x=null)
Get or set the flag indicating whether this block blocks the target from sending emails.
Definition: AbstractBlock.php:240
MediaWiki\Block\DatabaseBlock\newFromRow
static newFromRow( $row)
Create a new DatabaseBlock object from a database row.
Definition: DatabaseBlock.php:477
MediaWiki\Block\Restriction\Restriction
Definition: Restriction.php:25
MediaWiki\Block\AbstractBlock\getReasonComment
getReasonComment()
Get the reason for creating the block.
Definition: AbstractBlock.php:171
MediaWiki\Block\DatabaseBlock\$forcedTargetID
int $forcedTargetID
Hack for foreign blocking (CentralAuth)
Definition: DatabaseBlock.php:74
MediaWiki\Block\Restriction\PageRestriction\TYPE
const TYPE
Definition: PageRestriction.php:30
MediaWiki\Block\DatabaseBlock\isWhitelistedFromAutoblocks
static isWhitelistedFromAutoblocks( $ip)
Checks whether a given IP is on the autoblock whitelist.
Definition: DatabaseBlock.php:782
MediaWiki\Block\AbstractBlock\TYPE_IP
const TYPE_IP
Definition: AbstractBlock.php:88
MediaWiki\Block\DatabaseBlock\getRangeEnd
getRangeEnd()
Get the IP address at the end of the range in Hex form.
Definition: DatabaseBlock.php:982
$title
$title
Definition: testCompression.php:38
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:1840
RequestContext
Group all the pieces relevant to the context of a request into one instance.
Definition: RequestContext.php:34
User\newFromAnyId
static newFromAnyId( $userId, $userName, $actorId, $dbDomain=false)
Static factory method for creation from an ID, name, and/or actor ID.
Definition: User.php:608
MediaWiki\Block\DatabaseBlock\isExpired
isExpired()
Has the block expired?
Definition: DatabaseBlock.php:925
MediaWiki\Block\AbstractBlock\isSitewide
isSitewide( $x=null)
Indicates that the block is a sitewide block.
Definition: AbstractBlock.php:214
DB_MASTER
const DB_MASTER
Definition: defines.php:26
MediaWiki\Block\DatabaseBlock\getIdFromCookieValue
static getIdFromCookieValue( $cookieValue)
Get the stored ID from the 'BlockID' cookie.
Definition: DatabaseBlock.php:1439
MediaWiki\Block\DatabaseBlock\fromMaster
fromMaster( $x=null)
Get/set a flag determining whether the master is used for reads.
Definition: DatabaseBlock.php:1047
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:912
MediaWiki\Block\DatabaseBlock\getRangeCond
static getRangeCond( $start, $end=null)
Get a set of SQL conditions which will select rangeblocks encompassing a given range.
Definition: DatabaseBlock.php:394
MediaWiki\Block\DatabaseBlock\getBlockRestrictionStore
getBlockRestrictionStore()
Get a BlockRestrictionStore instance.
Definition: DatabaseBlock.php:1588
MediaWiki\Block\DatabaseBlock\getRedactedName
getRedactedName()
Get the block name, but with autoblocked IPs hidden as per standard privacy policy.
Definition: DatabaseBlock.php:1084
MediaWiki\Block\DatabaseBlock\isAutoblocking
isAutoblocking( $x=null)
Definition: DatabaseBlock.php:1070
MediaWiki\Block\AbstractBlock\setTimestamp
setTimestamp( $timestamp)
Set the timestamp indicating when the block was created.
Definition: AbstractBlock.php:498
MediaWiki\Block\DatabaseBlock\getBy
getBy()
Get the user id of the blocking sysop.int (0 for foreign users)
Definition: DatabaseBlock.php:1595
MediaWiki\Block\AbstractBlock\parseTarget
static parseTarget( $target)
From an existing block, get the target and the type of target.
Definition: AbstractBlock.php:379
MediaWiki\Block\AbstractBlock\TYPE_USER
const TYPE_USER
Definition: AbstractBlock.php:87
MediaWiki\Block\DatabaseBlock\getIdentifier
getIdentifier()
Get the information that identifies this block, such that a user could look up everything that can be...
Definition: DatabaseBlock.php:1447
MediaWiki\Block\DatabaseBlock\getParentBlockId
getParentBlockId()
Definition: DatabaseBlock.php:1036
MediaWiki\Block\DatabaseBlock\$isAutoblocking
bool $isAutoblocking
Definition: DatabaseBlock.php:80
MediaWiki\Block\DatabaseBlock\newLoad
static newLoad( $specificTarget, $specificType, $fromMaster, $vagueTarget=null)
Load blocks from the database which target the specific target exactly, or which cover the vague targ...
Definition: DatabaseBlock.php:252
MediaWiki\Block\DatabaseBlock\getReason
getReason()
Get the reason given for creating the block, as a string.Deprecated, since this gives the caller no c...
Definition: DatabaseBlock.php:1000
Hooks\runner
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
Definition: Hooks.php:172
$line
$line
Definition: mcc.php:119
$wgBlockDisablesLogin
$wgBlockDisablesLogin
If true, blocked users will not be allowed to login.
Definition: DefaultSettings.php:5446
MediaWiki\Block\AbstractBlock\setExpiry
setExpiry( $expiry)
Set the block expiry time.
Definition: AbstractBlock.php:478
MediaWiki\Block\DatabaseBlock\clearCookie
static clearCookie(WebResponse $response)
Unset the 'BlockID' cookie.
Definition: DatabaseBlock.php:1410
MediaWiki\Block\AbstractBlock\getExpiry
getExpiry()
Get the block expiry time.
Definition: AbstractBlock.php:468
MediaWiki\Block\DatabaseBlock\update
update()
Update a block in the DB with new parameters.
Definition: DatabaseBlock.php:593
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:451
$lines
if(!file_exists( $CREDITS)) $lines
Definition: updateCredits.php:49
MediaWiki\Block\Restriction\NamespaceRestriction
Definition: NamespaceRestriction.php:25
MediaWiki\Block\AbstractBlock\getTimestamp
getTimestamp()
Get the timestamp indicating when the block was created.
Definition: AbstractBlock.php:488
MediaWiki\Block\DatabaseBlock\getId
getId()
Get the block ID.int|null
Definition: DatabaseBlock.php:1010
Title
Represents a title within MediaWiki.
Definition: Title.php:42
$wgBlockCIDRLimit
$wgBlockCIDRLimit
Limits on the possible sizes of range blocks.
Definition: DefaultSettings.php:5434
MediaWiki\Block\DatabaseBlock\setId
setId( $blockId)
Set the block ID.
Definition: DatabaseBlock.php:1020
MediaWiki\Block\AbstractBlock\appliesToRight
appliesToRight( $right)
Determine whether the block prevents a given right.
Definition: AbstractBlock.php:268
$cache
$cache
Definition: mcc.php:33
Wikimedia\Rdbms\IDatabase\addQuotes
addQuotes( $s)
Escape and quote a raw value string for use in a SQL query.
MediaWiki\Block\DatabaseBlock\chooseMostSpecificBlock
static chooseMostSpecificBlock(array $blocks)
Choose the most specific block from some combination of user, IP and IP range blocks.
Definition: DatabaseBlock.php:352
MediaWiki\Block\Restriction\PageRestriction
Definition: PageRestriction.php:25
MediaWiki\Block\AbstractBlock\setReason
setReason( $reason)
Set the reason for creating the block.
Definition: AbstractBlock.php:181
MediaWiki\Block\DatabaseBlock\getRestrictions
getRestrictions()
Get Restrictions.
Definition: DatabaseBlock.php:1460
MediaWiki\$config
Config $config
Definition: MediaWiki.php:42
MediaWiki\Block\DatabaseBlock\updateTimestamp
updateTimestamp()
Update the timestamp on autoblocks.
Definition: DatabaseBlock.php:939
MediaWiki\Block\DatabaseBlock\getQueryInfo
static getQueryInfo()
Return the tables, fields, and join conditions to be selected to create a new block object.
Definition: DatabaseBlock.php:187
Wikimedia\Rdbms\IDatabase\selectFieldValues
selectFieldValues( $table, $var, $cond='', $fname=__METHOD__, $options=[], $join_conds=[])
A SELECT wrapper which returns a list of single field values from result rows.
MediaWiki\Block\DatabaseBlock\doAutoblock
doAutoblock( $autoblockIP)
Autoblocks the given IP, referring to this block.
Definition: DatabaseBlock.php:828
MediaWiki\Block\DatabaseBlock\findRestriction
findRestriction( $type, $value)
Find Restriction by type and value.
Definition: DatabaseBlock.php:1549
MediaWiki\Block\DatabaseBlock\newFromTarget
static newFromTarget( $specificTarget, $vagueTarget=null, $fromMaster=false)
Given a target and the target's type, get an existing block object if possible.
Definition: DatabaseBlock.php:1155
MediaWiki\Block\DatabaseBlock\getAutoblockExpiry
static getAutoblockExpiry( $timestamp)
Get a timestamp of the expiry for autoblocks.
Definition: DatabaseBlock.php:1102
MediaWiki\Block\AbstractBlock\getHideName
getHideName()
Get whether the block hides the target's username.
Definition: AbstractBlock.php:191
MediaWiki\Block\AbstractBlock\$type
int null $type
AbstractBlock::TYPE_ constant.
Definition: AbstractBlock.php:81
MediaWiki\Block\AbstractBlock
Definition: AbstractBlock.php:37
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:231
MediaWiki\Block\DatabaseBlock\$mAuto
bool $mAuto
Definition: DatabaseBlock.php:59
User\isUsableName
static isUsableName( $name)
Usernames which fail to pass this function will be blocked from user login and new account registrati...
Definition: User.php:987
MediaWiki\Block\AbstractBlock\setTarget
setTarget( $target)
Set the target for this block, and update $this->type accordingly.
Definition: AbstractBlock.php:506
WebResponse
Allow programs to request this object from WebRequest::response() and handle all outputting (or lack ...
Definition: WebResponse.php:28
CommentStore\getStore
static getStore()
Definition: CommentStore.php:109
MediaWiki\Block\DatabaseBlock\$isHardblock
bool $isHardblock
Definition: DatabaseBlock.php:77
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:54
MediaWiki\Block\DatabaseBlock\insert
insert(IDatabase $dbw=null)
Insert a block into the block table.
Definition: DatabaseBlock.php:519
MediaWiki\Block\DatabaseBlock\appliesToTitle
appliesToTitle(Title $title)
Checks if a block applies to a particular title.This check does not consider whether $this->isUsertal...
Definition: DatabaseBlock.php:1491
MediaWiki\Block\AbstractBlock\getTarget
getTarget()
Get the target for this particular block.
Definition: AbstractBlock.php:458
MediaWiki\Block\DatabaseBlock\isHardblock
isHardblock( $x=null)
Get/set whether the block is a hardblock (affects logged-in users on a given IP/range)
Definition: DatabaseBlock.php:1057
MediaWiki\Block\DatabaseBlock\newListFromTarget
static newListFromTarget( $specificTarget, $vagueTarget=null, $fromMaster=false)
This is similar to DatabaseBlock::newFromTarget, but it returns all the relevant blocks.
Definition: DatabaseBlock.php:1169
MediaWiki\Block\DatabaseBlock\$restrictions
Restriction[] $restrictions
Definition: DatabaseBlock.php:83
MediaWiki\Block\AbstractBlock\isUsertalkEditAllowed
isUsertalkEditAllowed( $x=null)
Get or set the flag indicating whether this block blocks the target from editing their own user talk ...
Definition: AbstractBlock.php:253
Wikimedia\Rdbms\IDatabase\delete
delete( $table, $conds, $fname=__METHOD__)
Delete all rows in a table that match a condition.
MediaWiki\Block\DatabaseBlock\$mId
int $mId
Definition: DatabaseBlock.php:68
Hooks
Hooks class.
Definition: Hooks.php:38
MediaWiki\Block\BlockRestrictionStore
Definition: BlockRestrictionStore.php:34
MediaWiki\Block\DatabaseBlock\newFromID
static newFromID( $id)
Load a block from the block id.
Definition: DatabaseBlock.php:160
Html
This class is a collection of static functions that serve two purposes:
Definition: Html.php:49