diff options
Diffstat (limited to 'includes/Block.php')
-rw-r--r-- | includes/Block.php | 185 |
1 files changed, 102 insertions, 83 deletions
diff --git a/includes/Block.php b/includes/Block.php index a44941f1..187ff2db 100644 --- a/includes/Block.php +++ b/includes/Block.php @@ -34,7 +34,7 @@ class Block { $this->mUser = $user; $this->mBy = $by; $this->mReason = $reason; - $this->mTimestamp = wfTimestamp(TS_MW,$timestamp); + $this->mTimestamp = wfTimestamp( TS_MW, $timestamp ); $this->mAuto = $auto; $this->mAnonOnly = $anonOnly; $this->mCreateAccount = $createAccount; @@ -54,7 +54,7 @@ class Block { * Load a block from the database, using either the IP address or * user ID. Tries the user ID first, and if that doesn't work, tries * the address. - * + * * @param $address String: IP address of user/anon * @param $user Integer: user id of user * @param $killExpired Boolean: delete expired blocks on load @@ -87,14 +87,14 @@ class Block { return null; } } - + /** * Check if two blocks are effectively equal * * @return Boolean */ public function equals( Block $block ) { - return ( + return ( $this->mAddress == $block->mAddress && $this->mUser == $block->mUser && $this->mAuto == $block->mAuto @@ -130,9 +130,10 @@ class Block { */ protected function &getDBOptions( &$options ) { global $wgAntiLockFlags; + if ( $this->mForUpdate || $this->mFromMaster ) { $db = wfGetDB( DB_MASTER ); - if ( !$this->mForUpdate || ($wgAntiLockFlags & ALF_NO_BLOCK_LOCK) ) { + if ( !$this->mForUpdate || ( $wgAntiLockFlags & ALF_NO_BLOCK_LOCK ) ) { $options = array(); } else { $options = array( 'FOR UPDATE' ); @@ -180,12 +181,13 @@ class Block { if ( $address ) { $conds = array( 'ipb_address' => $address, 'ipb_auto' => 0 ); $res = $db->resultObject( $db->select( 'ipblocks', '*', $conds, __METHOD__, $options ) ); + if ( $this->loadFromResult( $res, $killExpired ) ) { if ( $user && $this->mAnonOnly ) { # Block is marked anon-only # Whitelist this IP address against autoblocks and range blocks # (but not account creation blocks -- bug 13611) - if( !$this->mCreateAccount ) { + if ( !$this->mCreateAccount ) { $this->clear(); } return false; @@ -199,7 +201,7 @@ class Block { if ( $this->loadRange( $address, $killExpired, $user ) ) { if ( $user && $this->mAnonOnly ) { # Respect account creation blocks on logged-in users -- bug 13611 - if( !$this->mCreateAccount ) { + if ( !$this->mCreateAccount ) { $this->clear(); } return false; @@ -211,10 +213,13 @@ class Block { # Try autoblock if ( $address ) { $conds = array( 'ipb_address' => $address, 'ipb_auto' => 1 ); + if ( $user ) { $conds['ipb_anon_only'] = 0; } + $res = $db->resultObject( $db->select( 'ipblocks', '*', $conds, __METHOD__, $options ) ); + if ( $this->loadFromResult( $res, $killExpired ) ) { return true; } @@ -234,6 +239,7 @@ class Block { */ protected function loadFromResult( ResultWrapper $res, $killExpired = true ) { $ret = false; + if ( 0 != $res->numRows() ) { # Get first block $row = $res->fetchObject(); @@ -274,6 +280,7 @@ class Block { */ public function loadRange( $address, $killExpired = true, $user = 0 ) { $iaddr = IP::toHex( $address ); + if ( $iaddr === false ) { # Invalid address return false; @@ -286,7 +293,7 @@ class Block { $options = array(); $db =& $this->getDBOptions( $options ); $conds = array( - "ipb_range_start LIKE '$range%'", + 'ipb_range_start' . $db->buildLike( $range, $db->anyString() ), "ipb_range_start <= '$iaddr'", "ipb_range_end >= '$iaddr'" ); @@ -309,7 +316,7 @@ class Block { public function initFromRow( $row ) { $this->mAddress = $row->ipb_address; $this->mReason = $row->ipb_reason; - $this->mTimestamp = wfTimestamp(TS_MW,$row->ipb_timestamp); + $this->mTimestamp = wfTimestamp( TS_MW, $row->ipb_timestamp ); $this->mUser = $row->ipb_user; $this->mBy = $row->ipb_by; $this->mAuto = $row->ipb_auto; @@ -321,17 +328,19 @@ class Block { $this->mHideName = $row->ipb_deleted; $this->mId = $row->ipb_id; $this->mExpiry = self::decodeExpiry( $row->ipb_expiry ); + if ( isset( $row->user_name ) ) { $this->mByName = $row->user_name; } else { $this->mByName = $row->ipb_by_text; } + $this->mRangeStart = $row->ipb_range_start; $this->mRangeEnd = $row->ipb_range_end; } /** - * Once $mAddress has been set, get the range they came from. + * Once $mAddress has been set, get the range they came from. * Wrapper for IP::parseRange */ protected function initialiseRange() { @@ -352,6 +361,7 @@ class Block { if ( wfReadOnly() ) { return false; } + if ( !$this->mId ) { throw new MWException( "Block::delete() now requires that the mId member be filled\n" ); } @@ -377,8 +387,9 @@ class Block { # Don't collide with expired blocks Block::purgeExpired(); - $ipb_id = $dbw->nextSequenceValue('ipblocks_ipb_id_val'); - $dbw->insert( 'ipblocks', + $ipb_id = $dbw->nextSequenceValue( 'ipblocks_ipb_id_seq' ); + $dbw->insert( + 'ipblocks', array( 'ipb_id' => $ipb_id, 'ipb_address' => $this->mAddress, @@ -386,7 +397,7 @@ class Block { 'ipb_by' => $this->mBy, 'ipb_by_text' => $this->mByName, 'ipb_reason' => $this->mReason, - 'ipb_timestamp' => $dbw->timestamp($this->mTimestamp), + 'ipb_timestamp' => $dbw->timestamp( $this->mTimestamp ), 'ipb_auto' => $this->mAuto, 'ipb_anon_only' => $this->mAnonOnly, 'ipb_create_account' => $this->mCreateAccount, @@ -394,14 +405,16 @@ class Block { 'ipb_expiry' => self::encodeExpiry( $this->mExpiry, $dbw ), 'ipb_range_start' => $this->mRangeStart, 'ipb_range_end' => $this->mRangeEnd, - 'ipb_deleted' => $this->mHideName, + 'ipb_deleted' => intval( $this->mHideName ), // typecast required for SQLite 'ipb_block_email' => $this->mBlockEmail, 'ipb_allow_usertalk' => $this->mAllowUsertalk - ), 'Block::insert', array( 'IGNORE' ) + ), + 'Block::insert', + array( 'IGNORE' ) ); $affected = $dbw->affectedRows(); - if ($affected) + if ( $affected ) $this->doRetroactiveAutoblock(); return (bool)$affected; @@ -417,13 +430,14 @@ class Block { $this->validateBlockParams(); - $dbw->update( 'ipblocks', + $dbw->update( + 'ipblocks', array( 'ipb_user' => $this->mUser, 'ipb_by' => $this->mBy, 'ipb_by_text' => $this->mByName, 'ipb_reason' => $this->mReason, - 'ipb_timestamp' => $dbw->timestamp($this->mTimestamp), + 'ipb_timestamp' => $dbw->timestamp( $this->mTimestamp ), 'ipb_auto' => $this->mAuto, 'ipb_anon_only' => $this->mAnonOnly, 'ipb_create_account' => $this->mCreateAccount, @@ -433,13 +447,15 @@ class Block { 'ipb_range_end' => $this->mRangeEnd, 'ipb_deleted' => $this->mHideName, 'ipb_block_email' => $this->mBlockEmail, - 'ipb_allow_usertalk' => $this->mAllowUsertalk ), + 'ipb_allow_usertalk' => $this->mAllowUsertalk + ), array( 'ipb_id' => $this->mId ), - 'Block::update' ); + 'Block::update' + ); return $dbw->affectedRows(); } - + /** * Make sure all the proper members are set to sane values * before adding/updating a block @@ -453,11 +469,14 @@ class Block { # Unset ipb_enable_autoblock for IP blocks, makes no sense if ( !$this->mUser ) { $this->mEnableAutoblock = 0; - $this->mBlockEmail = 0; //Same goes for email... } - if( !$this->mByName ) { - if( $this->mBy ) { + # bug 18860: non-anon-only IP blocks should be allowed to block email + if ( !$this->mUser && $this->mAnonOnly ) { + $this->mBlockEmail = 0; + } + if ( !$this->mByName ) { + if ( $this->mBy ) { $this->mByName = User::whoIs( $this->mBy ); } else { global $wgUser; @@ -465,28 +484,27 @@ class Block { } } } - - + /** - * Retroactively autoblocks the last IP used by the user (if it is a user) - * blocked by this Block. - * - * @return Boolean: whether or not a retroactive autoblock was made. - */ + * Retroactively autoblocks the last IP used by the user (if it is a user) + * blocked by this Block. + * + * @return Boolean: whether or not a retroactive autoblock was made. + */ public function doRetroactiveAutoblock() { $dbr = wfGetDB( DB_SLAVE ); - #If autoblock is enabled, autoblock the LAST IP used + # If autoblock is enabled, autoblock the LAST IP used # - stolen shamelessly from CheckUser_body.php - if ($this->mEnableAutoblock && $this->mUser) { - wfDebug("Doing retroactive autoblocks for " . $this->mAddress . "\n"); - + if ( $this->mEnableAutoblock && $this->mUser ) { + wfDebug( "Doing retroactive autoblocks for " . $this->mAddress . "\n" ); + $options = array( 'ORDER BY' => 'rc_timestamp DESC' ); $conds = array( 'rc_user_text' => $this->mAddress ); - - if ($this->mAngryAutoblock) { + + if ( $this->mAngryAutoblock ) { // Block any IP used in the last 7 days. Up to five IPs. - $conds[] = 'rc_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( time() - (7*86400) ) ); + $conds[] = 'rc_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( time() - ( 7 * 86400 ) ) ); $options['LIMIT'] = 5; } else { // Just the last IP used. @@ -494,11 +512,11 @@ class Block { } $res = $dbr->select( 'recentchanges', array( 'rc_ip' ), $conds, - __METHOD__ , $options); + __METHOD__ , $options ); if ( !$dbr->numRows( $res ) ) { - #No results, don't autoblock anything - wfDebug("No IP found to retroactively autoblock\n"); + # No results, don't autoblock anything + wfDebug( "No IP found to retroactively autoblock\n" ); } else { while ( $row = $dbr->fetchObject( $res ) ) { if ( $row->rc_ip ) @@ -507,7 +525,7 @@ class Block { } } } - + /** * Checks whether a given IP is on the autoblock whitelist. * @@ -516,7 +534,7 @@ class Block { */ public static function isWhitelistedFromAutoblocks( $ip ) { global $wgMemc; - + // Try to get the autoblock_whitelist from the cache, as it's faster // than getting the msg raw and explode()'ing it. $key = wfMemcKey( 'ipb', 'autoblock', 'whitelist' ); @@ -526,28 +544,28 @@ class Block { $wgMemc->set( $key, $lines, 3600 * 24 ); } - wfDebug("Checking the autoblock whitelist..\n"); + wfDebug( "Checking the autoblock whitelist..\n" ); - foreach( $lines as $line ) { + foreach ( $lines as $line ) { # List items only if ( substr( $line, 0, 1 ) !== '*' ) { continue; } - $wlEntry = substr($line, 1); - $wlEntry = trim($wlEntry); + $wlEntry = substr( $line, 1 ); + $wlEntry = trim( $wlEntry ); - wfDebug("Checking $ip against $wlEntry..."); + wfDebug( "Checking $ip against $wlEntry..." ); # Is the IP in this range? - if (IP::isInRange( $ip, $wlEntry )) { - wfDebug(" IP $ip matches $wlEntry, not autoblocking\n"); + if ( IP::isInRange( $ip, $wlEntry ) ) { + wfDebug( " IP $ip matches $wlEntry, not autoblocking\n" ); return true; } else { wfDebug( " No match\n" ); } } - + return false; } @@ -565,12 +583,12 @@ class Block { } # Check for presence on the autoblock whitelist - if (Block::isWhitelistedFromAutoblocks($autoblockIP)) { + if ( Block::isWhitelistedFromAutoblocks( $autoblockIP ) ) { return; } - - ## Allow hooks to cancel the autoblock. - if (!wfRunHooks( 'AbortAutoblock', array( $autoblockIP, &$this ) )) { + + # # Allow hooks to cancel the autoblock. + if ( !wfRunHooks( 'AbortAutoblock', array( $autoblockIP, &$this ) ) ) { wfDebug( "Autoblock aborted by hook.\n" ); return false; } @@ -582,8 +600,8 @@ class Block { # If the user is already blocked. Then check if the autoblock would # exceed the user block. If it would exceed, then do nothing, else # prolong block time - if ($this->mExpiry && - ($this->mExpiry < Block::getAutoblockExpiry($ipblock->mTimestamp))) { + if ( $this->mExpiry && + ( $this->mExpiry < Block::getAutoblockExpiry( $ipblock->mTimestamp ) ) ) { return; } # Just update the timestamp @@ -610,8 +628,8 @@ class Block { $ipblock->mAllowUsertalk = $this->mAllowUsertalk; # If the user is already blocked with an expiry date, we don't # want to pile on top of that! - if($this->mExpiry) { - $ipblock->mExpiry = min ( $this->mExpiry, Block::getAutoblockExpiry( $this->mTimestamp )); + if ( $this->mExpiry ) { + $ipblock->mExpiry = min( $this->mExpiry, Block::getAutoblockExpiry( $this->mTimestamp ) ); } else { $ipblock->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp ); } @@ -624,8 +642,7 @@ class Block { * @return Boolean */ public function deleteIfExpired() { - $fname = 'Block::deleteIfExpired'; - wfProfileIn( $fname ); + wfProfileIn( __METHOD__ ); if ( $this->isExpired() ) { wfDebug( "Block::deleteIfExpired() -- deleting\n" ); $this->delete(); @@ -634,7 +651,7 @@ class Block { wfDebug( "Block::deleteIfExpired() -- not expired\n" ); $retVal = false; } - wfProfileOut( $fname ); + wfProfileOut( __METHOD__ ); return $retVal; } @@ -660,7 +677,7 @@ class Block { } /** - * Update the timestamp on autoblocks. + * Update the timestamp on autoblocks. */ public function updateTimestamp() { if ( $this->mAuto ) { @@ -670,8 +687,8 @@ class Block { $dbw = wfGetDB( DB_MASTER ); $dbw->update( 'ipblocks', array( /* SET */ - 'ipb_timestamp' => $dbw->timestamp($this->mTimestamp), - 'ipb_expiry' => $dbw->timestamp($this->mExpiry), + 'ipb_timestamp' => $dbw->timestamp( $this->mTimestamp ), + 'ipb_expiry' => $dbw->timestamp( $this->mExpiry ), ), array( /* WHERE */ 'ipb_address' => $this->mAddress ), 'Block::updateTimestamp' @@ -700,14 +717,14 @@ class Block { /** * Get/set the SELECT ... FOR UPDATE flag */ - public function forUpdate( $x = NULL ) { + public function forUpdate( $x = null ) { return wfSetVar( $this->mForUpdate, $x ); } /** * Get/set a flag determining whether the master is used for reads */ - public function fromMaster( $x = NULL ) { + public function fromMaster( $x = null ) { return wfSetVar( $this->mFromMaster, $x ); } @@ -726,7 +743,7 @@ class Block { /** * Encode expiry for DB * - * @param $expiry String: timestamp for expiry, or + * @param $expiry String: timestamp for expiry, or * @param $db Database object * @return String */ @@ -773,10 +790,10 @@ class Block { $parts = explode( '/', $range ); if ( count( $parts ) == 2 ) { // IPv6 - if ( IP::isIPv6($range) && $parts[1] >= 64 && $parts[1] <= 128 ) { + if ( IP::isIPv6( $range ) && $parts[1] >= 64 && $parts[1] <= 128 ) { $bits = $parts[1]; $ipint = IP::toUnsigned6( $parts[0] ); - # Native 32 bit functions WONT work here!!! + # Native 32 bit functions WON'T work here!!! # Convert to a padded binary number $network = wfBaseConvert( $ipint, 10, 2, 128 ); # Truncate the last (128-$bits) bits and replace them with zeros @@ -787,7 +804,7 @@ class Block { $newip = IP::toOctet( $network ); $range = "$newip/{$parts[1]}"; } // IPv4 - else if ( IP::isIPv4($range) && $parts[1] >= 16 && $parts[1] <= 32 ) { + elseif ( IP::isIPv4( $range ) && $parts[1] >= 16 && $parts[1] <= 32 ) { $shift = 32 - $parts[1]; $ipint = IP::toUnsigned( $parts[0] ); $ipint = $ipint >> $shift << $shift; @@ -808,7 +825,7 @@ class Block { /** * Get a value to insert into expiry field of the database when infinite expiry - * is desired. In principle this could be DBMS-dependant, but currently all + * is desired. In principle this could be DBMS-dependant, but currently all * supported DBMS's support the string "infinity", so we just use that. * * @return String @@ -818,35 +835,36 @@ class Block { # works with CHAR(14) as well because "i" sorts after all numbers. return 'infinity'; } - + /** * Convert a DB-encoded expiry into a real string that humans can read. * * @param $encoded_expiry String: Database encoded expiry time - * @return String + * @return Html-escaped String */ public static function formatExpiry( $encoded_expiry ) { static $msg = null; - - if( is_null( $msg ) ) { + + if ( is_null( $msg ) ) { $msg = array(); $keys = array( 'infiniteblock', 'expiringblock' ); - foreach( $keys as $key ) { + foreach ( $keys as $key ) { $msg[$key] = wfMsgHtml( $key ); } } - + $expiry = Block::decodeExpiry( $encoded_expiry ); - if ($expiry == 'infinity') { + if ( $expiry == 'infinity' ) { $expirystr = $msg['infiniteblock']; } else { global $wgLang; - $expiretimestr = $wgLang->timeanddate( $expiry, true ); - $expirystr = wfMsgReplaceArgs( $msg['expiringblock'], array($expiretimestr) ); + $expiredatestr = htmlspecialchars( $wgLang->date( $expiry, true ) ); + $expiretimestr = htmlspecialchars( $wgLang->time( $expiry, true ) ); + $expirystr = wfMsgReplaceArgs( $msg['expiringblock'], array( $expiredatestr, $expiretimestr ) ); } return $expirystr; } - + /** * Convert a typed-in expiry time into something we can put into the database. * @param $expiry_input String: whatever was typed into the form @@ -857,7 +875,8 @@ class Block { $expiry = 'infinity'; } else { $expiry = strtotime( $expiry_input ); - if ($expiry < 0 || $expiry === false) { + + if ( $expiry < 0 || $expiry === false ) { return false; } } |