MediaWiki  REL1_19
Block.php
Go to the documentation of this file.
00001 <?php
00022 class Block {
00023         /* public*/ var $mReason, $mTimestamp, $mAuto, $mExpiry, $mHideName;
00024 
00025         protected
00026                 $mId,
00027                 $mFromMaster,
00028 
00029                 $mBlockEmail,
00030                 $mDisableUsertalk,
00031                 $mCreateAccount;
00032 
00034         protected $target;
00035 
00037         protected $type;
00038 
00040         protected $blocker;
00041 
00043         protected $isHardblock = true;
00044 
00046         protected $isAutoblocking = true;
00047 
00048         # TYPE constants
00049         const TYPE_USER = 1;
00050         const TYPE_IP = 2;
00051         const TYPE_RANGE = 3;
00052         const TYPE_AUTO = 4;
00053         const TYPE_ID = 5;
00054 
00060         function __construct( $address = '', $user = 0, $by = 0, $reason = '',
00061                 $timestamp = 0, $auto = 0, $expiry = '', $anonOnly = 0, $createAccount = 0, $enableAutoblock = 0,
00062                 $hideName = 0, $blockEmail = 0, $allowUsertalk = 0, $byText = '' )
00063         {
00064                 if( $timestamp === 0 ){
00065                         $timestamp = wfTimestampNow();
00066                 }
00067 
00068                 if( count( func_get_args() ) > 0 ){
00069                         # Soon... :D
00070                         # wfDeprecated( __METHOD__ . " with arguments" );
00071                 }
00072 
00073                 $this->setTarget( $address );
00074                 if ( $this->target instanceof User && $user ) {
00075                         $this->target->setId( $user ); // needed for foreign users
00076                 }
00077                 if ( $by ) { // local user
00078                         $this->setBlocker( User::newFromID( $by ) );
00079                 } else { // foreign user
00080                         $this->setBlocker( $byText );
00081                 }
00082                 $this->mReason = $reason;
00083                 $this->mTimestamp = wfTimestamp( TS_MW, $timestamp );
00084                 $this->mAuto = $auto;
00085                 $this->isHardblock( !$anonOnly );
00086                 $this->prevents( 'createaccount', $createAccount );
00087                 if ( $expiry == 'infinity' || $expiry == wfGetDB( DB_SLAVE )->getInfinity() ) {
00088                         $this->mExpiry = 'infinity';
00089                 } else {
00090                         $this->mExpiry = wfTimestamp( TS_MW, $expiry );
00091                 }
00092                 $this->isAutoblocking( $enableAutoblock );
00093                 $this->mHideName = $hideName;
00094                 $this->prevents( 'sendemail', $blockEmail );
00095                 $this->prevents( 'editownusertalk', !$allowUsertalk );
00096 
00097                 $this->mFromMaster = false;
00098         }
00099 
00110         public static function newFromDB( $address, $user = 0 ) {
00111                 wfDeprecated( __METHOD__, '1.18' );
00112                 return self::newFromTarget( User::whoIs( $user ), $address );
00113         }
00114 
00121         public static function newFromID( $id ) {
00122                 $dbr = wfGetDB( DB_SLAVE );
00123                 $res = $dbr->selectRow(
00124                         'ipblocks',
00125                         '*',
00126                         array( 'ipb_id' => $id ),
00127                         __METHOD__
00128                 );
00129                 if ( $res ) {
00130                         return Block::newFromRow( $res );
00131                 } else {
00132                         return null;
00133                 }
00134         }
00135 
00144         public function equals( Block $block ) {
00145                 return (
00146                         (string)$this->target == (string)$block->target
00147                         && $this->type == $block->type
00148                         && $this->mAuto == $block->mAuto
00149                         && $this->isHardblock() == $block->isHardblock()
00150                         && $this->prevents( 'createaccount' ) == $block->prevents( 'createaccount' )
00151                         && $this->mExpiry == $block->mExpiry
00152                         && $this->isAutoblocking() == $block->isAutoblocking()
00153                         && $this->mHideName == $block->mHideName
00154                         && $this->prevents( 'sendemail' ) == $block->prevents( 'sendemail' )
00155                         && $this->prevents( 'editownusertalk' ) == $block->prevents( 'editownusertalk' )
00156                         && $this->mReason == $block->mReason
00157                 );
00158         }
00159 
00165         public function clear() {
00166                 wfDeprecated( __METHOD__, '1.18' );
00167                 # Noop
00168         }
00169 
00178         public function load( $address = '', $user = 0 ) {
00179                 wfDeprecated( __METHOD__, '1.18' );
00180                 if( $user ){
00181                         $username = User::whoIs( $user );
00182                         $block = self::newFromTarget( $username, $address );
00183                 } else {
00184                         $block = self::newFromTarget( null, $address );
00185                 }
00186 
00187                 if( $block instanceof Block ){
00188                         # This is mildly evil, but hey, it's B/C :D
00189                         foreach( $block as $variable => $value ){
00190                                 $this->$variable = $value;
00191                         }
00192                         return true;
00193                 } else {
00194                         return false;
00195                 }
00196         }
00197 
00207         protected function newLoad( $vagueTarget = null ) {
00208                 $db = wfGetDB( $this->mFromMaster ? DB_MASTER : DB_SLAVE );
00209 
00210                 if( $this->type !== null ){
00211                         $conds = array(
00212                                 'ipb_address' => array( (string)$this->target ),
00213                         );
00214                 } else {
00215                         $conds = array( 'ipb_address' => array() );
00216                 }
00217 
00218                 # Be aware that the != '' check is explicit, since empty values will be
00219                 # passed by some callers (bug 29116)
00220                 if( $vagueTarget != ''){
00221                         list( $target, $type ) = self::parseTarget( $vagueTarget );
00222                         switch( $type ) {
00223                                 case self::TYPE_USER:
00224                                         # Slightly wierd, but who are we to argue?
00225                                         $conds['ipb_address'][] = (string)$target;
00226                                         break;
00227 
00228                                 case self::TYPE_IP:
00229                                         $conds['ipb_address'][] = (string)$target;
00230                                         $conds[] = self::getRangeCond( IP::toHex( $target ) );
00231                                         $conds = $db->makeList( $conds, LIST_OR );
00232                                         break;
00233 
00234                                 case self::TYPE_RANGE:
00235                                         list( $start, $end ) = IP::parseRange( $target );
00236                                         $conds['ipb_address'][] = (string)$target;
00237                                         $conds[] = self::getRangeCond( $start, $end );
00238                                         $conds = $db->makeList( $conds, LIST_OR );
00239                                         break;
00240 
00241                                 default:
00242                                         throw new MWException( "Tried to load block with invalid type" );
00243                         }
00244                 }
00245 
00246                 $res = $db->select( 'ipblocks', '*', $conds, __METHOD__ );
00247 
00248                 # This result could contain a block on the user, a block on the IP, and a russian-doll
00249                 # set of rangeblocks.  We want to choose the most specific one, so keep a leader board.
00250                 $bestRow = null;
00251 
00252                 # Lower will be better
00253                 $bestBlockScore = 100;
00254 
00255                 # This is begging for $this = $bestBlock, but that's not allowed in PHP :(
00256                 $bestBlockPreventsEdit = null;
00257 
00258                 foreach( $res as $row ){
00259                         $block = Block::newFromRow( $row );
00260 
00261                         # Don't use expired blocks
00262                         if( $block->deleteIfExpired() ){
00263                                 continue;
00264                         }
00265 
00266                         # Don't use anon only blocks on users
00267                         if( $this->type == self::TYPE_USER && !$block->isHardblock() ){
00268                                 continue;
00269                         }
00270 
00271                         if( $block->getType() == self::TYPE_RANGE ){
00272                                 # This is the number of bits that are allowed to vary in the block, give
00273                                 # or take some floating point errors
00274                                 $end = wfBaseconvert( $block->getRangeEnd(), 16, 10 );
00275                                 $start = wfBaseconvert( $block->getRangeStart(), 16, 10 );
00276                                 $size = log( $end - $start + 1, 2 );
00277 
00278                                 # This has the nice property that a /32 block is ranked equally with a
00279                                 # single-IP block, which is exactly what it is...
00280                                 $score = self::TYPE_RANGE  - 1 + ( $size / 128 );
00281 
00282                         } else {
00283                                 $score = $block->getType();
00284                         }
00285 
00286                         if( $score < $bestBlockScore ){
00287                                 $bestBlockScore = $score;
00288                                 $bestRow = $row;
00289                                 $bestBlockPreventsEdit = $block->prevents( 'edit' );
00290                         }
00291                 }
00292 
00293                 if( $bestRow !== null ){
00294                         $this->initFromRow( $bestRow );
00295                         $this->prevents( 'edit', $bestBlockPreventsEdit );
00296                         return true;
00297                 } else {
00298                         return false;
00299                 }
00300         }
00301 
00308         public static function getRangeCond( $start, $end = null ) {
00309                 if ( $end === null ) {
00310                         $end = $start;
00311                 }
00312                 # Per bug 14634, we want to include relevant active rangeblocks; for
00313                 # rangeblocks, we want to include larger ranges which enclose the given
00314                 # range. We know that all blocks must be smaller than $wgBlockCIDRLimit,
00315                 # so we can improve performance by filtering on a LIKE clause
00316                 $chunk = self::getIpFragment( $start );
00317                 $dbr = wfGetDB( DB_SLAVE );
00318                 $like = $dbr->buildLike( $chunk, $dbr->anyString() );
00319 
00320                 # Fairly hard to make a malicious SQL statement out of hex characters,
00321                 # but stranger things have happened...
00322                 $safeStart = $dbr->addQuotes( $start );
00323                 $safeEnd = $dbr->addQuotes( $end );
00324 
00325                 return $dbr->makeList(
00326                         array(
00327                                 "ipb_range_start $like",
00328                                 "ipb_range_start <= $safeStart",
00329                                 "ipb_range_end >= $safeEnd",
00330                         ),
00331                         LIST_AND
00332                 );
00333         }
00334 
00341         protected static function getIpFragment( $hex ) {
00342                 global $wgBlockCIDRLimit;
00343                 if ( substr( $hex, 0, 3 ) == 'v6-' ) {
00344                         return 'v6-' . substr( substr( $hex, 3 ), 0,  floor( $wgBlockCIDRLimit['IPv6'] / 4 ) );
00345                 } else {
00346                         return substr( $hex, 0,  floor( $wgBlockCIDRLimit['IPv4'] / 4 ) );
00347                 }
00348         }
00349 
00355         protected function initFromRow( $row ) {
00356                 $this->setTarget( $row->ipb_address );
00357                 if ( $row->ipb_by ) { // local user
00358                         $this->setBlocker( User::newFromID( $row->ipb_by ) );
00359                 } else { // foreign user
00360                         $this->setBlocker( $row->ipb_by_text );
00361                 }
00362 
00363                 $this->mReason = $row->ipb_reason;
00364                 $this->mTimestamp = wfTimestamp( TS_MW, $row->ipb_timestamp );
00365                 $this->mAuto = $row->ipb_auto;
00366                 $this->mHideName = $row->ipb_deleted;
00367                 $this->mId = $row->ipb_id;
00368 
00369                 // I wish I didn't have to do this
00370                 $db = wfGetDB( DB_SLAVE );
00371                 if ( $row->ipb_expiry == $db->getInfinity() ) {
00372                         $this->mExpiry = 'infinity';
00373                 } else {
00374                         $this->mExpiry = wfTimestamp( TS_MW, $row->ipb_expiry );
00375                 }
00376 
00377                 $this->isHardblock( !$row->ipb_anon_only );
00378                 $this->isAutoblocking( $row->ipb_enable_autoblock );
00379 
00380                 $this->prevents( 'createaccount', $row->ipb_create_account );
00381                 $this->prevents( 'sendemail', $row->ipb_block_email );
00382                 $this->prevents( 'editownusertalk', !$row->ipb_allow_usertalk );
00383         }
00384 
00390         public static function newFromRow( $row ){
00391                 $block = new Block;
00392                 $block->initFromRow( $row );
00393                 return $block;
00394         }
00395 
00401         public function delete() {
00402                 if ( wfReadOnly() ) {
00403                         return false;
00404                 }
00405 
00406                 if ( !$this->getId() ) {
00407                         throw new MWException( "Block::delete() requires that the mId member be filled\n" );
00408                 }
00409 
00410                 $dbw = wfGetDB( DB_MASTER );
00411                 $dbw->delete( 'ipblocks', array( 'ipb_id' => $this->getId() ), __METHOD__ );
00412 
00413                 return $dbw->affectedRows() > 0;
00414         }
00415 
00424         public function insert( $dbw = null ) {
00425                 wfDebug( "Block::insert; timestamp {$this->mTimestamp}\n" );
00426 
00427                 if ( $dbw === null ) {
00428                         $dbw = wfGetDB( DB_MASTER );
00429                 }
00430 
00431                 # Don't collide with expired blocks
00432                 Block::purgeExpired();
00433 
00434                 $row = $this->getDatabaseArray();
00435                 $row['ipb_id'] = $dbw->nextSequenceValue("ipblocks_ipb_id_seq");
00436 
00437                 $dbw->insert(
00438                         'ipblocks',
00439                         $row,
00440                         __METHOD__,
00441                         array( 'IGNORE' )
00442                 );
00443                 $affected = $dbw->affectedRows();
00444                 $this->mId = $dbw->insertId();
00445 
00446                 if ( $affected ) {
00447                         $auto_ipd_ids = $this->doRetroactiveAutoblock();
00448                         return array( 'id' => $this->mId, 'autoIds' => $auto_ipd_ids );
00449                 }
00450 
00451                 return false;
00452         }
00453 
00461         public function update() {
00462                 wfDebug( "Block::update; timestamp {$this->mTimestamp}\n" );
00463                 $dbw = wfGetDB( DB_MASTER );
00464 
00465                 $dbw->update(
00466                         'ipblocks',
00467                         $this->getDatabaseArray( $dbw ),
00468                         array( 'ipb_id' => $this->getId() ),
00469                         __METHOD__
00470                 );
00471 
00472                 return $dbw->affectedRows();
00473         }
00474 
00480         protected function getDatabaseArray( $db = null ){
00481                 if( !$db ){
00482                         $db = wfGetDB( DB_SLAVE );
00483                 }
00484                 $expiry = $db->encodeExpiry( $this->mExpiry );
00485 
00486                 $a = array(
00487                         'ipb_address'          => (string)$this->target,
00488                         'ipb_user'             => $this->target instanceof User ? $this->target->getID() : 0,
00489                         'ipb_by'               => $this->getBy(),
00490                         'ipb_by_text'          => $this->getByName(),
00491                         'ipb_reason'           => $this->mReason,
00492                         'ipb_timestamp'        => $db->timestamp( $this->mTimestamp ),
00493                         'ipb_auto'             => $this->mAuto,
00494                         'ipb_anon_only'        => !$this->isHardblock(),
00495                         'ipb_create_account'   => $this->prevents( 'createaccount' ),
00496                         'ipb_enable_autoblock' => $this->isAutoblocking(),
00497                         'ipb_expiry'           => $expiry,
00498                         'ipb_range_start'      => $this->getRangeStart(),
00499                         'ipb_range_end'        => $this->getRangeEnd(),
00500                         'ipb_deleted'          => intval( $this->mHideName ), // typecast required for SQLite
00501                         'ipb_block_email'      => $this->prevents( 'sendemail' ),
00502                         'ipb_allow_usertalk'   => !$this->prevents( 'editownusertalk' )
00503                 );
00504 
00505                 return $a;
00506         }
00507 
00514         protected function doRetroactiveAutoblock() {
00515                 $blockIds = array();
00516                 # If autoblock is enabled, autoblock the LAST IP(s) used
00517                 if ( $this->isAutoblocking() && $this->getType() == self::TYPE_USER ) {
00518                         wfDebug( "Doing retroactive autoblocks for " . $this->getTarget() . "\n" );
00519 
00520                         $continue = wfRunHooks(
00521                                 'PerformRetroactiveAutoblock', array( $this, &$blockIds ) );
00522 
00523                         if ( $continue ) {
00524                                 self::defaultRetroactiveAutoblock( $this, $blockIds );
00525                         }
00526                 }
00527                 return $blockIds;
00528         }
00529 
00538         protected static function defaultRetroactiveAutoblock( Block $block, array &$blockIds ) {
00539                 $dbr = wfGetDB( DB_SLAVE );
00540 
00541                 $options = array( 'ORDER BY' => 'rc_timestamp DESC' );
00542                 $conds = array( 'rc_user_text' => (string)$block->getTarget() );
00543 
00544                 // Just the last IP used.
00545                 $options['LIMIT'] = 1;
00546 
00547                 $res = $dbr->select( 'recentchanges', array( 'rc_ip' ), $conds,
00548                         __METHOD__ ,  $options );
00549 
00550                 if ( !$dbr->numRows( $res ) ) {
00551                         # No results, don't autoblock anything
00552                         wfDebug( "No IP found to retroactively autoblock\n" );
00553                 } else {
00554                         foreach ( $res as $row ) {
00555                                 if ( $row->rc_ip ) {
00556                                         $id = $block->doAutoblock( $row->rc_ip );
00557                                         if ( $id ) $blockIds[] = $id;
00558                                 }
00559                         }
00560                 }
00561         }
00562 
00570         public static function isWhitelistedFromAutoblocks( $ip ) {
00571                 global $wgMemc;
00572 
00573                 // Try to get the autoblock_whitelist from the cache, as it's faster
00574                 // than getting the msg raw and explode()'ing it.
00575                 $key = wfMemcKey( 'ipb', 'autoblock', 'whitelist' );
00576                 $lines = $wgMemc->get( $key );
00577                 if ( !$lines ) {
00578                         $lines = explode( "\n", wfMsgForContentNoTrans( 'autoblock_whitelist' ) );
00579                         $wgMemc->set( $key, $lines, 3600 * 24 );
00580                 }
00581 
00582                 wfDebug( "Checking the autoblock whitelist..\n" );
00583 
00584                 foreach ( $lines as $line ) {
00585                         # List items only
00586                         if ( substr( $line, 0, 1 ) !== '*' ) {
00587                                 continue;
00588                         }
00589 
00590                         $wlEntry = substr( $line, 1 );
00591                         $wlEntry = trim( $wlEntry );
00592 
00593                         wfDebug( "Checking $ip against $wlEntry..." );
00594 
00595                         # Is the IP in this range?
00596                         if ( IP::isInRange( $ip, $wlEntry ) ) {
00597                                 wfDebug( " IP $ip matches $wlEntry, not autoblocking\n" );
00598                                 return true;
00599                         } else {
00600                                 wfDebug( " No match\n" );
00601                         }
00602                 }
00603 
00604                 return false;
00605         }
00606 
00613         public function doAutoblock( $autoblockIP ) {
00614                 # If autoblocks are disabled, go away.
00615                 if ( !$this->isAutoblocking() ) {
00616                         return false;
00617                 }
00618 
00619                 # Check for presence on the autoblock whitelist.
00620                 if ( self::isWhitelistedFromAutoblocks( $autoblockIP ) ) {
00621                         return false;
00622                 }
00623 
00624                 # Allow hooks to cancel the autoblock.
00625                 if ( !wfRunHooks( 'AbortAutoblock', array( $autoblockIP, &$this ) ) ) {
00626                         wfDebug( "Autoblock aborted by hook.\n" );
00627                         return false;
00628                 }
00629 
00630                 # It's okay to autoblock. Go ahead and insert/update the block...
00631 
00632                 # Do not add a *new* block if the IP is already blocked.
00633                 $ipblock = Block::newFromTarget( $autoblockIP );
00634                 if ( $ipblock ) {
00635                         # Check if the block is an autoblock and would exceed the user block
00636                         # if renewed. If so, do nothing, otherwise prolong the block time...
00637                         if ( $ipblock->mAuto && // @TODO: why not compare $ipblock->mExpiry?
00638                                 $this->mExpiry > Block::getAutoblockExpiry( $ipblock->mTimestamp )
00639                         ) {
00640                                 # Reset block timestamp to now and its expiry to
00641                                 # $wgAutoblockExpiry in the future
00642                                 $ipblock->updateTimestamp();
00643                         }
00644                         return false;
00645                 }
00646 
00647                 # Make a new block object with the desired properties.
00648                 $autoblock = new Block;
00649                 wfDebug( "Autoblocking {$this->getTarget()}@" . $autoblockIP . "\n" );
00650                 $autoblock->setTarget( $autoblockIP );
00651                 $autoblock->setBlocker( $this->getBlocker() );
00652                 $autoblock->mReason = wfMsgForContent( 'autoblocker', $this->getTarget(), $this->mReason );
00653                 $timestamp = wfTimestampNow();
00654                 $autoblock->mTimestamp = $timestamp;
00655                 $autoblock->mAuto = 1;
00656                 $autoblock->prevents( 'createaccount', $this->prevents( 'createaccount' ) );
00657                 # Continue suppressing the name if needed
00658                 $autoblock->mHideName = $this->mHideName;
00659                 $autoblock->prevents( 'editownusertalk', $this->prevents( 'editownusertalk' ) );
00660 
00661                 if ( $this->mExpiry == 'infinity' ) {
00662                         # Original block was indefinite, start an autoblock now
00663                         $autoblock->mExpiry = Block::getAutoblockExpiry( $timestamp );
00664                 } else {
00665                         # If the user is already blocked with an expiry date, we don't
00666                         # want to pile on top of that.
00667                         $autoblock->mExpiry = min( $this->mExpiry, Block::getAutoblockExpiry( $timestamp ) );
00668                 }
00669 
00670                 # Insert the block...
00671                 $status = $autoblock->insert();
00672                 return $status
00673                         ? $status['id']
00674                         : false;
00675         }
00676 
00681         public function deleteIfExpired() {
00682                 wfProfileIn( __METHOD__ );
00683 
00684                 if ( $this->isExpired() ) {
00685                         wfDebug( "Block::deleteIfExpired() -- deleting\n" );
00686                         $this->delete();
00687                         $retVal = true;
00688                 } else {
00689                         wfDebug( "Block::deleteIfExpired() -- not expired\n" );
00690                         $retVal = false;
00691                 }
00692 
00693                 wfProfileOut( __METHOD__ );
00694                 return $retVal;
00695         }
00696 
00701         public function isExpired() {
00702                 $timestamp = wfTimestampNow();
00703                 wfDebug( "Block::isExpired() checking current " . $timestamp . " vs $this->mExpiry\n" );
00704 
00705                 if ( !$this->mExpiry ) {
00706                         return false;
00707                 } else {
00708                         return $timestamp > $this->mExpiry;
00709                 }
00710         }
00711 
00716         public function isValid() {
00717                 return $this->getTarget() != null;
00718         }
00719 
00723         public function updateTimestamp() {
00724                 if ( $this->mAuto ) {
00725                         $this->mTimestamp = wfTimestamp();
00726                         $this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp );
00727 
00728                         $dbw = wfGetDB( DB_MASTER );
00729                         $dbw->update( 'ipblocks',
00730                                 array( /* SET */
00731                                         'ipb_timestamp' => $dbw->timestamp( $this->mTimestamp ),
00732                                         'ipb_expiry' => $dbw->timestamp( $this->mExpiry ),
00733                                 ),
00734                                 array( /* WHERE */
00735                                         'ipb_address' => (string)$this->getTarget()
00736                                 ),
00737                                 __METHOD__
00738                         );
00739                 }
00740         }
00741 
00746         public function getRangeStart() {
00747                 switch( $this->type ) {
00748                         case self::TYPE_USER:
00749                                 return '';
00750                         case self::TYPE_IP:
00751                                 return IP::toHex( $this->target );
00752                         case self::TYPE_RANGE:
00753                                 list( $start, /*...*/ ) = IP::parseRange( $this->target );
00754                                 return $start;
00755                         default: throw new MWException( "Block with invalid type" );
00756                 }
00757         }
00758 
00763         public function getRangeEnd() {
00764                 switch( $this->type ) {
00765                         case self::TYPE_USER:
00766                                 return '';
00767                         case self::TYPE_IP:
00768                                 return IP::toHex( $this->target );
00769                         case self::TYPE_RANGE:
00770                                 list( /*...*/, $end ) = IP::parseRange( $this->target );
00771                                 return $end;
00772                         default: throw new MWException( "Block with invalid type" );
00773                 }
00774         }
00775 
00781         public function getBy() {
00782                 $blocker = $this->getBlocker();
00783                 return ( $blocker instanceof User )
00784                         ? $blocker->getId()
00785                         : 0;
00786         }
00787 
00793         public function getByName() {
00794                 $blocker = $this->getBlocker();
00795                 return ( $blocker instanceof User )
00796                         ? $blocker->getName()
00797                         : (string)$blocker; // username
00798         }
00799 
00804         public function getId() {
00805                 return $this->mId;
00806         }
00807 
00814         public function forUpdate( $x = null ) {
00815                 wfDeprecated( __METHOD__, '1.18' );
00816                 # noop
00817         }
00818 
00825         public function fromMaster( $x = null ) {
00826                 return wfSetVar( $this->mFromMaster, $x );
00827         }
00828 
00834         public function isHardblock( $x = null ) {
00835                 wfSetVar( $this->isHardblock, $x );
00836 
00837                 # You can't *not* hardblock a user
00838                 return $this->getType() == self::TYPE_USER
00839                         ? true
00840                         : $this->isHardblock;
00841         }
00842 
00843         public function isAutoblocking( $x = null ) {
00844                 wfSetVar( $this->isAutoblocking, $x );
00845 
00846                 # You can't put an autoblock on an IP or range as we don't have any history to
00847                 # look over to get more IPs from
00848                 return $this->getType() == self::TYPE_USER
00849                         ? $this->isAutoblocking
00850                         : false;
00851         }
00852 
00859         public function prevents( $action, $x = null ) {
00860                 switch( $action ) {
00861                         case 'edit':
00862                                 # For now... <evil laugh>
00863                                 return true;
00864 
00865                         case 'createaccount':
00866                                 return wfSetVar( $this->mCreateAccount, $x );
00867 
00868                         case 'sendemail':
00869                                 return wfSetVar( $this->mBlockEmail, $x );
00870 
00871                         case 'editownusertalk':
00872                                 return wfSetVar( $this->mDisableUsertalk, $x );
00873 
00874                         default:
00875                                 return null;
00876                 }
00877         }
00878 
00883         public function getRedactedName() {
00884                 if ( $this->mAuto ) {
00885                         return Html::rawElement(
00886                                 'span',
00887                                 array( 'class' => 'mw-autoblockid' ),
00888                                 wfMessage( 'autoblockid', $this->mId )
00889                         );
00890                 } else {
00891                         return htmlspecialchars( $this->getTarget() );
00892                 }
00893         }
00894 
00903         public static function encodeExpiry( $expiry, $db ) {
00904                 wfDeprecated( __METHOD__, '1.18' );
00905                 return $db->encodeExpiry( $expiry );
00906         }
00907 
00916         public static function decodeExpiry( $expiry, $timestampType = TS_MW ) {
00917                 wfDeprecated( __METHOD__, '1.18' );
00918                 global $wgContLang;
00919                 return $wgContLang->formatExpiry( $expiry, $timestampType );
00920         }
00921 
00928         public static function getAutoblockExpiry( $timestamp ) {
00929                 global $wgAutoblockExpiry;
00930 
00931                 return wfTimestamp( TS_MW, wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
00932         }
00933 
00941         public static function normaliseRange( $range ) {
00942                 wfDeprecated( __METHOD__, '1.18' );
00943                 return IP::sanitizeRange( $range );
00944         }
00945 
00949         public static function purgeExpired() {
00950                 $dbw = wfGetDB( DB_MASTER );
00951                 $dbw->delete( 'ipblocks',
00952                         array( 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), __METHOD__ );
00953         }
00954 
00961         public static function infinity() {
00962                 wfDeprecated( __METHOD__, '1.18' );
00963                 return wfGetDB( DB_SLAVE )->getInfinity();
00964         }
00965 
00973         public static function formatExpiry( $encoded_expiry ) {
00974                 wfDeprecated( __METHOD__, '1.18' );
00975 
00976                 global $wgContLang;
00977                 static $msg = null;
00978 
00979                 if ( is_null( $msg ) ) {
00980                         $msg = array();
00981                         $keys = array( 'infiniteblock', 'expiringblock' );
00982 
00983                         foreach ( $keys as $key ) {
00984                                 $msg[$key] = wfMsgHtml( $key );
00985                         }
00986                 }
00987 
00988                 $expiry = $wgContLang->formatExpiry( $encoded_expiry, TS_MW );
00989                 if ( $expiry == wfGetDB( DB_SLAVE )->getInfinity() ) {
00990                         $expirystr = $msg['infiniteblock'];
00991                 } else {
00992                         global $wgLang;
00993                         $expiredatestr = htmlspecialchars( $wgLang->date( $expiry, true ) );
00994                         $expiretimestr = htmlspecialchars( $wgLang->time( $expiry, true ) );
00995                         $expirystr = wfMsgReplaceArgs( $msg['expiringblock'], array( $expiredatestr, $expiretimestr ) );
00996                 }
00997 
00998                 return $expirystr;
00999         }
01000 
01008         public static function parseExpiryInput( $expiry ) {
01009                 wfDeprecated( __METHOD__, '1.18' );
01010                 return SpecialBlock::parseExpiryInput( $expiry );
01011         }
01012 
01033         public static function newFromTarget( $specificTarget, $vagueTarget = null, $fromMaster = false ) {
01034 
01035                 list( $target, $type ) = self::parseTarget( $specificTarget );
01036                 if( $type == Block::TYPE_ID || $type == Block::TYPE_AUTO ){
01037                         return Block::newFromID( $target );
01038 
01039                 } elseif( $target === null && $vagueTarget == '' ){
01040                         # We're not going to find anything useful here
01041                         # Be aware that the == '' check is explicit, since empty values will be
01042                         # passed by some callers (bug 29116)
01043                         return null;
01044 
01045                 } elseif( in_array( $type, array( Block::TYPE_USER, Block::TYPE_IP, Block::TYPE_RANGE ) ) ) {
01046                         $block = new Block();
01047                         $block->fromMaster( $fromMaster );
01048 
01049                         if( $type !== null ){
01050                                 $block->setTarget( $target );
01051                         }
01052 
01053                         if( $block->newLoad( $vagueTarget ) ){
01054                                 return $block;
01055                         }
01056                 }
01057                 return null;
01058         }
01059 
01068         public static function parseTarget( $target ) {
01069                 $target = trim( $target );
01070 
01071                 # We may have been through this before
01072                 if( $target instanceof User ){
01073                         if( IP::isValid( $target->getName() ) ){
01074                                 return array( $target, self::TYPE_IP );
01075                         } else {
01076                                 return array( $target, self::TYPE_USER );
01077                         }
01078                 } elseif( $target === null ){
01079                         return array( null, null );
01080                 }
01081 
01082                 if ( IP::isValid( $target ) ) {
01083                         # We can still create a User if it's an IP address, but we need to turn
01084                         # off validation checking (which would exclude IP addresses)
01085                         return array(
01086                                 User::newFromName( IP::sanitizeIP( $target ), false ),
01087                                 Block::TYPE_IP
01088                         );
01089 
01090                 } elseif ( IP::isValidBlock( $target ) ) {
01091                         # Can't create a User from an IP range
01092                         return array( IP::sanitizeRange( $target ), Block::TYPE_RANGE );
01093                 }
01094 
01095                 # Consider the possibility that this is not a username at all
01096                 # but actually an old subpage (bug #29797)
01097                 if( strpos( $target, '/' ) !== false ){
01098                         # An old subpage, drill down to the user behind it
01099                         $parts = explode( '/', $target );
01100                         $target = $parts[0];
01101                 }
01102 
01103                 $userObj = User::newFromName( $target );
01104                 if ( $userObj instanceof User ) {
01105                         # Note that since numbers are valid usernames, a $target of "12345" will be
01106                         # considered a User.  If you want to pass a block ID, prepend a hash "#12345",
01107                         # since hash characters are not valid in usernames or titles generally.
01108                         return array( $userObj, Block::TYPE_USER );
01109 
01110                 } elseif ( preg_match( '/^#\d+$/', $target ) ) {
01111                         # Autoblock reference in the form "#12345"
01112                         return array( substr( $target, 1 ), Block::TYPE_AUTO );
01113 
01114                 } else {
01115                         # WTF?
01116                         return array( null, null );
01117                 }
01118         }
01119 
01124         public function getType() {
01125                 return $this->mAuto
01126                         ? self::TYPE_AUTO
01127                         : $this->type;
01128         }
01129 
01137         public function getTargetAndType() {
01138                 return array( $this->getTarget(), $this->getType() );
01139         }
01140 
01147         public function getTarget() {
01148                 return $this->target;
01149         }
01150 
01156         public function getExpiry() {
01157                 return $this->mExpiry;
01158         }
01159 
01164         public function setTarget( $target ){
01165                 list( $this->target, $this->type ) = self::parseTarget( $target );
01166         }
01167 
01172         public function getBlocker(){
01173                 return $this->blocker;
01174         }
01175 
01180         public function setBlocker( $user ){
01181                 $this->blocker = $user;
01182         }
01183 }