* @file
*/
class Block {
- /* public*/ var $mReason, $mTimestamp, $mAuto, $mExpiry, $mHideName, $mAngryAutoblock;
+ /* public*/ var $mReason, $mTimestamp, $mAuto, $mExpiry, $mHideName;
protected
$mId,
$mBlockEmail,
$mDisableUsertalk,
- $mCreateAccount;
+ $mCreateAccount,
+ $mParentBlockId;
/// @var User|String
protected $target;
+ // @var Integer Hack for foreign blocking (CentralAuth)
+ protected $forcedTargetID;
+
/// @var Block::TYPE_ constant. Can only be USER, IP or RANGE internally
protected $type;
*/
function __construct( $address = '', $user = 0, $by = 0, $reason = '',
$timestamp = 0, $auto = 0, $expiry = '', $anonOnly = 0, $createAccount = 0, $enableAutoblock = 0,
- $hideName = 0, $blockEmail = 0, $allowUsertalk = 0 )
+ $hideName = 0, $blockEmail = 0, $allowUsertalk = 0, $byText = '' )
{
if( $timestamp === 0 ){
$timestamp = wfTimestampNow();
}
$this->setTarget( $address );
- $this->setBlocker( User::newFromID( $by ) );
+ if ( $this->target instanceof User && $user ) {
+ $this->forcedTargetID = $user; // needed for foreign users
+ }
+ if ( $by ) { // local user
+ $this->setBlocker( User::newFromID( $by ) );
+ } else { // foreign user
+ $this->setBlocker( $byText );
+ }
$this->mReason = $reason;
$this->mTimestamp = wfTimestamp( TS_MW, $timestamp );
$this->mAuto = $auto;
$this->isHardblock( !$anonOnly );
$this->prevents( 'createaccount', $createAccount );
- $this->mExpiry = $expiry;
+ if ( $expiry == 'infinity' || $expiry == wfGetDB( DB_SLAVE )->getInfinity() ) {
+ $this->mExpiry = 'infinity';
+ } else {
+ $this->mExpiry = wfTimestamp( TS_MW, $expiry );
+ }
$this->isAutoblocking( $enableAutoblock );
$this->mHideName = $hideName;
$this->prevents( 'sendemail', $blockEmail );
$this->prevents( 'editownusertalk', !$allowUsertalk );
$this->mFromMaster = false;
- $this->mAngryAutoblock = false;
}
/**
* @deprecated since 1.18
*/
public static function newFromDB( $address, $user = 0 ) {
+ wfDeprecated( __METHOD__, '1.18' );
return self::newFromTarget( User::whoIs( $user ), $address );
}
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->selectRow(
'ipblocks',
- '*',
+ self::selectFields(),
array( 'ipb_id' => $id ),
__METHOD__
);
if ( $res ) {
- return Block::newFromRow( $res );
+ return self::newFromRow( $res );
} else {
return null;
}
}
+ /**
+ * Return the list of ipblocks fields that should be selected to create
+ * a new block.
+ * @return array
+ */
+ public static function selectFields() {
+ return array(
+ 'ipb_id',
+ 'ipb_address',
+ 'ipb_by',
+ 'ipb_by_text',
+ 'ipb_reason',
+ 'ipb_timestamp',
+ 'ipb_auto',
+ 'ipb_anon_only',
+ 'ipb_create_account',
+ 'ipb_enable_autoblock',
+ 'ipb_expiry',
+ 'ipb_deleted',
+ 'ipb_block_email',
+ 'ipb_allow_usertalk',
+ 'ipb_parent_block_id',
+ );
+ }
+
/**
* Check if two blocks are effectively equal. Doesn't check irrelevant things like
* the blocking user or the block timestamp, only things which affect the blocked user *
* @deprecated since 1.18
*/
public function clear() {
+ wfDeprecated( __METHOD__, '1.18' );
# Noop
}
* @deprecated since 1.18
*/
public function load( $address = '', $user = 0 ) {
- wfDeprecated( __METHOD__ );
+ wfDeprecated( __METHOD__, '1.18' );
if( $user ){
$username = User::whoIs( $user );
$block = self::newFromTarget( $username, $address );
}
}
- $res = $db->select( 'ipblocks', '*', $conds, __METHOD__ );
+ $res = $db->select( 'ipblocks', self::selectFields(), $conds, __METHOD__ );
# This result could contain a block on the user, a block on the IP, and a russian-doll
# set of rangeblocks. We want to choose the most specific one, so keep a leader board.
$bestBlockPreventsEdit = null;
foreach( $res as $row ){
- $block = Block::newFromRow( $row );
+ $block = self::newFromRow( $row );
# Don't use expired blocks
if( $block->deleteIfExpired() ){
*/
protected function initFromRow( $row ) {
$this->setTarget( $row->ipb_address );
- $this->setBlocker( User::newFromId( $row->ipb_by ) );
+ if ( $row->ipb_by ) { // local user
+ $this->setBlocker( User::newFromID( $row->ipb_by ) );
+ } else { // foreign user
+ $this->setBlocker( $row->ipb_by_text );
+ }
$this->mReason = $row->ipb_reason;
$this->mTimestamp = wfTimestamp( TS_MW, $row->ipb_timestamp );
$this->mAuto = $row->ipb_auto;
$this->mHideName = $row->ipb_deleted;
$this->mId = $row->ipb_id;
- $this->mExpiry = $row->ipb_expiry;
+ $this->mParentBlockId = $row->ipb_parent_block_id;
+
+ // I wish I didn't have to do this
+ $db = wfGetDB( DB_SLAVE );
+ if ( $row->ipb_expiry == $db->getInfinity() ) {
+ $this->mExpiry = 'infinity';
+ } else {
+ $this->mExpiry = wfTimestamp( TS_MW, $row->ipb_expiry );
+ }
$this->isHardblock( !$row->ipb_anon_only );
$this->isAutoblocking( $row->ipb_enable_autoblock );
}
$dbw = wfGetDB( DB_MASTER );
+ $dbw->delete( 'ipblocks', array( 'ipb_parent_block_id' => $this->getId() ), __METHOD__ );
$dbw->delete( 'ipblocks', array( 'ipb_id' => $this->getId() ), __METHOD__ );
return $dbw->affectedRows() > 0;
# Don't collide with expired blocks
Block::purgeExpired();
- $ipb_id = $dbw->nextSequenceValue( 'ipblocks_ipb_id_seq' );
+ $row = $this->getDatabaseArray();
+ $row['ipb_id'] = $dbw->nextSequenceValue("ipblocks_ipb_id_seq");
+
$dbw->insert(
'ipblocks',
- $this->getDatabaseArray(),
+ $row,
__METHOD__,
array( 'IGNORE' )
);
if( !$db ){
$db = wfGetDB( DB_SLAVE );
}
- $this->mExpiry = $db->encodeExpiry( $this->mExpiry );
+ $expiry = $db->encodeExpiry( $this->mExpiry );
+
+ if ( $this->forcedTargetID ) {
+ $uid = $this->forcedTargetID;
+ } else {
+ $uid = $this->target instanceof User ? $this->target->getID() : 0;
+ }
$a = array(
'ipb_address' => (string)$this->target,
- 'ipb_user' => $this->target instanceof User ? $this->target->getID() : 0,
- 'ipb_by' => $this->getBlocker()->getId(),
- 'ipb_by_text' => $this->getBlocker()->getName(),
+ 'ipb_user' => $uid,
+ 'ipb_by' => $this->getBy(),
+ 'ipb_by_text' => $this->getByName(),
'ipb_reason' => $this->mReason,
'ipb_timestamp' => $db->timestamp( $this->mTimestamp ),
'ipb_auto' => $this->mAuto,
'ipb_anon_only' => !$this->isHardblock(),
'ipb_create_account' => $this->prevents( 'createaccount' ),
'ipb_enable_autoblock' => $this->isAutoblocking(),
- 'ipb_expiry' => $this->mExpiry,
+ 'ipb_expiry' => $expiry,
'ipb_range_start' => $this->getRangeStart(),
'ipb_range_end' => $this->getRangeEnd(),
'ipb_deleted' => intval( $this->mHideName ), // typecast required for SQLite
'ipb_block_email' => $this->prevents( 'sendemail' ),
- 'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' )
+ 'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' ),
+ 'ipb_parent_block_id' => $this->mParentBlockId
);
return $a;
*/
protected function doRetroactiveAutoblock() {
$blockIds = array();
-
- $dbr = wfGetDB( DB_SLAVE );
- # If autoblock is enabled, autoblock the LAST IP used
- # - stolen shamelessly from CheckUser_body.php
-
+ # If autoblock is enabled, autoblock the LAST IP(s) used
if ( $this->isAutoblocking() && $this->getType() == self::TYPE_USER ) {
wfDebug( "Doing retroactive autoblocks for " . $this->getTarget() . "\n" );
- $options = array( 'ORDER BY' => 'rc_timestamp DESC' );
- $conds = array( 'rc_user_text' => (string)$this->getTarget() );
+ $continue = wfRunHooks(
+ 'PerformRetroactiveAutoblock', array( $this, &$blockIds ) );
- 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 ) ) );
- $options['LIMIT'] = 5;
- } else {
- // Just the last IP used.
- $options['LIMIT'] = 1;
+ if ( $continue ) {
+ self::defaultRetroactiveAutoblock( $this, $blockIds );
}
+ }
+ return $blockIds;
+ }
- $res = $dbr->select( 'recentchanges', array( 'rc_ip' ), $conds,
- __METHOD__ , $options );
+ /**
+ * Retroactively autoblocks the last IP used by the user (if it is a user)
+ * blocked by this Block. This will use the recentchanges table.
+ *
+ * @param Block $block
+ * @param Array &$blockIds
+ * @return Array: block IDs of retroactive autoblocks made
+ */
+ protected static function defaultRetroactiveAutoblock( Block $block, array &$blockIds ) {
+ $dbr = wfGetDB( DB_SLAVE );
- if ( !$dbr->numRows( $res ) ) {
- # No results, don't autoblock anything
- wfDebug( "No IP found to retroactively autoblock\n" );
- } else {
- foreach ( $res as $row ) {
- if ( $row->rc_ip ) {
- $id = $this->doAutoblock( $row->rc_ip );
- if ( $id ) $blockIds[] = $id;
- }
+ $options = array( 'ORDER BY' => 'rc_timestamp DESC' );
+ $conds = array( 'rc_user_text' => (string)$block->getTarget() );
+
+ // Just the last IP used.
+ $options['LIMIT'] = 1;
+
+ $res = $dbr->select( 'recentchanges', array( 'rc_ip' ), $conds,
+ __METHOD__ , $options );
+
+ if ( !$dbr->numRows( $res ) ) {
+ # No results, don't autoblock anything
+ wfDebug( "No IP found to retroactively autoblock\n" );
+ } else {
+ foreach ( $res as $row ) {
+ if ( $row->rc_ip ) {
+ $id = $block->doAutoblock( $row->rc_ip );
+ if ( $id ) $blockIds[] = $id;
}
}
}
- return $blockIds;
}
/**
# Continue suppressing the name if needed
$autoblock->mHideName = $this->mHideName;
$autoblock->prevents( 'editownusertalk', $this->prevents( 'editownusertalk' ) );
+ $autoblock->mParentBlockId = $this->mId;
- $dbr = wfGetDB( DB_SLAVE );
- if ( $this->mExpiry == $dbr->getInfinity() ) {
+ if ( $this->mExpiry == 'infinity' ) {
# Original block was indefinite, start an autoblock now
$autoblock->mExpiry = Block::getAutoblockExpiry( $timestamp );
} else {
/**
* Get the user id of the blocking sysop
*
- * @return Integer
+ * @return Integer (0 for foreign users)
*/
public function getBy() {
- return $this->getBlocker() instanceof User
- ? $this->getBlocker()->getId()
+ $blocker = $this->getBlocker();
+ return ( $blocker instanceof User )
+ ? $blocker->getId()
: 0;
}
* @return String
*/
public function getByName() {
- return $this->getBlocker() instanceof User
- ? $this->getBlocker()->getName()
- : null;
+ $blocker = $this->getBlocker();
+ return ( $blocker instanceof User )
+ ? $blocker->getName()
+ : (string)$blocker; // username
}
/**
* @param $x Bool
*/
public function forUpdate( $x = null ) {
+ wfDeprecated( __METHOD__, '1.18' );
# noop
}
* Encode expiry for DB
*
* @param $expiry String: timestamp for expiry, or
- * @param $db Database object
+ * @param $db DatabaseBase object
* @return String
* @deprecated since 1.18; use $dbw->encodeExpiry() instead
*/
public static function encodeExpiry( $expiry, $db ) {
+ wfDeprecated( __METHOD__, '1.18' );
return $db->encodeExpiry( $expiry );
}
* @param $expiry String: Database expiry format
* @param $timestampType Int Requested timestamp format
* @return String
- * @deprecated since 1.18; use $wgLang->decodeExpiry() instead
+ * @deprecated since 1.18; use $wgLang->formatExpiry() instead
*/
public static function decodeExpiry( $expiry, $timestampType = TS_MW ) {
+ wfDeprecated( __METHOD__, '1.18' );
global $wgContLang;
return $wgContLang->formatExpiry( $expiry, $timestampType );
}
* @deprecated since 1.18, call IP::sanitizeRange() directly
*/
public static function normaliseRange( $range ) {
+ wfDeprecated( __METHOD__, '1.18' );
return IP::sanitizeRange( $range );
}
*/
public static function purgeExpired() {
$dbw = wfGetDB( DB_MASTER );
- $dbw->delete( 'ipblocks', array( 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), __METHOD__ );
+ $dbw->delete( 'ipblocks',
+ array( 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), __METHOD__ );
}
/**
* @return String
*/
public static function infinity() {
+ wfDeprecated( __METHOD__, '1.18' );
return wfGetDB( DB_SLAVE )->getInfinity();
}
* @deprecated since 1.18; use $wgLang->formatExpiry() instead
*/
public static function formatExpiry( $encoded_expiry ) {
+ wfDeprecated( __METHOD__, '1.18' );
+
global $wgContLang;
static $msg = null;
* @deprecated since 1.18 moved to SpecialBlock::parseExpiryInput()
*/
public static function parseExpiryInput( $expiry ) {
- wfDeprecated( __METHOD__ );
+ wfDeprecated( __METHOD__, '1.18' );
return SpecialBlock::parseExpiryInput( $expiry );
}
# passed by some callers (bug 29116)
return null;
- } elseif( in_array( $type, array( Block::TYPE_USER, Block::TYPE_IP, Block::TYPE_RANGE, null ) ) ) {
+ } elseif( in_array( $type, array( Block::TYPE_USER, Block::TYPE_IP, Block::TYPE_RANGE ) ) ) {
$block = new Block();
$block->fromMaster( $fromMaster );
if( $block->newLoad( $vagueTarget ) ){
return $block;
- } else {
- return null;
}
- } else {
- return null;
}
+ return null;
}
/**
* @return array( User|String, Block::TYPE_ constant )
*/
public static function parseTarget( $target ) {
- $target = trim( $target );
-
# We may have been through this before
if( $target instanceof User ){
if( IP::isValid( $target->getName() ) ){
return array( null, null );
}
+ $target = trim( $target );
+
+ if ( IP::isValid( $target ) ) {
+ # We can still create a User if it's an IP address, but we need to turn
+ # off validation checking (which would exclude IP addresses)
+ return array(
+ User::newFromName( IP::sanitizeIP( $target ), false ),
+ Block::TYPE_IP
+ );
+
+ } elseif ( IP::isValidBlock( $target ) ) {
+ # Can't create a User from an IP range
+ return array( IP::sanitizeRange( $target ), Block::TYPE_RANGE );
+ }
+
# Consider the possibility that this is not a username at all
# but actually an old subpage (bug #29797)
if( strpos( $target, '/' ) !== false ){
# since hash characters are not valid in usernames or titles generally.
return array( $userObj, Block::TYPE_USER );
- } elseif ( IP::isValid( $target ) ) {
- # We can still create a User if it's an IP address, but we need to turn
- # off validation checking (which would exclude IP addresses)
- return array(
- User::newFromName( IP::sanitizeIP( $target ), false ),
- Block::TYPE_IP
- );
-
- } elseif ( IP::isValidBlock( $target ) ) {
- # Can't create a User from an IP range
- return array( IP::sanitizeRange( $target ), Block::TYPE_RANGE );
-
} elseif ( preg_match( '/^#\d+$/', $target ) ) {
# Autoblock reference in the form "#12345"
return array( substr( $target, 1 ), Block::TYPE_AUTO );
return $this->target;
}
+ /**
+ * @since 1.19
+ *
+ * @return Mixed|string
+ */
+ public function getExpiry() {
+ return $this->mExpiry;
+ }
+
/**
* Set the target for this block, and update $this->type accordingly
* @param $target Mixed
/**
* Get the user who implemented this block
- * @return User
+ * @return User|string Local User object or string for a foreign user
*/
public function getBlocker(){
return $this->blocker;
/**
* Set the user who implemented (or will implement) this block
- * @param $user User
+ * @param $user User|string Local User object or username string for foriegn users
*/
- public function setBlocker( User $user ){
+ public function setBlocker( $user ){
$this->blocker = $user;
}
}