MediaWiki  1.27.2
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  # Allow hooks to cancel the autoblock.
745  if ( !Hooks::run( 'AbortAutoblock', [ $autoblockIP, &$this ] ) ) {
746  wfDebug( "Autoblock aborted by hook.\n" );
747  return false;
748  }
749 
750  # It's okay to autoblock. Go ahead and insert/update the block...
751 
752  # Do not add a *new* block if the IP is already blocked.
753  $ipblock = Block::newFromTarget( $autoblockIP );
754  if ( $ipblock ) {
755  # Check if the block is an autoblock and would exceed the user block
756  # if renewed. If so, do nothing, otherwise prolong the block time...
757  if ( $ipblock->mAuto && // @todo Why not compare $ipblock->mExpiry?
758  $this->mExpiry > Block::getAutoblockExpiry( $ipblock->mTimestamp )
759  ) {
760  # Reset block timestamp to now and its expiry to
761  # $wgAutoblockExpiry in the future
762  $ipblock->updateTimestamp();
763  }
764  return false;
765  }
766 
767  # Make a new block object with the desired properties.
768  $autoblock = new Block;
769  wfDebug( "Autoblocking {$this->getTarget()}@" . $autoblockIP . "\n" );
770  $autoblock->setTarget( $autoblockIP );
771  $autoblock->setBlocker( $this->getBlocker() );
772  $autoblock->mReason = wfMessage( 'autoblocker', $this->getTarget(), $this->mReason )
773  ->inContentLanguage()->plain();
775  $autoblock->mTimestamp = $timestamp;
776  $autoblock->mAuto = 1;
777  $autoblock->prevents( 'createaccount', $this->prevents( 'createaccount' ) );
778  # Continue suppressing the name if needed
779  $autoblock->mHideName = $this->mHideName;
780  $autoblock->prevents( 'editownusertalk', $this->prevents( 'editownusertalk' ) );
781  $autoblock->mParentBlockId = $this->mId;
782 
783  if ( $this->mExpiry == 'infinity' ) {
784  # Original block was indefinite, start an autoblock now
785  $autoblock->mExpiry = Block::getAutoblockExpiry( $timestamp );
786  } else {
787  # If the user is already blocked with an expiry date, we don't
788  # want to pile on top of that.
789  $autoblock->mExpiry = min( $this->mExpiry, Block::getAutoblockExpiry( $timestamp ) );
790  }
791 
792  # Insert the block...
793  $status = $autoblock->insert();
794  return $status
795  ? $status['id']
796  : false;
797  }
798 
803  public function deleteIfExpired() {
804 
805  if ( $this->isExpired() ) {
806  wfDebug( "Block::deleteIfExpired() -- deleting\n" );
807  $this->delete();
808  $retVal = true;
809  } else {
810  wfDebug( "Block::deleteIfExpired() -- not expired\n" );
811  $retVal = false;
812  }
813 
814  return $retVal;
815  }
816 
821  public function isExpired() {
823  wfDebug( "Block::isExpired() checking current " . $timestamp . " vs $this->mExpiry\n" );
824 
825  if ( !$this->mExpiry ) {
826  return false;
827  } else {
828  return $timestamp > $this->mExpiry;
829  }
830  }
831 
836  public function isValid() {
837  return $this->getTarget() != null;
838  }
839 
843  public function updateTimestamp() {
844  if ( $this->mAuto ) {
845  $this->mTimestamp = wfTimestamp();
846  $this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp );
847 
848  $dbw = wfGetDB( DB_MASTER );
849  $dbw->update( 'ipblocks',
850  [ /* SET */
851  'ipb_timestamp' => $dbw->timestamp( $this->mTimestamp ),
852  'ipb_expiry' => $dbw->timestamp( $this->mExpiry ),
853  ],
854  [ /* WHERE */
855  'ipb_id' => $this->getId(),
856  ],
857  __METHOD__
858  );
859  }
860  }
861 
867  public function getRangeStart() {
868  switch ( $this->type ) {
869  case self::TYPE_USER:
870  return '';
871  case self::TYPE_IP:
872  return IP::toHex( $this->target );
873  case self::TYPE_RANGE:
874  list( $start, /*...*/ ) = IP::parseRange( $this->target );
875  return $start;
876  default:
877  throw new MWException( "Block with invalid type" );
878  }
879  }
880 
886  public function getRangeEnd() {
887  switch ( $this->type ) {
888  case self::TYPE_USER:
889  return '';
890  case self::TYPE_IP:
891  return IP::toHex( $this->target );
892  case self::TYPE_RANGE:
893  list( /*...*/, $end ) = IP::parseRange( $this->target );
894  return $end;
895  default:
896  throw new MWException( "Block with invalid type" );
897  }
898  }
899 
905  public function getBy() {
906  $blocker = $this->getBlocker();
907  return ( $blocker instanceof User )
908  ? $blocker->getId()
909  : 0;
910  }
911 
917  public function getByName() {
918  $blocker = $this->getBlocker();
919  return ( $blocker instanceof User )
920  ? $blocker->getName()
921  : (string)$blocker; // username
922  }
923 
928  public function getId() {
929  return $this->mId;
930  }
931 
938  public function fromMaster( $x = null ) {
939  return wfSetVar( $this->mFromMaster, $x );
940  }
941 
947  public function isHardblock( $x = null ) {
948  wfSetVar( $this->isHardblock, $x );
949 
950  # You can't *not* hardblock a user
951  return $this->getType() == self::TYPE_USER
952  ? true
954  }
955 
960  public function isAutoblocking( $x = null ) {
961  wfSetVar( $this->isAutoblocking, $x );
962 
963  # You can't put an autoblock on an IP or range as we don't have any history to
964  # look over to get more IPs from
965  return $this->getType() == self::TYPE_USER
966  ? $this->isAutoblocking
967  : false;
968  }
969 
977  public function prevents( $action, $x = null ) {
978  global $wgBlockDisablesLogin;
979  $res = null;
980  switch ( $action ) {
981  case 'edit':
982  # For now... <evil laugh>
983  $res = true;
984  break;
985  case 'createaccount':
986  $res = wfSetVar( $this->mCreateAccount, $x );
987  break;
988  case 'sendemail':
989  $res = wfSetVar( $this->mBlockEmail, $x );
990  break;
991  case 'editownusertalk':
992  $res = wfSetVar( $this->mDisableUsertalk, $x );
993  break;
994  case 'read':
995  $res = false;
996  break;
997  }
998  if ( !$res && $wgBlockDisablesLogin ) {
999  // If a block would disable login, then it should
1000  // prevent any action that all users cannot do
1001  $anon = new User;
1002  $res = $anon->isAllowed( $action ) ? $res : true;
1003  }
1004 
1005  return $res;
1006  }
1007 
1012  public function getRedactedName() {
1013  if ( $this->mAuto ) {
1014  return Html::rawElement(
1015  'span',
1016  [ 'class' => 'mw-autoblockid' ],
1017  wfMessage( 'autoblockid', $this->mId )
1018  );
1019  } else {
1020  return htmlspecialchars( $this->getTarget() );
1021  }
1022  }
1023 
1030  public static function getAutoblockExpiry( $timestamp ) {
1031  global $wgAutoblockExpiry;
1032 
1033  return wfTimestamp( TS_MW, wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
1034  }
1035 
1039  public static function purgeExpired() {
1040  if ( wfReadOnly() ) {
1041  return;
1042  }
1043 
1045  wfGetDB( DB_MASTER ),
1046  __METHOD__,
1047  function ( IDatabase $dbw, $fname ) {
1048  $dbw->delete(
1049  'ipblocks',
1050  [ 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ],
1051  $fname
1052  );
1053  }
1054  ) );
1055  }
1056 
1077  public static function newFromTarget( $specificTarget, $vagueTarget = null, $fromMaster = false ) {
1078 
1079  list( $target, $type ) = self::parseTarget( $specificTarget );
1080  if ( $type == Block::TYPE_ID || $type == Block::TYPE_AUTO ) {
1081  return Block::newFromID( $target );
1082 
1083  } elseif ( $target === null && $vagueTarget == '' ) {
1084  # We're not going to find anything useful here
1085  # Be aware that the == '' check is explicit, since empty values will be
1086  # passed by some callers (bug 29116)
1087  return null;
1088 
1089  } elseif ( in_array(
1090  $type,
1092  ) {
1093  $block = new Block();
1094  $block->fromMaster( $fromMaster );
1095 
1096  if ( $type !== null ) {
1097  $block->setTarget( $target );
1098  }
1099 
1100  if ( $block->newLoad( $vagueTarget ) ) {
1101  return $block;
1102  }
1103  }
1104  return null;
1105  }
1106 
1117  public static function getBlocksForIPList( array $ipChain, $isAnon, $fromMaster = false ) {
1118  if ( !count( $ipChain ) ) {
1119  return [];
1120  }
1121 
1122  $conds = [];
1123  foreach ( array_unique( $ipChain ) as $ipaddr ) {
1124  # Discard invalid IP addresses. Since XFF can be spoofed and we do not
1125  # necessarily trust the header given to us, make sure that we are only
1126  # checking for blocks on well-formatted IP addresses (IPv4 and IPv6).
1127  # Do not treat private IP spaces as special as it may be desirable for wikis
1128  # to block those IP ranges in order to stop misbehaving proxies that spoof XFF.
1129  if ( !IP::isValid( $ipaddr ) ) {
1130  continue;
1131  }
1132  # Don't check trusted IPs (includes local squids which will be in every request)
1133  if ( IP::isTrustedProxy( $ipaddr ) ) {
1134  continue;
1135  }
1136  # Check both the original IP (to check against single blocks), as well as build
1137  # the clause to check for rangeblocks for the given IP.
1138  $conds['ipb_address'][] = $ipaddr;
1139  $conds[] = self::getRangeCond( IP::toHex( $ipaddr ) );
1140  }
1141 
1142  if ( !count( $conds ) ) {
1143  return [];
1144  }
1145 
1146  if ( $fromMaster ) {
1147  $db = wfGetDB( DB_MASTER );
1148  } else {
1149  $db = wfGetDB( DB_SLAVE );
1150  }
1151  $conds = $db->makeList( $conds, LIST_OR );
1152  if ( !$isAnon ) {
1153  $conds = [ $conds, 'ipb_anon_only' => 0 ];
1154  }
1155  $selectFields = array_merge(
1156  [ 'ipb_range_start', 'ipb_range_end' ],
1158  );
1159  $rows = $db->select( 'ipblocks',
1160  $selectFields,
1161  $conds,
1162  __METHOD__
1163  );
1164 
1165  $blocks = [];
1166  foreach ( $rows as $row ) {
1167  $block = self::newFromRow( $row );
1168  if ( !$block->isExpired() ) {
1169  $blocks[] = $block;
1170  }
1171  }
1172 
1173  return $blocks;
1174  }
1175 
1197  public static function chooseBlock( array $blocks, array $ipChain ) {
1198  if ( !count( $blocks ) ) {
1199  return null;
1200  } elseif ( count( $blocks ) == 1 ) {
1201  return $blocks[0];
1202  }
1203 
1204  // Sort hard blocks before soft ones and secondarily sort blocks
1205  // that disable account creation before those that don't.
1206  usort( $blocks, function ( Block $a, Block $b ) {
1207  $aWeight = (int)$a->isHardblock() . (int)$a->prevents( 'createaccount' );
1208  $bWeight = (int)$b->isHardblock() . (int)$b->prevents( 'createaccount' );
1209  return strcmp( $bWeight, $aWeight ); // highest weight first
1210  } );
1211 
1212  $blocksListExact = [
1213  'hard' => false,
1214  'disable_create' => false,
1215  'other' => false,
1216  'auto' => false
1217  ];
1218  $blocksListRange = [
1219  'hard' => false,
1220  'disable_create' => false,
1221  'other' => false,
1222  'auto' => false
1223  ];
1224  $ipChain = array_reverse( $ipChain );
1225 
1227  foreach ( $blocks as $block ) {
1228  // Stop searching if we have already have a "better" block. This
1229  // is why the order of the blocks matters
1230  if ( !$block->isHardblock() && $blocksListExact['hard'] ) {
1231  break;
1232  } elseif ( !$block->prevents( 'createaccount' ) && $blocksListExact['disable_create'] ) {
1233  break;
1234  }
1235 
1236  foreach ( $ipChain as $checkip ) {
1237  $checkipHex = IP::toHex( $checkip );
1238  if ( (string)$block->getTarget() === $checkip ) {
1239  if ( $block->isHardblock() ) {
1240  $blocksListExact['hard'] = $blocksListExact['hard'] ?: $block;
1241  } elseif ( $block->prevents( 'createaccount' ) ) {
1242  $blocksListExact['disable_create'] = $blocksListExact['disable_create'] ?: $block;
1243  } elseif ( $block->mAuto ) {
1244  $blocksListExact['auto'] = $blocksListExact['auto'] ?: $block;
1245  } else {
1246  $blocksListExact['other'] = $blocksListExact['other'] ?: $block;
1247  }
1248  // We found closest exact match in the ip list, so go to the next Block
1249  break;
1250  } elseif ( array_filter( $blocksListExact ) == []
1251  && $block->getRangeStart() <= $checkipHex
1252  && $block->getRangeEnd() >= $checkipHex
1253  ) {
1254  if ( $block->isHardblock() ) {
1255  $blocksListRange['hard'] = $blocksListRange['hard'] ?: $block;
1256  } elseif ( $block->prevents( 'createaccount' ) ) {
1257  $blocksListRange['disable_create'] = $blocksListRange['disable_create'] ?: $block;
1258  } elseif ( $block->mAuto ) {
1259  $blocksListRange['auto'] = $blocksListRange['auto'] ?: $block;
1260  } else {
1261  $blocksListRange['other'] = $blocksListRange['other'] ?: $block;
1262  }
1263  break;
1264  }
1265  }
1266  }
1267 
1268  if ( array_filter( $blocksListExact ) == [] ) {
1269  $blocksList = &$blocksListRange;
1270  } else {
1271  $blocksList = &$blocksListExact;
1272  }
1273 
1274  $chosenBlock = null;
1275  if ( $blocksList['hard'] ) {
1276  $chosenBlock = $blocksList['hard'];
1277  } elseif ( $blocksList['disable_create'] ) {
1278  $chosenBlock = $blocksList['disable_create'];
1279  } elseif ( $blocksList['other'] ) {
1280  $chosenBlock = $blocksList['other'];
1281  } elseif ( $blocksList['auto'] ) {
1282  $chosenBlock = $blocksList['auto'];
1283  } else {
1284  throw new MWException( "Proxy block found, but couldn't be classified." );
1285  }
1286 
1287  return $chosenBlock;
1288  }
1289 
1299  public static function parseTarget( $target ) {
1300  # We may have been through this before
1301  if ( $target instanceof User ) {
1302  if ( IP::isValid( $target->getName() ) ) {
1303  return [ $target, self::TYPE_IP ];
1304  } else {
1305  return [ $target, self::TYPE_USER ];
1306  }
1307  } elseif ( $target === null ) {
1308  return [ null, null ];
1309  }
1310 
1311  $target = trim( $target );
1312 
1313  if ( IP::isValid( $target ) ) {
1314  # We can still create a User if it's an IP address, but we need to turn
1315  # off validation checking (which would exclude IP addresses)
1316  return [
1319  ];
1320 
1321  } elseif ( IP::isValidBlock( $target ) ) {
1322  # Can't create a User from an IP range
1324  }
1325 
1326  # Consider the possibility that this is not a username at all
1327  # but actually an old subpage (bug #29797)
1328  if ( strpos( $target, '/' ) !== false ) {
1329  # An old subpage, drill down to the user behind it
1330  $target = explode( '/', $target )[0];
1331  }
1332 
1333  $userObj = User::newFromName( $target );
1334  if ( $userObj instanceof User ) {
1335  # Note that since numbers are valid usernames, a $target of "12345" will be
1336  # considered a User. If you want to pass a block ID, prepend a hash "#12345",
1337  # since hash characters are not valid in usernames or titles generally.
1338  return [ $userObj, Block::TYPE_USER ];
1339 
1340  } elseif ( preg_match( '/^#\d+$/', $target ) ) {
1341  # Autoblock reference in the form "#12345"
1342  return [ substr( $target, 1 ), Block::TYPE_AUTO ];
1343 
1344  } else {
1345  # WTF?
1346  return [ null, null ];
1347  }
1348  }
1349 
1354  public function getType() {
1355  return $this->mAuto
1356  ? self::TYPE_AUTO
1357  : $this->type;
1358  }
1359 
1367  public function getTargetAndType() {
1368  return [ $this->getTarget(), $this->getType() ];
1369  }
1370 
1377  public function getTarget() {
1378  return $this->target;
1379  }
1380 
1386  public function getExpiry() {
1387  return $this->mExpiry;
1388  }
1389 
1394  public function setTarget( $target ) {
1395  list( $this->target, $this->type ) = self::parseTarget( $target );
1396  }
1397 
1402  public function getBlocker() {
1403  return $this->blocker;
1404  }
1405 
1410  public function setBlocker( $user ) {
1411  $this->blocker = $user;
1412  }
1413 
1422  $blocker = $this->getBlocker();
1423  if ( $blocker instanceof User ) { // local user
1424  $blockerUserpage = $blocker->getUserPage();
1425  $link = "[[{$blockerUserpage->getPrefixedText()}|{$blockerUserpage->getText()}]]";
1426  } else { // foreign user
1427  $link = $blocker;
1428  }
1429 
1430  $reason = $this->mReason;
1431  if ( $reason == '' ) {
1432  $reason = $context->msg( 'blockednoreason' )->text();
1433  }
1434 
1435  /* $ip returns who *is* being blocked, $intended contains who was meant to be blocked.
1436  * This could be a username, an IP range, or a single IP. */
1437  $intended = $this->getTarget();
1438 
1439  $lang = $context->getLanguage();
1440  return [
1441  $this->mAuto ? 'autoblockedtext' : 'blockedtext',
1442  $link,
1443  $reason,
1444  $context->getRequest()->getIP(),
1445  $this->getByName(),
1446  $this->getId(),
1447  $lang->formatExpiry( $this->mExpiry ),
1448  (string)$intended,
1449  $lang->userTimeAndDate( $this->mTimestamp, $context->getUser() ),
1450  ];
1451  }
1452 }
getBy()
Get the user id of the blocking sysop.
Definition: Block.php:905
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:1410
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:1197
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:836
msg()
Get a Message object with context set.
getType()
Get the type of target for this particular block.
Definition: Block.php:1354
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:928
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:2086
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:2581
getRangeEnd()
Get the IP address at the end of the range in Hex form.
Definition: Block.php:886
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:803
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:1386
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:193
int $type
Block::TYPE_ constant.
Definition: Block.php:63
getTargetAndType()
Get the target and target type for this particular Block.
Definition: Block.php:1367
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:1077
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:1004
getRedactedName()
Get the block name, but with autoblocked IPs hidden as per standard privacy policy.
Definition: Block.php:1012
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:1394
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:46
static parseTarget($target)
From an existing Block, get the target and the type of target.
Definition: Block.php:1299
static purgeExpired()
Purge expired blocks from the ipblocks table.
Definition: Block.php:1039
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:242
const LIST_OR
Definition: Defines.php:196
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:1117
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:843
$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:977
static getAutoblockExpiry($timestamp)
Get a timestamp of the expiry for autoblocks.
Definition: Block.php:1030
getBlocker()
Get the user who implemented this block.
Definition: Block.php:1402
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:2061
getPermissionsError(IContextSource $context)
Get the key and parameters for the corresponding error message.
Definition: Block.php:1421
isAutoblocking($x=null)
Definition: Block.php:960
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:1377
getUserPage()
Get this user's personal page title.
Definition: User.php:4080
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:1004
fromMaster($x=null)
Get/set a flag determining whether the master is used for reads.
Definition: Block.php:938
wfMemcKey()
Make a cache key for the local wiki.
const DB_MASTER
Definition: Defines.php:47
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:947
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:867
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:917
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:821