MediaWiki  1.27.0
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  wfDebug( "Block::insert; timestamp {$this->mTimestamp}\n" );
461 
462  if ( $dbw === null ) {
463  $dbw = wfGetDB( DB_MASTER );
464  }
465 
466  # Periodic purge via commit hooks
467  if ( mt_rand( 0, 9 ) == 0 ) {
469  }
470 
471  $row = $this->getDatabaseArray();
472  $row['ipb_id'] = $dbw->nextSequenceValue( "ipblocks_ipb_id_seq" );
473 
474  $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
475  $affected = $dbw->affectedRows();
476  $this->mId = $dbw->insertId();
477 
478  # Don't collide with expired blocks.
479  # Do this after trying to insert to avoid locking.
480  if ( !$affected ) {
481  # T96428: The ipb_address index uses a prefix on a field, so
482  # use a standard SELECT + DELETE to avoid annoying gap locks.
483  $ids = $dbw->selectFieldValues( 'ipblocks',
484  'ipb_id',
485  [
486  'ipb_address' => $row['ipb_address'],
487  'ipb_user' => $row['ipb_user'],
488  'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() )
489  ],
490  __METHOD__
491  );
492  if ( $ids ) {
493  $dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], __METHOD__ );
494  $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
495  $affected = $dbw->affectedRows();
496  $this->mId = $dbw->insertId();
497  }
498  }
499 
500  if ( $affected ) {
501  $auto_ipd_ids = $this->doRetroactiveAutoblock();
502  return [ 'id' => $this->mId, 'autoIds' => $auto_ipd_ids ];
503  }
504 
505  return false;
506  }
507 
515  public function update() {
516  wfDebug( "Block::update; timestamp {$this->mTimestamp}\n" );
517  $dbw = wfGetDB( DB_MASTER );
518 
519  $dbw->startAtomic( __METHOD__ );
520 
521  $dbw->update(
522  'ipblocks',
523  $this->getDatabaseArray( $dbw ),
524  [ 'ipb_id' => $this->getId() ],
525  __METHOD__
526  );
527 
528  $affected = $dbw->affectedRows();
529 
530  if ( $this->isAutoblocking() ) {
531  // update corresponding autoblock(s) (bug 48813)
532  $dbw->update(
533  'ipblocks',
534  $this->getAutoblockUpdateArray(),
535  [ 'ipb_parent_block_id' => $this->getId() ],
536  __METHOD__
537  );
538  } else {
539  // autoblock no longer required, delete corresponding autoblock(s)
540  $dbw->delete(
541  'ipblocks',
542  [ 'ipb_parent_block_id' => $this->getId() ],
543  __METHOD__
544  );
545  }
546 
547  $dbw->endAtomic( __METHOD__ );
548 
549  if ( $affected ) {
550  $auto_ipd_ids = $this->doRetroactiveAutoblock();
551  return [ 'id' => $this->mId, 'autoIds' => $auto_ipd_ids ];
552  }
553 
554  return false;
555  }
556 
562  protected function getDatabaseArray( $db = null ) {
563  if ( !$db ) {
564  $db = wfGetDB( DB_SLAVE );
565  }
566  $expiry = $db->encodeExpiry( $this->mExpiry );
567 
568  if ( $this->forcedTargetID ) {
569  $uid = $this->forcedTargetID;
570  } else {
571  $uid = $this->target instanceof User ? $this->target->getId() : 0;
572  }
573 
574  $a = [
575  'ipb_address' => (string)$this->target,
576  'ipb_user' => $uid,
577  'ipb_by' => $this->getBy(),
578  'ipb_by_text' => $this->getByName(),
579  'ipb_reason' => $this->mReason,
580  'ipb_timestamp' => $db->timestamp( $this->mTimestamp ),
581  'ipb_auto' => $this->mAuto,
582  'ipb_anon_only' => !$this->isHardblock(),
583  'ipb_create_account' => $this->prevents( 'createaccount' ),
584  'ipb_enable_autoblock' => $this->isAutoblocking(),
585  'ipb_expiry' => $expiry,
586  'ipb_range_start' => $this->getRangeStart(),
587  'ipb_range_end' => $this->getRangeEnd(),
588  'ipb_deleted' => intval( $this->mHideName ), // typecast required for SQLite
589  'ipb_block_email' => $this->prevents( 'sendemail' ),
590  'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' ),
591  'ipb_parent_block_id' => $this->mParentBlockId
592  ];
593 
594  return $a;
595  }
596 
600  protected function getAutoblockUpdateArray() {
601  return [
602  'ipb_by' => $this->getBy(),
603  'ipb_by_text' => $this->getByName(),
604  'ipb_reason' => $this->mReason,
605  'ipb_create_account' => $this->prevents( 'createaccount' ),
606  'ipb_deleted' => (int)$this->mHideName, // typecast required for SQLite
607  'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' ),
608  ];
609  }
610 
617  protected function doRetroactiveAutoblock() {
618  $blockIds = [];
619  # If autoblock is enabled, autoblock the LAST IP(s) used
620  if ( $this->isAutoblocking() && $this->getType() == self::TYPE_USER ) {
621  wfDebug( "Doing retroactive autoblocks for " . $this->getTarget() . "\n" );
622 
623  $continue = Hooks::run(
624  'PerformRetroactiveAutoblock', [ $this, &$blockIds ] );
625 
626  if ( $continue ) {
627  self::defaultRetroactiveAutoblock( $this, $blockIds );
628  }
629  }
630  return $blockIds;
631  }
632 
640  protected static function defaultRetroactiveAutoblock( Block $block, array &$blockIds ) {
641  global $wgPutIPinRC;
642 
643  // No IPs are in recentchanges table, so nothing to select
644  if ( !$wgPutIPinRC ) {
645  return;
646  }
647 
648  $dbr = wfGetDB( DB_SLAVE );
649 
650  $options = [ 'ORDER BY' => 'rc_timestamp DESC' ];
651  $conds = [ 'rc_user_text' => (string)$block->getTarget() ];
652 
653  // Just the last IP used.
654  $options['LIMIT'] = 1;
655 
656  $res = $dbr->select( 'recentchanges', [ 'rc_ip' ], $conds,
657  __METHOD__, $options );
658 
659  if ( !$res->numRows() ) {
660  # No results, don't autoblock anything
661  wfDebug( "No IP found to retroactively autoblock\n" );
662  } else {
663  foreach ( $res as $row ) {
664  if ( $row->rc_ip ) {
665  $id = $block->doAutoblock( $row->rc_ip );
666  if ( $id ) {
667  $blockIds[] = $id;
668  }
669  }
670  }
671  }
672  }
673 
681  public static function isWhitelistedFromAutoblocks( $ip ) {
682  // Try to get the autoblock_whitelist from the cache, as it's faster
683  // than getting the msg raw and explode()'ing it.
685  $lines = $cache->getWithSetCallback(
686  wfMemcKey( 'ipb', 'autoblock', 'whitelist' ),
687  $cache::TTL_DAY,
688  function () {
689  return explode( "\n",
690  wfMessage( 'autoblock_whitelist' )->inContentLanguage()->plain() );
691  }
692  );
693 
694  wfDebug( "Checking the autoblock whitelist..\n" );
695 
696  foreach ( $lines as $line ) {
697  # List items only
698  if ( substr( $line, 0, 1 ) !== '*' ) {
699  continue;
700  }
701 
702  $wlEntry = substr( $line, 1 );
703  $wlEntry = trim( $wlEntry );
704 
705  wfDebug( "Checking $ip against $wlEntry..." );
706 
707  # Is the IP in this range?
708  if ( IP::isInRange( $ip, $wlEntry ) ) {
709  wfDebug( " IP $ip matches $wlEntry, not autoblocking\n" );
710  return true;
711  } else {
712  wfDebug( " No match\n" );
713  }
714  }
715 
716  return false;
717  }
718 
725  public function doAutoblock( $autoblockIP ) {
726  # If autoblocks are disabled, go away.
727  if ( !$this->isAutoblocking() ) {
728  return false;
729  }
730 
731  # Check for presence on the autoblock whitelist.
732  if ( self::isWhitelistedFromAutoblocks( $autoblockIP ) ) {
733  return false;
734  }
735 
736  # Allow hooks to cancel the autoblock.
737  if ( !Hooks::run( 'AbortAutoblock', [ $autoblockIP, &$this ] ) ) {
738  wfDebug( "Autoblock aborted by hook.\n" );
739  return false;
740  }
741 
742  # It's okay to autoblock. Go ahead and insert/update the block...
743 
744  # Do not add a *new* block if the IP is already blocked.
745  $ipblock = Block::newFromTarget( $autoblockIP );
746  if ( $ipblock ) {
747  # Check if the block is an autoblock and would exceed the user block
748  # if renewed. If so, do nothing, otherwise prolong the block time...
749  if ( $ipblock->mAuto && // @todo Why not compare $ipblock->mExpiry?
750  $this->mExpiry > Block::getAutoblockExpiry( $ipblock->mTimestamp )
751  ) {
752  # Reset block timestamp to now and its expiry to
753  # $wgAutoblockExpiry in the future
754  $ipblock->updateTimestamp();
755  }
756  return false;
757  }
758 
759  # Make a new block object with the desired properties.
760  $autoblock = new Block;
761  wfDebug( "Autoblocking {$this->getTarget()}@" . $autoblockIP . "\n" );
762  $autoblock->setTarget( $autoblockIP );
763  $autoblock->setBlocker( $this->getBlocker() );
764  $autoblock->mReason = wfMessage( 'autoblocker', $this->getTarget(), $this->mReason )
765  ->inContentLanguage()->plain();
767  $autoblock->mTimestamp = $timestamp;
768  $autoblock->mAuto = 1;
769  $autoblock->prevents( 'createaccount', $this->prevents( 'createaccount' ) );
770  # Continue suppressing the name if needed
771  $autoblock->mHideName = $this->mHideName;
772  $autoblock->prevents( 'editownusertalk', $this->prevents( 'editownusertalk' ) );
773  $autoblock->mParentBlockId = $this->mId;
774 
775  if ( $this->mExpiry == 'infinity' ) {
776  # Original block was indefinite, start an autoblock now
777  $autoblock->mExpiry = Block::getAutoblockExpiry( $timestamp );
778  } else {
779  # If the user is already blocked with an expiry date, we don't
780  # want to pile on top of that.
781  $autoblock->mExpiry = min( $this->mExpiry, Block::getAutoblockExpiry( $timestamp ) );
782  }
783 
784  # Insert the block...
785  $status = $autoblock->insert();
786  return $status
787  ? $status['id']
788  : false;
789  }
790 
795  public function deleteIfExpired() {
796 
797  if ( $this->isExpired() ) {
798  wfDebug( "Block::deleteIfExpired() -- deleting\n" );
799  $this->delete();
800  $retVal = true;
801  } else {
802  wfDebug( "Block::deleteIfExpired() -- not expired\n" );
803  $retVal = false;
804  }
805 
806  return $retVal;
807  }
808 
813  public function isExpired() {
815  wfDebug( "Block::isExpired() checking current " . $timestamp . " vs $this->mExpiry\n" );
816 
817  if ( !$this->mExpiry ) {
818  return false;
819  } else {
820  return $timestamp > $this->mExpiry;
821  }
822  }
823 
828  public function isValid() {
829  return $this->getTarget() != null;
830  }
831 
835  public function updateTimestamp() {
836  if ( $this->mAuto ) {
837  $this->mTimestamp = wfTimestamp();
838  $this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp );
839 
840  $dbw = wfGetDB( DB_MASTER );
841  $dbw->update( 'ipblocks',
842  [ /* SET */
843  'ipb_timestamp' => $dbw->timestamp( $this->mTimestamp ),
844  'ipb_expiry' => $dbw->timestamp( $this->mExpiry ),
845  ],
846  [ /* WHERE */
847  'ipb_id' => $this->getId(),
848  ],
849  __METHOD__
850  );
851  }
852  }
853 
859  public function getRangeStart() {
860  switch ( $this->type ) {
861  case self::TYPE_USER:
862  return '';
863  case self::TYPE_IP:
864  return IP::toHex( $this->target );
865  case self::TYPE_RANGE:
866  list( $start, /*...*/ ) = IP::parseRange( $this->target );
867  return $start;
868  default:
869  throw new MWException( "Block with invalid type" );
870  }
871  }
872 
878  public function getRangeEnd() {
879  switch ( $this->type ) {
880  case self::TYPE_USER:
881  return '';
882  case self::TYPE_IP:
883  return IP::toHex( $this->target );
884  case self::TYPE_RANGE:
885  list( /*...*/, $end ) = IP::parseRange( $this->target );
886  return $end;
887  default:
888  throw new MWException( "Block with invalid type" );
889  }
890  }
891 
897  public function getBy() {
898  $blocker = $this->getBlocker();
899  return ( $blocker instanceof User )
900  ? $blocker->getId()
901  : 0;
902  }
903 
909  public function getByName() {
910  $blocker = $this->getBlocker();
911  return ( $blocker instanceof User )
912  ? $blocker->getName()
913  : (string)$blocker; // username
914  }
915 
920  public function getId() {
921  return $this->mId;
922  }
923 
930  public function fromMaster( $x = null ) {
931  return wfSetVar( $this->mFromMaster, $x );
932  }
933 
939  public function isHardblock( $x = null ) {
940  wfSetVar( $this->isHardblock, $x );
941 
942  # You can't *not* hardblock a user
943  return $this->getType() == self::TYPE_USER
944  ? true
946  }
947 
952  public function isAutoblocking( $x = null ) {
953  wfSetVar( $this->isAutoblocking, $x );
954 
955  # You can't put an autoblock on an IP or range as we don't have any history to
956  # look over to get more IPs from
957  return $this->getType() == self::TYPE_USER
958  ? $this->isAutoblocking
959  : false;
960  }
961 
968  public function prevents( $action, $x = null ) {
969  switch ( $action ) {
970  case 'edit':
971  # For now... <evil laugh>
972  return true;
973 
974  case 'createaccount':
975  return wfSetVar( $this->mCreateAccount, $x );
976 
977  case 'sendemail':
978  return wfSetVar( $this->mBlockEmail, $x );
979 
980  case 'editownusertalk':
981  return wfSetVar( $this->mDisableUsertalk, $x );
982 
983  default:
984  return null;
985  }
986  }
987 
992  public function getRedactedName() {
993  if ( $this->mAuto ) {
994  return Html::rawElement(
995  'span',
996  [ 'class' => 'mw-autoblockid' ],
997  wfMessage( 'autoblockid', $this->mId )
998  );
999  } else {
1000  return htmlspecialchars( $this->getTarget() );
1001  }
1002  }
1003 
1010  public static function getAutoblockExpiry( $timestamp ) {
1011  global $wgAutoblockExpiry;
1012 
1013  return wfTimestamp( TS_MW, wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
1014  }
1015 
1019  public static function purgeExpired() {
1020  if ( wfReadOnly() ) {
1021  return;
1022  }
1023 
1025  wfGetDB( DB_MASTER ),
1026  __METHOD__,
1027  function ( IDatabase $dbw, $fname ) {
1028  $dbw->delete(
1029  'ipblocks',
1030  [ 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ],
1031  $fname
1032  );
1033  }
1034  ) );
1035  }
1036 
1057  public static function newFromTarget( $specificTarget, $vagueTarget = null, $fromMaster = false ) {
1058 
1059  list( $target, $type ) = self::parseTarget( $specificTarget );
1060  if ( $type == Block::TYPE_ID || $type == Block::TYPE_AUTO ) {
1061  return Block::newFromID( $target );
1062 
1063  } elseif ( $target === null && $vagueTarget == '' ) {
1064  # We're not going to find anything useful here
1065  # Be aware that the == '' check is explicit, since empty values will be
1066  # passed by some callers (bug 29116)
1067  return null;
1068 
1069  } elseif ( in_array(
1070  $type,
1072  ) {
1073  $block = new Block();
1074  $block->fromMaster( $fromMaster );
1075 
1076  if ( $type !== null ) {
1077  $block->setTarget( $target );
1078  }
1079 
1080  if ( $block->newLoad( $vagueTarget ) ) {
1081  return $block;
1082  }
1083  }
1084  return null;
1085  }
1086 
1097  public static function getBlocksForIPList( array $ipChain, $isAnon, $fromMaster = false ) {
1098  if ( !count( $ipChain ) ) {
1099  return [];
1100  }
1101 
1102  $conds = [];
1103  foreach ( array_unique( $ipChain ) as $ipaddr ) {
1104  # Discard invalid IP addresses. Since XFF can be spoofed and we do not
1105  # necessarily trust the header given to us, make sure that we are only
1106  # checking for blocks on well-formatted IP addresses (IPv4 and IPv6).
1107  # Do not treat private IP spaces as special as it may be desirable for wikis
1108  # to block those IP ranges in order to stop misbehaving proxies that spoof XFF.
1109  if ( !IP::isValid( $ipaddr ) ) {
1110  continue;
1111  }
1112  # Don't check trusted IPs (includes local squids which will be in every request)
1113  if ( IP::isTrustedProxy( $ipaddr ) ) {
1114  continue;
1115  }
1116  # Check both the original IP (to check against single blocks), as well as build
1117  # the clause to check for rangeblocks for the given IP.
1118  $conds['ipb_address'][] = $ipaddr;
1119  $conds[] = self::getRangeCond( IP::toHex( $ipaddr ) );
1120  }
1121 
1122  if ( !count( $conds ) ) {
1123  return [];
1124  }
1125 
1126  if ( $fromMaster ) {
1127  $db = wfGetDB( DB_MASTER );
1128  } else {
1129  $db = wfGetDB( DB_SLAVE );
1130  }
1131  $conds = $db->makeList( $conds, LIST_OR );
1132  if ( !$isAnon ) {
1133  $conds = [ $conds, 'ipb_anon_only' => 0 ];
1134  }
1135  $selectFields = array_merge(
1136  [ 'ipb_range_start', 'ipb_range_end' ],
1138  );
1139  $rows = $db->select( 'ipblocks',
1140  $selectFields,
1141  $conds,
1142  __METHOD__
1143  );
1144 
1145  $blocks = [];
1146  foreach ( $rows as $row ) {
1147  $block = self::newFromRow( $row );
1148  if ( !$block->isExpired() ) {
1149  $blocks[] = $block;
1150  }
1151  }
1152 
1153  return $blocks;
1154  }
1155 
1177  public static function chooseBlock( array $blocks, array $ipChain ) {
1178  if ( !count( $blocks ) ) {
1179  return null;
1180  } elseif ( count( $blocks ) == 1 ) {
1181  return $blocks[0];
1182  }
1183 
1184  // Sort hard blocks before soft ones and secondarily sort blocks
1185  // that disable account creation before those that don't.
1186  usort( $blocks, function ( Block $a, Block $b ) {
1187  $aWeight = (int)$a->isHardblock() . (int)$a->prevents( 'createaccount' );
1188  $bWeight = (int)$b->isHardblock() . (int)$b->prevents( 'createaccount' );
1189  return strcmp( $bWeight, $aWeight ); // highest weight first
1190  } );
1191 
1192  $blocksListExact = [
1193  'hard' => false,
1194  'disable_create' => false,
1195  'other' => false,
1196  'auto' => false
1197  ];
1198  $blocksListRange = [
1199  'hard' => false,
1200  'disable_create' => false,
1201  'other' => false,
1202  'auto' => false
1203  ];
1204  $ipChain = array_reverse( $ipChain );
1205 
1207  foreach ( $blocks as $block ) {
1208  // Stop searching if we have already have a "better" block. This
1209  // is why the order of the blocks matters
1210  if ( !$block->isHardblock() && $blocksListExact['hard'] ) {
1211  break;
1212  } elseif ( !$block->prevents( 'createaccount' ) && $blocksListExact['disable_create'] ) {
1213  break;
1214  }
1215 
1216  foreach ( $ipChain as $checkip ) {
1217  $checkipHex = IP::toHex( $checkip );
1218  if ( (string)$block->getTarget() === $checkip ) {
1219  if ( $block->isHardblock() ) {
1220  $blocksListExact['hard'] = $blocksListExact['hard'] ?: $block;
1221  } elseif ( $block->prevents( 'createaccount' ) ) {
1222  $blocksListExact['disable_create'] = $blocksListExact['disable_create'] ?: $block;
1223  } elseif ( $block->mAuto ) {
1224  $blocksListExact['auto'] = $blocksListExact['auto'] ?: $block;
1225  } else {
1226  $blocksListExact['other'] = $blocksListExact['other'] ?: $block;
1227  }
1228  // We found closest exact match in the ip list, so go to the next Block
1229  break;
1230  } elseif ( array_filter( $blocksListExact ) == []
1231  && $block->getRangeStart() <= $checkipHex
1232  && $block->getRangeEnd() >= $checkipHex
1233  ) {
1234  if ( $block->isHardblock() ) {
1235  $blocksListRange['hard'] = $blocksListRange['hard'] ?: $block;
1236  } elseif ( $block->prevents( 'createaccount' ) ) {
1237  $blocksListRange['disable_create'] = $blocksListRange['disable_create'] ?: $block;
1238  } elseif ( $block->mAuto ) {
1239  $blocksListRange['auto'] = $blocksListRange['auto'] ?: $block;
1240  } else {
1241  $blocksListRange['other'] = $blocksListRange['other'] ?: $block;
1242  }
1243  break;
1244  }
1245  }
1246  }
1247 
1248  if ( array_filter( $blocksListExact ) == [] ) {
1249  $blocksList = &$blocksListRange;
1250  } else {
1251  $blocksList = &$blocksListExact;
1252  }
1253 
1254  $chosenBlock = null;
1255  if ( $blocksList['hard'] ) {
1256  $chosenBlock = $blocksList['hard'];
1257  } elseif ( $blocksList['disable_create'] ) {
1258  $chosenBlock = $blocksList['disable_create'];
1259  } elseif ( $blocksList['other'] ) {
1260  $chosenBlock = $blocksList['other'];
1261  } elseif ( $blocksList['auto'] ) {
1262  $chosenBlock = $blocksList['auto'];
1263  } else {
1264  throw new MWException( "Proxy block found, but couldn't be classified." );
1265  }
1266 
1267  return $chosenBlock;
1268  }
1269 
1279  public static function parseTarget( $target ) {
1280  # We may have been through this before
1281  if ( $target instanceof User ) {
1282  if ( IP::isValid( $target->getName() ) ) {
1283  return [ $target, self::TYPE_IP ];
1284  } else {
1285  return [ $target, self::TYPE_USER ];
1286  }
1287  } elseif ( $target === null ) {
1288  return [ null, null ];
1289  }
1290 
1291  $target = trim( $target );
1292 
1293  if ( IP::isValid( $target ) ) {
1294  # We can still create a User if it's an IP address, but we need to turn
1295  # off validation checking (which would exclude IP addresses)
1296  return [
1299  ];
1300 
1301  } elseif ( IP::isValidBlock( $target ) ) {
1302  # Can't create a User from an IP range
1304  }
1305 
1306  # Consider the possibility that this is not a username at all
1307  # but actually an old subpage (bug #29797)
1308  if ( strpos( $target, '/' ) !== false ) {
1309  # An old subpage, drill down to the user behind it
1310  $target = explode( '/', $target )[0];
1311  }
1312 
1313  $userObj = User::newFromName( $target );
1314  if ( $userObj instanceof User ) {
1315  # Note that since numbers are valid usernames, a $target of "12345" will be
1316  # considered a User. If you want to pass a block ID, prepend a hash "#12345",
1317  # since hash characters are not valid in usernames or titles generally.
1318  return [ $userObj, Block::TYPE_USER ];
1319 
1320  } elseif ( preg_match( '/^#\d+$/', $target ) ) {
1321  # Autoblock reference in the form "#12345"
1322  return [ substr( $target, 1 ), Block::TYPE_AUTO ];
1323 
1324  } else {
1325  # WTF?
1326  return [ null, null ];
1327  }
1328  }
1329 
1334  public function getType() {
1335  return $this->mAuto
1336  ? self::TYPE_AUTO
1337  : $this->type;
1338  }
1339 
1347  public function getTargetAndType() {
1348  return [ $this->getTarget(), $this->getType() ];
1349  }
1350 
1357  public function getTarget() {
1358  return $this->target;
1359  }
1360 
1366  public function getExpiry() {
1367  return $this->mExpiry;
1368  }
1369 
1374  public function setTarget( $target ) {
1375  list( $this->target, $this->type ) = self::parseTarget( $target );
1376  }
1377 
1382  public function getBlocker() {
1383  return $this->blocker;
1384  }
1385 
1390  public function setBlocker( $user ) {
1391  $this->blocker = $user;
1392  }
1393 
1402  $blocker = $this->getBlocker();
1403  if ( $blocker instanceof User ) { // local user
1404  $blockerUserpage = $blocker->getUserPage();
1405  $link = "[[{$blockerUserpage->getPrefixedText()}|{$blockerUserpage->getText()}]]";
1406  } else { // foreign user
1407  $link = $blocker;
1408  }
1409 
1410  $reason = $this->mReason;
1411  if ( $reason == '' ) {
1412  $reason = $context->msg( 'blockednoreason' )->text();
1413  }
1414 
1415  /* $ip returns who *is* being blocked, $intended contains who was meant to be blocked.
1416  * This could be a username, an IP range, or a single IP. */
1417  $intended = $this->getTarget();
1418 
1419  $lang = $context->getLanguage();
1420  return [
1421  $this->mAuto ? 'autoblockedtext' : 'blockedtext',
1422  $link,
1423  $reason,
1424  $context->getRequest()->getIP(),
1425  $this->getByName(),
1426  $this->getId(),
1427  $lang->formatExpiry( $this->mExpiry ),
1428  (string)$intended,
1429  $lang->userTimeAndDate( $this->mTimestamp, $context->getUser() ),
1430  ];
1431  }
1432 }
getBy()
Get the user id of the blocking sysop.
Definition: Block.php:897
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:1390
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:640
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:1177
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:681
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:828
msg()
Get a Message object with context set.
getType()
Get the type of target for this particular block.
Definition: Block.php:1334
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:920
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:2088
update()
Update a block in the DB with new parameters.
Definition: Block.php:515
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:878
getAutoblockUpdateArray()
Definition: Block.php:600
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:795
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:1366
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:1347
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:1057
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:992
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:1374
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:725
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:1279
static purgeExpired()
Purge expired blocks from the ipblocks table.
Definition: Block.php:1019
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:617
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:1097
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:835
$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:968
static getAutoblockExpiry($timestamp)
Get a timestamp of the expiry for autoblocks.
Definition: Block.php:1010
getBlocker()
Get the user who implemented this block.
Definition: Block.php:1382
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:2063
getPermissionsError(IContextSource $context)
Get the key and parameters for the corresponding error message.
Definition: Block.php:1401
isAutoblocking($x=null)
Definition: Block.php:952
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:1357
getUserPage()
Get this user's personal page title.
Definition: User.php:4066
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:562
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:930
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:939
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:859
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:909
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:813