MediaWiki  1.27.4
Block.php
Go to the documentation of this file.
1 <?php
22 class Block {
24  public $mReason;
25 
27  public $mTimestamp;
28 
30  public $mAuto;
31 
33  public $mExpiry;
34 
36  public $mHideName;
37 
40 
42  protected $mId;
43 
45  protected $mFromMaster;
46 
48  protected $mBlockEmail;
49 
51  protected $mDisableUsertalk;
52 
54  protected $mCreateAccount;
55 
57  protected $target;
58 
60  protected $forcedTargetID;
61 
63  protected $type;
64 
66  protected $blocker;
67 
69  protected $isHardblock;
70 
72  protected $isAutoblocking;
73 
74  # TYPE constants
75  const TYPE_USER = 1;
76  const TYPE_IP = 2;
77  const TYPE_RANGE = 3;
78  const TYPE_AUTO = 4;
79  const TYPE_ID = 5;
80 
103  function __construct( $options = [] ) {
104  $defaults = [
105  'address' => '',
106  'user' => null,
107  'by' => null,
108  'reason' => '',
109  'timestamp' => '',
110  'auto' => false,
111  'expiry' => '',
112  'anonOnly' => false,
113  'createAccount' => false,
114  'enableAutoblock' => false,
115  'hideName' => false,
116  'blockEmail' => false,
117  'allowUsertalk' => false,
118  'byText' => '',
119  ];
120 
121  if ( func_num_args() > 1 || !is_array( $options ) ) {
122  $options = array_combine(
123  array_slice( array_keys( $defaults ), 0, func_num_args() ),
124  func_get_args()
125  );
126  wfDeprecated( __METHOD__ . ' with multiple arguments', '1.26' );
127  }
128 
129  $options += $defaults;
130 
131  $this->setTarget( $options['address'] );
132 
133  if ( $this->target instanceof User && $options['user'] ) {
134  # Needed for foreign users
135  $this->forcedTargetID = $options['user'];
136  }
137 
138  if ( $options['by'] ) {
139  # Local user
140  $this->setBlocker( User::newFromId( $options['by'] ) );
141  } else {
142  # Foreign user
143  $this->setBlocker( $options['byText'] );
144  }
145 
146  $this->mReason = $options['reason'];
147  $this->mTimestamp = wfTimestamp( TS_MW, $options['timestamp'] );
148  $this->mExpiry = wfGetDB( DB_SLAVE )->decodeExpiry( $options['expiry'] );
149 
150  # Boolean settings
151  $this->mAuto = (bool)$options['auto'];
152  $this->mHideName = (bool)$options['hideName'];
153  $this->isHardblock( !$options['anonOnly'] );
154  $this->isAutoblocking( (bool)$options['enableAutoblock'] );
155 
156  # Prevention measures
157  $this->prevents( 'sendemail', (bool)$options['blockEmail'] );
158  $this->prevents( 'editownusertalk', !$options['allowUsertalk'] );
159  $this->prevents( 'createaccount', (bool)$options['createAccount'] );
160 
161  $this->mFromMaster = false;
162  }
163 
170  public static function newFromID( $id ) {
171  $dbr = wfGetDB( DB_SLAVE );
172  $res = $dbr->selectRow(
173  'ipblocks',
174  self::selectFields(),
175  [ 'ipb_id' => $id ],
176  __METHOD__
177  );
178  if ( $res ) {
179  return self::newFromRow( $res );
180  } else {
181  return null;
182  }
183  }
184 
190  public static function selectFields() {
191  return [
192  'ipb_id',
193  'ipb_address',
194  'ipb_by',
195  'ipb_by_text',
196  'ipb_reason',
197  'ipb_timestamp',
198  'ipb_auto',
199  'ipb_anon_only',
200  'ipb_create_account',
201  'ipb_enable_autoblock',
202  'ipb_expiry',
203  'ipb_deleted',
204  'ipb_block_email',
205  'ipb_allow_usertalk',
206  'ipb_parent_block_id',
207  ];
208  }
209 
218  public function equals( Block $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->prevents( 'createaccount' ) == $block->prevents( 'createaccount' )
225  && $this->mExpiry == $block->mExpiry
226  && $this->isAutoblocking() == $block->isAutoblocking()
227  && $this->mHideName == $block->mHideName
228  && $this->prevents( 'sendemail' ) == $block->prevents( 'sendemail' )
229  && $this->prevents( 'editownusertalk' ) == $block->prevents( 'editownusertalk' )
230  && $this->mReason == $block->mReason
231  );
232  }
233 
244  protected function newLoad( $vagueTarget = null ) {
245  $db = wfGetDB( $this->mFromMaster ? DB_MASTER : DB_SLAVE );
246 
247  if ( $this->type !== null ) {
248  $conds = [
249  'ipb_address' => [ (string)$this->target ],
250  ];
251  } else {
252  $conds = [ 'ipb_address' => [] ];
253  }
254 
255  # Be aware that the != '' check is explicit, since empty values will be
256  # passed by some callers (bug 29116)
257  if ( $vagueTarget != '' ) {
258  list( $target, $type ) = self::parseTarget( $vagueTarget );
259  switch ( $type ) {
260  case self::TYPE_USER:
261  # Slightly weird, but who are we to argue?
262  $conds['ipb_address'][] = (string)$target;
263  break;
264 
265  case self::TYPE_IP:
266  $conds['ipb_address'][] = (string)$target;
267  $conds[] = self::getRangeCond( IP::toHex( $target ) );
268  $conds = $db->makeList( $conds, LIST_OR );
269  break;
270 
271  case self::TYPE_RANGE:
272  list( $start, $end ) = IP::parseRange( $target );
273  $conds['ipb_address'][] = (string)$target;
274  $conds[] = self::getRangeCond( $start, $end );
275  $conds = $db->makeList( $conds, LIST_OR );
276  break;
277 
278  default:
279  throw new MWException( "Tried to load block with invalid type" );
280  }
281  }
282 
283  $res = $db->select( 'ipblocks', self::selectFields(), $conds, __METHOD__ );
284 
285  # This result could contain a block on the user, a block on the IP, and a russian-doll
286  # set of rangeblocks. We want to choose the most specific one, so keep a leader board.
287  $bestRow = null;
288 
289  # Lower will be better
290  $bestBlockScore = 100;
291 
292  # This is begging for $this = $bestBlock, but that's not allowed in PHP :(
293  $bestBlockPreventsEdit = null;
294 
295  foreach ( $res as $row ) {
296  $block = self::newFromRow( $row );
297 
298  # Don't use expired blocks
299  if ( $block->isExpired() ) {
300  continue;
301  }
302 
303  # Don't use anon only blocks on users
304  if ( $this->type == self::TYPE_USER && !$block->isHardblock() ) {
305  continue;
306  }
307 
308  if ( $block->getType() == self::TYPE_RANGE ) {
309  # This is the number of bits that are allowed to vary in the block, give
310  # or take some floating point errors
311  $end = Wikimedia\base_convert( $block->getRangeEnd(), 16, 10 );
312  $start = Wikimedia\base_convert( $block->getRangeStart(), 16, 10 );
313  $size = log( $end - $start + 1, 2 );
314 
315  # This has the nice property that a /32 block is ranked equally with a
316  # single-IP block, which is exactly what it is...
317  $score = self::TYPE_RANGE - 1 + ( $size / 128 );
318 
319  } else {
320  $score = $block->getType();
321  }
322 
323  if ( $score < $bestBlockScore ) {
324  $bestBlockScore = $score;
325  $bestRow = $row;
326  $bestBlockPreventsEdit = $block->prevents( 'edit' );
327  }
328  }
329 
330  if ( $bestRow !== null ) {
331  $this->initFromRow( $bestRow );
332  $this->prevents( 'edit', $bestBlockPreventsEdit );
333  return true;
334  } else {
335  return false;
336  }
337  }
338 
345  public static function getRangeCond( $start, $end = null ) {
346  if ( $end === null ) {
347  $end = $start;
348  }
349  # Per bug 14634, we want to include relevant active rangeblocks; for
350  # rangeblocks, we want to include larger ranges which enclose the given
351  # range. We know that all blocks must be smaller than $wgBlockCIDRLimit,
352  # so we can improve performance by filtering on a LIKE clause
353  $chunk = self::getIpFragment( $start );
354  $dbr = wfGetDB( DB_SLAVE );
355  $like = $dbr->buildLike( $chunk, $dbr->anyString() );
356 
357  # Fairly hard to make a malicious SQL statement out of hex characters,
358  # but stranger things have happened...
359  $safeStart = $dbr->addQuotes( $start );
360  $safeEnd = $dbr->addQuotes( $end );
361 
362  return $dbr->makeList(
363  [
364  "ipb_range_start $like",
365  "ipb_range_start <= $safeStart",
366  "ipb_range_end >= $safeEnd",
367  ],
368  LIST_AND
369  );
370  }
371 
378  protected static function getIpFragment( $hex ) {
379  global $wgBlockCIDRLimit;
380  if ( substr( $hex, 0, 3 ) == 'v6-' ) {
381  return 'v6-' . substr( substr( $hex, 3 ), 0, floor( $wgBlockCIDRLimit['IPv6'] / 4 ) );
382  } else {
383  return substr( $hex, 0, floor( $wgBlockCIDRLimit['IPv4'] / 4 ) );
384  }
385  }
386 
392  protected function initFromRow( $row ) {
393  $this->setTarget( $row->ipb_address );
394  if ( $row->ipb_by ) { // local user
395  $this->setBlocker( User::newFromId( $row->ipb_by ) );
396  } else { // foreign user
397  $this->setBlocker( $row->ipb_by_text );
398  }
399 
400  $this->mReason = $row->ipb_reason;
401  $this->mTimestamp = wfTimestamp( TS_MW, $row->ipb_timestamp );
402  $this->mAuto = $row->ipb_auto;
403  $this->mHideName = $row->ipb_deleted;
404  $this->mId = (int)$row->ipb_id;
405  $this->mParentBlockId = $row->ipb_parent_block_id;
406 
407  // I wish I didn't have to do this
408  $this->mExpiry = wfGetDB( DB_SLAVE )->decodeExpiry( $row->ipb_expiry );
409 
410  $this->isHardblock( !$row->ipb_anon_only );
411  $this->isAutoblocking( $row->ipb_enable_autoblock );
412 
413  $this->prevents( 'createaccount', $row->ipb_create_account );
414  $this->prevents( 'sendemail', $row->ipb_block_email );
415  $this->prevents( 'editownusertalk', !$row->ipb_allow_usertalk );
416  }
417 
423  public static function newFromRow( $row ) {
424  $block = new Block;
425  $block->initFromRow( $row );
426  return $block;
427  }
428 
435  public function delete() {
436  if ( wfReadOnly() ) {
437  return false;
438  }
439 
440  if ( !$this->getId() ) {
441  throw new MWException( "Block::delete() requires that the mId member be filled\n" );
442  }
443 
444  $dbw = wfGetDB( DB_MASTER );
445  $dbw->delete( 'ipblocks', [ 'ipb_parent_block_id' => $this->getId() ], __METHOD__ );
446  $dbw->delete( 'ipblocks', [ 'ipb_id' => $this->getId() ], __METHOD__ );
447 
448  return $dbw->affectedRows() > 0;
449  }
450 
459  public function insert( $dbw = null ) {
460  global $wgBlockDisablesLogin;
461  wfDebug( "Block::insert; timestamp {$this->mTimestamp}\n" );
462 
463  if ( $dbw === null ) {
464  $dbw = wfGetDB( DB_MASTER );
465  }
466 
467  # Periodic purge via commit hooks
468  if ( mt_rand( 0, 9 ) == 0 ) {
470  }
471 
472  $row = $this->getDatabaseArray();
473  $row['ipb_id'] = $dbw->nextSequenceValue( "ipblocks_ipb_id_seq" );
474 
475  $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
476  $affected = $dbw->affectedRows();
477  $this->mId = $dbw->insertId();
478 
479  # Don't collide with expired blocks.
480  # Do this after trying to insert to avoid locking.
481  if ( !$affected ) {
482  # T96428: The ipb_address index uses a prefix on a field, so
483  # use a standard SELECT + DELETE to avoid annoying gap locks.
484  $ids = $dbw->selectFieldValues( 'ipblocks',
485  'ipb_id',
486  [
487  'ipb_address' => $row['ipb_address'],
488  'ipb_user' => $row['ipb_user'],
489  'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() )
490  ],
491  __METHOD__
492  );
493  if ( $ids ) {
494  $dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], __METHOD__ );
495  $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
496  $affected = $dbw->affectedRows();
497  $this->mId = $dbw->insertId();
498  }
499  }
500 
501  if ( $affected ) {
502  $auto_ipd_ids = $this->doRetroactiveAutoblock();
503 
504  if ( $wgBlockDisablesLogin && $this->target instanceof User ) {
505  // Change user login token to force them to be logged out.
506  $this->target->setToken();
507  $this->target->saveSettings();
508  }
509 
510  return [ 'id' => $this->mId, 'autoIds' => $auto_ipd_ids ];
511  }
512 
513  return false;
514  }
515 
523  public function update() {
524  wfDebug( "Block::update; timestamp {$this->mTimestamp}\n" );
525  $dbw = wfGetDB( DB_MASTER );
526 
527  $dbw->startAtomic( __METHOD__ );
528 
529  $dbw->update(
530  'ipblocks',
531  $this->getDatabaseArray( $dbw ),
532  [ 'ipb_id' => $this->getId() ],
533  __METHOD__
534  );
535 
536  $affected = $dbw->affectedRows();
537 
538  if ( $this->isAutoblocking() ) {
539  // update corresponding autoblock(s) (bug 48813)
540  $dbw->update(
541  'ipblocks',
542  $this->getAutoblockUpdateArray(),
543  [ 'ipb_parent_block_id' => $this->getId() ],
544  __METHOD__
545  );
546  } else {
547  // autoblock no longer required, delete corresponding autoblock(s)
548  $dbw->delete(
549  'ipblocks',
550  [ 'ipb_parent_block_id' => $this->getId() ],
551  __METHOD__
552  );
553  }
554 
555  $dbw->endAtomic( __METHOD__ );
556 
557  if ( $affected ) {
558  $auto_ipd_ids = $this->doRetroactiveAutoblock();
559  return [ 'id' => $this->mId, 'autoIds' => $auto_ipd_ids ];
560  }
561 
562  return false;
563  }
564 
570  protected function getDatabaseArray( $db = null ) {
571  if ( !$db ) {
572  $db = wfGetDB( DB_SLAVE );
573  }
574  $expiry = $db->encodeExpiry( $this->mExpiry );
575 
576  if ( $this->forcedTargetID ) {
577  $uid = $this->forcedTargetID;
578  } else {
579  $uid = $this->target instanceof User ? $this->target->getId() : 0;
580  }
581 
582  $a = [
583  'ipb_address' => (string)$this->target,
584  'ipb_user' => $uid,
585  'ipb_by' => $this->getBy(),
586  'ipb_by_text' => $this->getByName(),
587  'ipb_reason' => $this->mReason,
588  'ipb_timestamp' => $db->timestamp( $this->mTimestamp ),
589  'ipb_auto' => $this->mAuto,
590  'ipb_anon_only' => !$this->isHardblock(),
591  'ipb_create_account' => $this->prevents( 'createaccount' ),
592  'ipb_enable_autoblock' => $this->isAutoblocking(),
593  'ipb_expiry' => $expiry,
594  'ipb_range_start' => $this->getRangeStart(),
595  'ipb_range_end' => $this->getRangeEnd(),
596  'ipb_deleted' => intval( $this->mHideName ), // typecast required for SQLite
597  'ipb_block_email' => $this->prevents( 'sendemail' ),
598  'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' ),
599  'ipb_parent_block_id' => $this->mParentBlockId
600  ];
601 
602  return $a;
603  }
604 
608  protected function getAutoblockUpdateArray() {
609  return [
610  'ipb_by' => $this->getBy(),
611  'ipb_by_text' => $this->getByName(),
612  'ipb_reason' => $this->mReason,
613  'ipb_create_account' => $this->prevents( 'createaccount' ),
614  'ipb_deleted' => (int)$this->mHideName, // typecast required for SQLite
615  'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' ),
616  ];
617  }
618 
625  protected function doRetroactiveAutoblock() {
626  $blockIds = [];
627  # If autoblock is enabled, autoblock the LAST IP(s) used
628  if ( $this->isAutoblocking() && $this->getType() == self::TYPE_USER ) {
629  wfDebug( "Doing retroactive autoblocks for " . $this->getTarget() . "\n" );
630 
631  $continue = Hooks::run(
632  'PerformRetroactiveAutoblock', [ $this, &$blockIds ] );
633 
634  if ( $continue ) {
635  self::defaultRetroactiveAutoblock( $this, $blockIds );
636  }
637  }
638  return $blockIds;
639  }
640 
648  protected static function defaultRetroactiveAutoblock( Block $block, array &$blockIds ) {
649  global $wgPutIPinRC;
650 
651  // No IPs are in recentchanges table, so nothing to select
652  if ( !$wgPutIPinRC ) {
653  return;
654  }
655 
656  $dbr = wfGetDB( DB_SLAVE );
657 
658  $options = [ 'ORDER BY' => 'rc_timestamp DESC' ];
659  $conds = [ 'rc_user_text' => (string)$block->getTarget() ];
660 
661  // Just the last IP used.
662  $options['LIMIT'] = 1;
663 
664  $res = $dbr->select( 'recentchanges', [ 'rc_ip' ], $conds,
665  __METHOD__, $options );
666 
667  if ( !$res->numRows() ) {
668  # No results, don't autoblock anything
669  wfDebug( "No IP found to retroactively autoblock\n" );
670  } else {
671  foreach ( $res as $row ) {
672  if ( $row->rc_ip ) {
673  $id = $block->doAutoblock( $row->rc_ip );
674  if ( $id ) {
675  $blockIds[] = $id;
676  }
677  }
678  }
679  }
680  }
681 
689  public static function isWhitelistedFromAutoblocks( $ip ) {
690  // Try to get the autoblock_whitelist from the cache, as it's faster
691  // than getting the msg raw and explode()'ing it.
693  $lines = $cache->getWithSetCallback(
694  wfMemcKey( 'ipb', 'autoblock', 'whitelist' ),
695  $cache::TTL_DAY,
696  function () {
697  return explode( "\n",
698  wfMessage( 'autoblock_whitelist' )->inContentLanguage()->plain() );
699  }
700  );
701 
702  wfDebug( "Checking the autoblock whitelist..\n" );
703 
704  foreach ( $lines as $line ) {
705  # List items only
706  if ( substr( $line, 0, 1 ) !== '*' ) {
707  continue;
708  }
709 
710  $wlEntry = substr( $line, 1 );
711  $wlEntry = trim( $wlEntry );
712 
713  wfDebug( "Checking $ip against $wlEntry..." );
714 
715  # Is the IP in this range?
716  if ( IP::isInRange( $ip, $wlEntry ) ) {
717  wfDebug( " IP $ip matches $wlEntry, not autoblocking\n" );
718  return true;
719  } else {
720  wfDebug( " No match\n" );
721  }
722  }
723 
724  return false;
725  }
726 
733  public function doAutoblock( $autoblockIP ) {
734  # If autoblocks are disabled, go away.
735  if ( !$this->isAutoblocking() ) {
736  return false;
737  }
738 
739  # Check for presence on the autoblock whitelist.
740  if ( self::isWhitelistedFromAutoblocks( $autoblockIP ) ) {
741  return false;
742  }
743 
744  // Avoid PHP 7.1 warning of passing $this by reference
745  $block = $this;
746  # Allow hooks to cancel the autoblock.
747  if ( !Hooks::run( 'AbortAutoblock', [ $autoblockIP, &$block ] ) ) {
748  wfDebug( "Autoblock aborted by hook.\n" );
749  return false;
750  }
751 
752  # It's okay to autoblock. Go ahead and insert/update the block...
753 
754  # Do not add a *new* block if the IP is already blocked.
755  $ipblock = Block::newFromTarget( $autoblockIP );
756  if ( $ipblock ) {
757  # Check if the block is an autoblock and would exceed the user block
758  # if renewed. If so, do nothing, otherwise prolong the block time...
759  if ( $ipblock->mAuto && // @todo Why not compare $ipblock->mExpiry?
760  $this->mExpiry > Block::getAutoblockExpiry( $ipblock->mTimestamp )
761  ) {
762  # Reset block timestamp to now and its expiry to
763  # $wgAutoblockExpiry in the future
764  $ipblock->updateTimestamp();
765  }
766  return false;
767  }
768 
769  # Make a new block object with the desired properties.
770  $autoblock = new Block;
771  wfDebug( "Autoblocking {$this->getTarget()}@" . $autoblockIP . "\n" );
772  $autoblock->setTarget( $autoblockIP );
773  $autoblock->setBlocker( $this->getBlocker() );
774  $autoblock->mReason = wfMessage( 'autoblocker', $this->getTarget(), $this->mReason )
775  ->inContentLanguage()->plain();
777  $autoblock->mTimestamp = $timestamp;
778  $autoblock->mAuto = 1;
779  $autoblock->prevents( 'createaccount', $this->prevents( 'createaccount' ) );
780  # Continue suppressing the name if needed
781  $autoblock->mHideName = $this->mHideName;
782  $autoblock->prevents( 'editownusertalk', $this->prevents( 'editownusertalk' ) );
783  $autoblock->mParentBlockId = $this->mId;
784 
785  if ( $this->mExpiry == 'infinity' ) {
786  # Original block was indefinite, start an autoblock now
787  $autoblock->mExpiry = Block::getAutoblockExpiry( $timestamp );
788  } else {
789  # If the user is already blocked with an expiry date, we don't
790  # want to pile on top of that.
791  $autoblock->mExpiry = min( $this->mExpiry, Block::getAutoblockExpiry( $timestamp ) );
792  }
793 
794  # Insert the block...
795  $status = $autoblock->insert();
796  return $status
797  ? $status['id']
798  : false;
799  }
800 
805  public function deleteIfExpired() {
806 
807  if ( $this->isExpired() ) {
808  wfDebug( "Block::deleteIfExpired() -- deleting\n" );
809  $this->delete();
810  $retVal = true;
811  } else {
812  wfDebug( "Block::deleteIfExpired() -- not expired\n" );
813  $retVal = false;
814  }
815 
816  return $retVal;
817  }
818 
823  public function isExpired() {
825  wfDebug( "Block::isExpired() checking current " . $timestamp . " vs $this->mExpiry\n" );
826 
827  if ( !$this->mExpiry ) {
828  return false;
829  } else {
830  return $timestamp > $this->mExpiry;
831  }
832  }
833 
838  public function isValid() {
839  return $this->getTarget() != null;
840  }
841 
845  public function updateTimestamp() {
846  if ( $this->mAuto ) {
847  $this->mTimestamp = wfTimestamp();
848  $this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp );
849 
850  $dbw = wfGetDB( DB_MASTER );
851  $dbw->update( 'ipblocks',
852  [ /* SET */
853  'ipb_timestamp' => $dbw->timestamp( $this->mTimestamp ),
854  'ipb_expiry' => $dbw->timestamp( $this->mExpiry ),
855  ],
856  [ /* WHERE */
857  'ipb_id' => $this->getId(),
858  ],
859  __METHOD__
860  );
861  }
862  }
863 
869  public function getRangeStart() {
870  switch ( $this->type ) {
871  case self::TYPE_USER:
872  return '';
873  case self::TYPE_IP:
874  return IP::toHex( $this->target );
875  case self::TYPE_RANGE:
876  list( $start, /*...*/ ) = IP::parseRange( $this->target );
877  return $start;
878  default:
879  throw new MWException( "Block with invalid type" );
880  }
881  }
882 
888  public function getRangeEnd() {
889  switch ( $this->type ) {
890  case self::TYPE_USER:
891  return '';
892  case self::TYPE_IP:
893  return IP::toHex( $this->target );
894  case self::TYPE_RANGE:
895  list( /*...*/, $end ) = IP::parseRange( $this->target );
896  return $end;
897  default:
898  throw new MWException( "Block with invalid type" );
899  }
900  }
901 
907  public function getBy() {
908  $blocker = $this->getBlocker();
909  return ( $blocker instanceof User )
910  ? $blocker->getId()
911  : 0;
912  }
913 
919  public function getByName() {
920  $blocker = $this->getBlocker();
921  return ( $blocker instanceof User )
922  ? $blocker->getName()
923  : (string)$blocker; // username
924  }
925 
930  public function getId() {
931  return $this->mId;
932  }
933 
940  public function fromMaster( $x = null ) {
941  return wfSetVar( $this->mFromMaster, $x );
942  }
943 
949  public function isHardblock( $x = null ) {
950  wfSetVar( $this->isHardblock, $x );
951 
952  # You can't *not* hardblock a user
953  return $this->getType() == self::TYPE_USER
954  ? true
956  }
957 
962  public function isAutoblocking( $x = null ) {
963  wfSetVar( $this->isAutoblocking, $x );
964 
965  # You can't put an autoblock on an IP or range as we don't have any history to
966  # look over to get more IPs from
967  return $this->getType() == self::TYPE_USER
968  ? $this->isAutoblocking
969  : false;
970  }
971 
979  public function prevents( $action, $x = null ) {
980  global $wgBlockDisablesLogin;
981  $res = null;
982  switch ( $action ) {
983  case 'edit':
984  # For now... <evil laugh>
985  $res = true;
986  break;
987  case 'createaccount':
988  $res = wfSetVar( $this->mCreateAccount, $x );
989  break;
990  case 'sendemail':
991  $res = wfSetVar( $this->mBlockEmail, $x );
992  break;
993  case 'editownusertalk':
994  $res = wfSetVar( $this->mDisableUsertalk, $x );
995  break;
996  case 'read':
997  $res = false;
998  break;
999  }
1000  if ( !$res && $wgBlockDisablesLogin ) {
1001  // If a block would disable login, then it should
1002  // prevent any action that all users cannot do
1003  $anon = new User;
1004  $res = $anon->isAllowed( $action ) ? $res : true;
1005  }
1006 
1007  return $res;
1008  }
1009 
1014  public function getRedactedName() {
1015  if ( $this->mAuto ) {
1016  return Html::rawElement(
1017  'span',
1018  [ 'class' => 'mw-autoblockid' ],
1019  wfMessage( 'autoblockid', $this->mId )
1020  );
1021  } else {
1022  return htmlspecialchars( $this->getTarget() );
1023  }
1024  }
1025 
1032  public static function getAutoblockExpiry( $timestamp ) {
1033  global $wgAutoblockExpiry;
1034 
1035  return wfTimestamp( TS_MW, wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
1036  }
1037 
1041  public static function purgeExpired() {
1042  if ( wfReadOnly() ) {
1043  return;
1044  }
1045 
1047  wfGetDB( DB_MASTER ),
1048  __METHOD__,
1049  function ( IDatabase $dbw, $fname ) {
1050  $dbw->delete(
1051  'ipblocks',
1052  [ 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ],
1053  $fname
1054  );
1055  }
1056  ) );
1057  }
1058 
1079  public static function newFromTarget( $specificTarget, $vagueTarget = null, $fromMaster = false ) {
1080 
1081  list( $target, $type ) = self::parseTarget( $specificTarget );
1082  if ( $type == Block::TYPE_ID || $type == Block::TYPE_AUTO ) {
1083  return Block::newFromID( $target );
1084 
1085  } elseif ( $target === null && $vagueTarget == '' ) {
1086  # We're not going to find anything useful here
1087  # Be aware that the == '' check is explicit, since empty values will be
1088  # passed by some callers (bug 29116)
1089  return null;
1090 
1091  } elseif ( in_array(
1092  $type,
1094  ) {
1095  $block = new Block();
1096  $block->fromMaster( $fromMaster );
1097 
1098  if ( $type !== null ) {
1099  $block->setTarget( $target );
1100  }
1101 
1102  if ( $block->newLoad( $vagueTarget ) ) {
1103  return $block;
1104  }
1105  }
1106  return null;
1107  }
1108 
1119  public static function getBlocksForIPList( array $ipChain, $isAnon, $fromMaster = false ) {
1120  if ( !count( $ipChain ) ) {
1121  return [];
1122  }
1123 
1124  $conds = [];
1125  foreach ( array_unique( $ipChain ) as $ipaddr ) {
1126  # Discard invalid IP addresses. Since XFF can be spoofed and we do not
1127  # necessarily trust the header given to us, make sure that we are only
1128  # checking for blocks on well-formatted IP addresses (IPv4 and IPv6).
1129  # Do not treat private IP spaces as special as it may be desirable for wikis
1130  # to block those IP ranges in order to stop misbehaving proxies that spoof XFF.
1131  if ( !IP::isValid( $ipaddr ) ) {
1132  continue;
1133  }
1134  # Don't check trusted IPs (includes local squids which will be in every request)
1135  if ( IP::isTrustedProxy( $ipaddr ) ) {
1136  continue;
1137  }
1138  # Check both the original IP (to check against single blocks), as well as build
1139  # the clause to check for rangeblocks for the given IP.
1140  $conds['ipb_address'][] = $ipaddr;
1141  $conds[] = self::getRangeCond( IP::toHex( $ipaddr ) );
1142  }
1143 
1144  if ( !count( $conds ) ) {
1145  return [];
1146  }
1147 
1148  if ( $fromMaster ) {
1149  $db = wfGetDB( DB_MASTER );
1150  } else {
1151  $db = wfGetDB( DB_SLAVE );
1152  }
1153  $conds = $db->makeList( $conds, LIST_OR );
1154  if ( !$isAnon ) {
1155  $conds = [ $conds, 'ipb_anon_only' => 0 ];
1156  }
1157  $selectFields = array_merge(
1158  [ 'ipb_range_start', 'ipb_range_end' ],
1160  );
1161  $rows = $db->select( 'ipblocks',
1162  $selectFields,
1163  $conds,
1164  __METHOD__
1165  );
1166 
1167  $blocks = [];
1168  foreach ( $rows as $row ) {
1169  $block = self::newFromRow( $row );
1170  if ( !$block->isExpired() ) {
1171  $blocks[] = $block;
1172  }
1173  }
1174 
1175  return $blocks;
1176  }
1177 
1199  public static function chooseBlock( array $blocks, array $ipChain ) {
1200  if ( !count( $blocks ) ) {
1201  return null;
1202  } elseif ( count( $blocks ) == 1 ) {
1203  return $blocks[0];
1204  }
1205 
1206  // Sort hard blocks before soft ones and secondarily sort blocks
1207  // that disable account creation before those that don't.
1208  usort( $blocks, function ( Block $a, Block $b ) {
1209  $aWeight = (int)$a->isHardblock() . (int)$a->prevents( 'createaccount' );
1210  $bWeight = (int)$b->isHardblock() . (int)$b->prevents( 'createaccount' );
1211  return strcmp( $bWeight, $aWeight ); // highest weight first
1212  } );
1213 
1214  $blocksListExact = [
1215  'hard' => false,
1216  'disable_create' => false,
1217  'other' => false,
1218  'auto' => false
1219  ];
1220  $blocksListRange = [
1221  'hard' => false,
1222  'disable_create' => false,
1223  'other' => false,
1224  'auto' => false
1225  ];
1226  $ipChain = array_reverse( $ipChain );
1227 
1229  foreach ( $blocks as $block ) {
1230  // Stop searching if we have already have a "better" block. This
1231  // is why the order of the blocks matters
1232  if ( !$block->isHardblock() && $blocksListExact['hard'] ) {
1233  break;
1234  } elseif ( !$block->prevents( 'createaccount' ) && $blocksListExact['disable_create'] ) {
1235  break;
1236  }
1237 
1238  foreach ( $ipChain as $checkip ) {
1239  $checkipHex = IP::toHex( $checkip );
1240  if ( (string)$block->getTarget() === $checkip ) {
1241  if ( $block->isHardblock() ) {
1242  $blocksListExact['hard'] = $blocksListExact['hard'] ?: $block;
1243  } elseif ( $block->prevents( 'createaccount' ) ) {
1244  $blocksListExact['disable_create'] = $blocksListExact['disable_create'] ?: $block;
1245  } elseif ( $block->mAuto ) {
1246  $blocksListExact['auto'] = $blocksListExact['auto'] ?: $block;
1247  } else {
1248  $blocksListExact['other'] = $blocksListExact['other'] ?: $block;
1249  }
1250  // We found closest exact match in the ip list, so go to the next Block
1251  break;
1252  } elseif ( array_filter( $blocksListExact ) == []
1253  && $block->getRangeStart() <= $checkipHex
1254  && $block->getRangeEnd() >= $checkipHex
1255  ) {
1256  if ( $block->isHardblock() ) {
1257  $blocksListRange['hard'] = $blocksListRange['hard'] ?: $block;
1258  } elseif ( $block->prevents( 'createaccount' ) ) {
1259  $blocksListRange['disable_create'] = $blocksListRange['disable_create'] ?: $block;
1260  } elseif ( $block->mAuto ) {
1261  $blocksListRange['auto'] = $blocksListRange['auto'] ?: $block;
1262  } else {
1263  $blocksListRange['other'] = $blocksListRange['other'] ?: $block;
1264  }
1265  break;
1266  }
1267  }
1268  }
1269 
1270  if ( array_filter( $blocksListExact ) == [] ) {
1271  $blocksList = &$blocksListRange;
1272  } else {
1273  $blocksList = &$blocksListExact;
1274  }
1275 
1276  $chosenBlock = null;
1277  if ( $blocksList['hard'] ) {
1278  $chosenBlock = $blocksList['hard'];
1279  } elseif ( $blocksList['disable_create'] ) {
1280  $chosenBlock = $blocksList['disable_create'];
1281  } elseif ( $blocksList['other'] ) {
1282  $chosenBlock = $blocksList['other'];
1283  } elseif ( $blocksList['auto'] ) {
1284  $chosenBlock = $blocksList['auto'];
1285  } else {
1286  throw new MWException( "Proxy block found, but couldn't be classified." );
1287  }
1288 
1289  return $chosenBlock;
1290  }
1291 
1301  public static function parseTarget( $target ) {
1302  # We may have been through this before
1303  if ( $target instanceof User ) {
1304  if ( IP::isValid( $target->getName() ) ) {
1305  return [ $target, self::TYPE_IP ];
1306  } else {
1307  return [ $target, self::TYPE_USER ];
1308  }
1309  } elseif ( $target === null ) {
1310  return [ null, null ];
1311  }
1312 
1313  $target = trim( $target );
1314 
1315  if ( IP::isValid( $target ) ) {
1316  # We can still create a User if it's an IP address, but we need to turn
1317  # off validation checking (which would exclude IP addresses)
1318  return [
1321  ];
1322 
1323  } elseif ( IP::isValidBlock( $target ) ) {
1324  # Can't create a User from an IP range
1326  }
1327 
1328  # Consider the possibility that this is not a username at all
1329  # but actually an old subpage (bug #29797)
1330  if ( strpos( $target, '/' ) !== false ) {
1331  # An old subpage, drill down to the user behind it
1332  $target = explode( '/', $target )[0];
1333  }
1334 
1335  $userObj = User::newFromName( $target );
1336  if ( $userObj instanceof User ) {
1337  # Note that since numbers are valid usernames, a $target of "12345" will be
1338  # considered a User. If you want to pass a block ID, prepend a hash "#12345",
1339  # since hash characters are not valid in usernames or titles generally.
1340  return [ $userObj, Block::TYPE_USER ];
1341 
1342  } elseif ( preg_match( '/^#\d+$/', $target ) ) {
1343  # Autoblock reference in the form "#12345"
1344  return [ substr( $target, 1 ), Block::TYPE_AUTO ];
1345 
1346  } else {
1347  # WTF?
1348  return [ null, null ];
1349  }
1350  }
1351 
1356  public function getType() {
1357  return $this->mAuto
1358  ? self::TYPE_AUTO
1359  : $this->type;
1360  }
1361 
1369  public function getTargetAndType() {
1370  return [ $this->getTarget(), $this->getType() ];
1371  }
1372 
1379  public function getTarget() {
1380  return $this->target;
1381  }
1382 
1388  public function getExpiry() {
1389  return $this->mExpiry;
1390  }
1391 
1396  public function setTarget( $target ) {
1397  list( $this->target, $this->type ) = self::parseTarget( $target );
1398  }
1399 
1404  public function getBlocker() {
1405  return $this->blocker;
1406  }
1407 
1412  public function setBlocker( $user ) {
1413  $this->blocker = $user;
1414  }
1415 
1424  $blocker = $this->getBlocker();
1425  if ( $blocker instanceof User ) { // local user
1426  $blockerUserpage = $blocker->getUserPage();
1427  $link = "[[{$blockerUserpage->getPrefixedText()}|{$blockerUserpage->getText()}]]";
1428  } else { // foreign user
1429  $link = $blocker;
1430  }
1431 
1432  $reason = $this->mReason;
1433  if ( $reason == '' ) {
1434  $reason = $context->msg( 'blockednoreason' )->text();
1435  }
1436 
1437  /* $ip returns who *is* being blocked, $intended contains who was meant to be blocked.
1438  * This could be a username, an IP range, or a single IP. */
1439  $intended = $this->getTarget();
1440 
1441  $lang = $context->getLanguage();
1442  return [
1443  $this->mAuto ? 'autoblockedtext' : 'blockedtext',
1444  $link,
1445  $reason,
1446  $context->getRequest()->getIP(),
1447  $this->getByName(),
1448  $this->getId(),
1449  $lang->formatExpiry( $this->mExpiry ),
1450  (string)$intended,
1451  $lang->userTimeAndDate( $this->mTimestamp, $context->getUser() ),
1452  ];
1453  }
1454 }
getBy()
Get the user id of the blocking sysop.
Definition: Block.php:907
static newFromName($name, $validate= 'valid')
Static factory method for creation from username.
Definition: User.php:568
static getRangeCond($start, $end=null)
Get a set of SQL conditions which will select rangeblocks encompassing a given range.
Definition: Block.php:345
bool $isHardblock
Definition: Block.php:69
static getMainWANInstance()
Get the main WAN cache object.
setBlocker($user)
Set the user who implemented (or will implement) this block.
Definition: Block.php:1412
Interface for objects which can provide a MediaWiki context on request.
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
wfGetDB($db, $groups=[], $wiki=false)
Get a Database object.
the array() calling protocol came about after MediaWiki 1.4rc1.
string $mTimestamp
Definition: Block.php:27
static defaultRetroactiveAutoblock(Block $block, array &$blockIds)
Retroactively autoblocks the last IP used by the user (if it is a user) blocked by this Block...
Definition: Block.php:648
static sanitizeIP($ip)
Convert an IP into a verbose, uppercase, normalized form.
Definition: IP.php:140
$context
Definition: load.php:44
static chooseBlock(array $blocks, array $ipChain)
From a list of multiple blocks, find the most exact and strongest Block.
Definition: Block.php:1199
const TYPE_RANGE
Definition: Block.php:77
static isInRange($addr, $range)
Determine if a given IPv4/IPv6 address is in a given CIDR network.
Definition: IP.php:638
static isWhitelistedFromAutoblocks($ip)
Checks whether a given IP is on the autoblock whitelist.
Definition: Block.php:689
static sanitizeRange($range)
Gets rid of unneeded numbers in quad-dotted/octet IP strings For example, 127.111.113.151/24 -> 127.111.113.0/24.
Definition: IP.php:713
bool $mFromMaster
Definition: Block.php:45
isValid()
Is the block address valid (i.e.
Definition: Block.php:838
msg()
Get a Message object with context set.
getType()
Get the type of target for this particular block.
Definition: Block.php:1356
static rawElement($element, $attribs=[], $contents= '')
Returns an HTML element in a string.
Definition: Html.php:210
if(!isset($args[0])) $lang
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:189
int $mParentBlockId
Definition: Block.php:39
bool $mDisableUsertalk
Definition: Block.php:51
equals(Block $block)
Check if two blocks are effectively equal.
Definition: Block.php:218
This code would result in ircNotify being run twice when an article is and once for brion Hooks can return three possible true was required This is the default since MediaWiki *some string
Definition: hooks.txt:177
static newFromId($id)
Static factory method for creation from a given user ID.
Definition: User.php:591
const TYPE_IP
Definition: Block.php:76
__construct($options=[])
Create a new block with specified parameters on a user, IP or IP range.
Definition: Block.php:103
getId()
Get the block ID.
Definition: Block.php:930
when a variable name is used in a it is silently declared as a new local masking the global
Definition: design.txt:93
timestamp($ts=0)
Convert a timestamp in one of the formats accepted by wfTimestamp() to the format used for inserting ...
getName()
Get the user name, or the IP of an anonymous user.
Definition: User.php:2095
update()
Update a block in the DB with new parameters.
Definition: Block.php:523
wfDebug($text, $dest= 'all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
the value to return A Title object or null for latest to be modified or replaced by the hook handler or if authentication is not possible after cache objects are set for highlighting & $link
Definition: hooks.txt:2585
getRangeEnd()
Get the IP address at the end of the range in Hex form.
Definition: Block.php:888
getAutoblockUpdateArray()
Definition: Block.php:608
wfTimestamp($outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
deleteIfExpired()
Check if a block has expired.
Definition: Block.php:805
getUser()
Get the User object.
insert($dbw=null)
Insert a block into the block table.
Definition: Block.php:459
delete($table, $conds, $fname=__METHOD__)
DELETE query wrapper.
getExpiry()
Definition: Block.php:1388
static isTrustedProxy($ip)
Checks if an IP is a trusted proxy provider.
Definition: IP.php:733
wfReadOnly()
Check whether the wiki is in read-only mode.
const LIST_AND
Definition: Defines.php:194
int $type
Block::TYPE_ constant.
Definition: Block.php:63
getTargetAndType()
Get the target and target type for this particular Block.
Definition: Block.php:1369
if($limit) $timestamp
static newFromTarget($specificTarget, $vagueTarget=null, $fromMaster=false)
Given a target and the target's type, get an existing Block object if possible.
Definition: Block.php:1079
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
Definition: hooks.txt:1008
getRedactedName()
Get the block name, but with autoblocked IPs hidden as per standard privacy policy.
Definition: Block.php:1014
bool $isAutoblocking
Definition: Block.php:72
static isValid($ip)
Validate an IP address.
Definition: IP.php:113
$res
Definition: database.txt:21
bool $mBlockEmail
Definition: Block.php:48
setTarget($target)
Set the target for this block, and update $this->type accordingly.
Definition: Block.php:1396
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock()-offset Set to overwrite offset parameter in $wgRequest set to ''to unsetoffset-wrap String Wrap the message in html(usually something like"&lt
Deferrable Update for closure/callback updates via IDatabase::doAtomicSection()
$cache
Definition: mcc.php:33
int $mId
Definition: Block.php:42
doAutoblock($autoblockIP)
Autoblocks the given IP, referring to this Block.
Definition: Block.php:733
wfDeprecated($function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
const DB_SLAVE
Definition: Defines.php:47
static parseTarget($target)
From an existing Block, get the target and the type of target.
Definition: Block.php:1301
static purgeExpired()
Purge expired blocks from the ipblocks table.
Definition: Block.php:1041
newLoad($vagueTarget=null)
Load a block from the database which affects the already-set $this->target: 1) A block directly on th...
Definition: Block.php:244
static addUpdate(DeferrableUpdate $update, $type=self::POSTSEND)
Add an update to the deferred list.
const TYPE_ID
Definition: Block.php:79
static run($event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:131
static toHex($ip)
Return a zero-padded upper case hexadecimal representation of an IP address.
Definition: IP.php:405
const TYPE_AUTO
Definition: Block.php:78
getLanguage()
Get the Language object.
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
static newFromRow($row)
Create a new Block object from a database row.
Definition: Block.php:423
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account $user
Definition: hooks.txt:246
const LIST_OR
Definition: Defines.php:197
const TS_MW
MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS)
User string $target
Definition: Block.php:57
doRetroactiveAutoblock()
Retroactively autoblocks the last IP used by the user (if it is a user) blocked by this Block...
Definition: Block.php:625
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
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...
static getBlocksForIPList(array $ipChain, $isAnon, $fromMaster=false)
Get all blocks that match any IP from an array of IP addresses.
Definition: Block.php:1119
bool $mAuto
Definition: Block.php:30
int $forcedTargetID
Hack for foreign blocking (CentralAuth)
Definition: Block.php:60
This document describes the state of Postgres support in and is fairly well maintained The main code is very well while extensions are very hit and miss it is probably the most supported database after MySQL Much of the work in making MediaWiki database agnostic came about through the work of creating Postgres as and are nearing end of but without copying over all the usage comments General notes on the but these can almost always be programmed around *Although Postgres has a true BOOLEAN type
Definition: postgres.txt:22
updateTimestamp()
Update the timestamp on autoblocks.
Definition: Block.php:845
$lines
Definition: router.php:66
if(!defined( 'MEDIAWIKI')) $fname
This file is not a valid entry point, perform no further processing unless MEDIAWIKI is defined...
Definition: Setup.php:35
prevents($action, $x=null)
Get/set whether the Block prevents a given action.
Definition: Block.php:979
static getAutoblockExpiry($timestamp)
Get a timestamp of the expiry for autoblocks.
Definition: Block.php:1032
getBlocker()
Get the user who implemented this block.
Definition: Block.php:1404
static parseRange($range)
Given a string range in a number of formats, return the start and end of the range in hexadecimal...
Definition: IP.php:501
getId()
Get the user's ID.
Definition: User.php:2070
getPermissionsError(IContextSource $context)
Get the key and parameters for the corresponding error message.
Definition: Block.php:1423
isAutoblocking($x=null)
Definition: Block.php:962
static selectFields()
Return the list of ipblocks fields that should be selected to create a new block. ...
Definition: Block.php:190
User $blocker
Definition: Block.php:66
$line
Definition: cdb.php:59
getTarget()
Get the target for this particular Block.
Definition: Block.php:1379
getUserPage()
Get this user's personal page title.
Definition: User.php:4097
static newFromID($id)
Load a blocked user from their block id.
Definition: Block.php:170
const TYPE_USER
Definition: Block.php:75
getDatabaseArray($db=null)
Get an array suitable for passing to $dbw->insert() or $dbw->update()
Definition: Block.php:570
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set $status
Definition: hooks.txt:1008
fromMaster($x=null)
Get/set a flag determining whether the master is used for reads.
Definition: Block.php:940
wfMemcKey()
Make a cache key for the local wiki.
const DB_MASTER
Definition: Defines.php:48
addQuotes($s)
Adds quotes and backslashes.
const TS_UNIX
Unix time - the number of seconds since 1970-01-01 00:00:00 UTC.
string $mExpiry
Definition: Block.php:33
bool $mHideName
Definition: Block.php:36
isHardblock($x=null)
Get/set whether the Block is a hardblock (affects logged-in users on a given IP/range) ...
Definition: Block.php:949
initFromRow($row)
Given a database row from the ipblocks table, initialize member variables.
Definition: Block.php:392
static isValidBlock($ipblock)
Validate an IP Block (valid address WITH a valid prefix).
Definition: IP.php:126
Definition: Block.php:22
getRangeStart()
Get the IP address at the start of the range in Hex form.
Definition: Block.php:869
getRequest()
Get the WebRequest object.
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: Block.php:378
getByName()
Get the username of the blocking sysop.
Definition: Block.php:919
string $mReason
Definition: Block.php:24
Basic database interface for live and lazy-loaded DB handles.
Definition: IDatabase.php:35
bool $mCreateAccount
Definition: Block.php:54
isExpired()
Has the block expired?
Definition: Block.php:823