* Implement accessors for isHardblock() and getRangeStart()/getRangeEnd() in the same fashion.
* Make the corresponding variables private, removing external accessors. This required updating AbuseFilter with non-B/C code, so I also implemented the rest of the changes I've made to the blocking backend in that extension.
* Move the "get an IP range which encompasses the given IP/range" logic to Block.php; will be needed later... :D
*/
class Block {
/* public*/ var $mAddress, $mUser, $mBy, $mReason, $mTimestamp, $mAuto, $mId, $mExpiry,
- $mRangeStart, $mRangeEnd, $mAnonOnly, $mEnableAutoblock, $mHideName,
- $mBlockEmail, $mByName, $mAngryAutoblock, $mAllowUsertalk;
- private $mFromMaster;
-
+ $mEnableAutoblock, $mHideName,
+ $mByName, $mAngryAutoblock;
+ private
+ $mFromMaster,
+ $mRangeStart,
+ $mRangeEnd,
+ $mAnonOnly,
+ $mBlockEmail,
+ $mAllowUsertalk,
+ $mCreateAccount;
+
+ /// TYPE constants
const TYPE_USER = 1;
const TYPE_IP = 2;
const TYPE_RANGE = 3;
return false;
}
+ /**
+ * Get a set of SQL conditions which will select rangeblocks encompasing a given range
+ * @param $start String Hexadecimal IP representation
+ * @param $end String Hexadecimal IP represenation, or null to use $start = $end
+ * @return String
+ */
+ public static function getRangeCond( $start, $end = null ){
+ if( $end === null ){
+ $end = $start;
+ }
+ # Per bug 14634, we want to include relevant active rangeblocks; for
+ # rangeblocks, we want to include larger ranges which enclose the given
+ # range. We know that all blocks must be smaller than $wgBlockCIDRLimit,
+ # so we can improve performance by filtering on a LIKE clause
+ $chunk = self::getIpFragment( $start );
+ $dbr = wfGetDB( DB_SLAVE );
+ $like = $dbr->buildLike( $chunk, $dbr->anyString() );
+
+ # Fairly hard to make a malicious SQL statement out of hex characters,
+ # but stranger things have happened...
+ $safeStart = $dbr->addQuotes( $start );
+ $safeEnd = $dbr->addQuotes( $end );
+
+ return $dbr->makeList(
+ array(
+ "ipb_range_start $like",
+ "ipb_range_start <= $safeStart",
+ "ipb_range_end >= $safeEnd",
+ ),
+ LIST_AND
+ );
+ }
+
+ /**
+ * Get the component of an IP address which is certain to be the same between an IP
+ * address and a rangeblock containing that IP address.
+ * @param $hex String Hexadecimal IP representation
+ * @return String
+ */
+ protected static function getIpFragment( $hex ){
+ global $wgBlockCIDRLimit;
+ if( substr( $hex, 0, 3 ) == 'v6-' ){
+ return 'v6-' . substr( substr( $hex, 3 ), 0, floor( $wgBlockCIDRLimit['IPv6'] / 4 ) );
+ } else {
+ return substr( $hex, 0, floor( $wgBlockCIDRLimit['IPv4'] / 4 ) );
+ }
+ }
+
/**
* Fill in member variables from a result wrapper
*
}
}
+ /**
+ * Get the IP address at the start of the range in Hex form
+ * @return String IP in Hex form
+ */
+ public function getRangeStart(){
+ switch( $this->type ){
+ case self::TYPE_USER:
+ return null;
+ case self::TYPE_IP:
+ return IP::toHex( $this->target );
+ case self::TYPE_RANGE:
+ return $this->mRangeStart;
+ default: throw new MWException( "Block with invalid type" );
+ }
+ }
+
+ /**
+ * Get the IP address at the start of the range in Hex form
+ * @return String IP in Hex form
+ */
+ public function getRangeEnd(){
+ switch( $this->type ){
+ case self::TYPE_USER:
+ return null;
+ case self::TYPE_IP:
+ return IP::toHex( $this->target );
+ case self::TYPE_RANGE:
+ return $this->mRangeEnd;
+ default: throw new MWException( "Block with invalid type" );
+ }
+ }
+
/**
* Get the user id of the blocking sysop
*
return wfSetVar( $this->mFromMaster, $x );
}
+ /**
+ * Get/set whether the Block is a hardblock (affects logged-in users on a given IP/range
+ * @param $x Bool
+ * @return Bool
+ */
+ public function isHardblock( $x = null ){
+ $y = $this->mAnonOnly;
+ if( $x !== null){
+ $this->mAnonOnly = !$x;
+ }
+ return !$y;
+ }
+
+ /**
+ * Get/set whether the Block prevents a given action
+ * @param $action String
+ * @param $x Bool
+ * @return Bool
+ */
+ public function prevents( $action, $x = null ){
+ switch( $action ){
+ case 'edit':
+ # TODO Not actually quite this simple (bug 13611 etc)
+ return true;
+
+ case 'createaccount':
+ return wfSetVar( $this->mCreateAccount, $x );
+
+ case 'sendemail':
+ return wfSetVar( $this->mBlockEmail, $x );
+
+ case 'editusertalk':
+ $y = $this->mAllowUsertalk;
+ if( $x !== null){
+ $this->mAllowUsertalk = !$x;
+ }
+ return !$y;
+
+ default:
+ return null;
+ }
+ }
+
/**
* Get the block name, but with autoblocked IPs hidden as per standard privacy policy
* @return String, text is escaped
$this->mBlockedby = $this->mBlock->mByName;
$this->mBlockreason = $this->mBlock->mReason;
$this->mHideName = $this->mBlock->mHideName;
- $this->mAllowUsertalk = $this->mBlock->mAllowUsertalk;
+ $this->mAllowUsertalk = !$this->mBlock->prevents( 'editusertalk' );
if ( $this->isLoggedIn() && $wgUser->getID() == $this->getID() ) {
$this->spreadBlock();
}
*/
function isBlockedFromCreateAccount() {
$this->getBlockedStatus();
- return $this->mBlock && $this->mBlock->mCreateAccount;
+ return $this->mBlock && $this->mBlock->prevents( 'createaccount' );
}
/**
*/
function isBlockedFromEmailuser() {
$this->getBlockedStatus();
- return $this->mBlock && $this->mBlock->mBlockEmail;
+ return $this->mBlock && $this->mBlock->prevents( 'sendemail' );
}
/**
|| $block->mAddress == $this->target ) # or if it is, the range is what we're about to block
)
{
- $fields['HardBlock']['default'] = !$block->mAnonOnly;
- $fields['CreateAccount']['default'] = $block->mCreateAccount;
+ $fields['HardBlock']['default'] = $block->isHardblock();
+ $fields['CreateAccount']['default'] = $block->prevents( 'createaccount' );
$fields['AutoBlock']['default'] = $block->mEnableAutoblock;
if( isset( $fields['DisableEmail'] ) ){
- $fields['DisableEmail']['default'] = $block->mBlockEmail;
+ $fields['DisableEmail']['default'] = $block->prevents( 'sendemail' );
}
if( isset( $fields['HideUser'] ) ){
$fields['HideUser']['default'] = $block->mHideName;
}
if( isset( $fields['DisableUTEdit'] ) ){
- $fields['DisableUTEdit']['default'] = !$block->mAllowUsertalk;
+ $fields['DisableUTEdit']['default'] = $block->prevents( 'editusertalk' );
}
$fields['Reason']['default'] = $block->mReason;
$fields['AlreadyBlocked']['default'] = true;
return array( 'ipb_expiry_invalid' );
}
- if( !$wgBlockAllowsUTEdit ){
- $data['DisableUTEdit'] = true;
- }
-
# If the user has done the form 'properly', they won't even have been given the
# option to suppress-block unless they have the 'hideuser' permission
if( !isset( $data['HideUser'] ) ){
!$data['HardBlock'], # Block anon only
$data['CreateAccount'],
$data['AutoBlock'],
- $data['HideUser'],
- $data['DisableEmail'],
- !$data['DisableUTEdit'] # *Allow* UTEdit
+ $data['HideUser']
);
+
+ $block->prevents( 'editusertalk', ( !$wgBlockAllowsUTEdit || $data['DisableUTEdit'] ) );
+ $block->prevents( 'sendemail', $data['DisableEmail'] );
if( !wfRunHooks( 'BlockIp', array( &$block, &$wgUser ) ) ) {
return array( 'hookaborted' );
# This returns direct blocks before autoblocks/rangeblocks, since we should
# be sure the user is blocked by now it should work for our purposes
- $currentBlock = Block::newFromDB( $target, $userId );
+ $currentBlock = Block::newFromTargetAndType( $target, $type );
if( $block->equals( $currentBlock ) ) {
return array( 'ipb_already_blocked' );
}
# Block constructor sanitizes certain block options on insert
- $data['BlockEmail'] = $block->mBlockEmail;
+ $data['BlockEmail'] = $block->prevents( 'sendemail' );
$data['AutoBlock'] = $block->mEnableAutoblock;
# Prepare log parameters
$this->showList();
}
- /**
- * Get the component of an IP address which is certain to be the same between an IP
- * address and a rangeblock containing that IP address.
- * @todo: should be in IP.php??
- * @param $ip String
- * @return String
- */
- protected static function getIpFragment( $ip ){
- global $wgBlockCIDRLimit;
- if( IP::isIPv4( $ip ) ){
- $hexAddress = IP::toHex( $ip );
- return substr( $hexAddress, 0, wfBaseconvert( $wgBlockCIDRLimit['IPv4'], 10, 16 ) );
- } elseif( IP::isIPv6( $ip ) ) {
- $hexAddress = substr( IP::toHex( $ip ), 2 );
- return 'v6-' . substr( $hexAddress, 0, wfBaseconvert( $wgBlockCIDRLimit['IPv6'], 10, 16 ) );
- } else {
- return null;
- }
- }
-
function showList() {
global $wgOut, $wgUser;
break;
case Block::TYPE_IP:
- case BLock::TYPE_RANGE:
+ case Block::TYPE_RANGE:
list( $start, $end ) = IP::parseRange( $target );
- # Per bug 14634, we want to include relevant active rangeblocks; for
- # rangeblocks, we want to include larger ranges which enclose the given
- # range. We know that all blocks must be smaller than $wgBlockCIDRLimit,
- # so we can improve performance by filtering on a LIKE clause
- $chunk = self::getIpFragment( $start );
$dbr = wfGetDB( DB_SLAVE );
- $like = $dbr->buildLike( $chunk, $dbr->anyString() );
-
- # Fairly hard to make a malicious SQL statement out of hex characters,
- # but stranger things have happened...
- $safeStart = $dbr->addQuotes( IP::toHex( $start ) );
- $safeEnd = $dbr->addQuotes( IP::toHex( $end ) );
- $safeTarget = $dbr->addQuotes( IP::toHex( $target ) );
-
- # TODO: abstract this away
- $conds[] = "(ipb_address = $safeTarget) OR
- (ipb_range_start $like AND ipb_range_start <= $safeStart AND ipb_range_end >= $safeEnd)";
+ $conds[] = $dbr->makeList(
+ array(
+ 'ipb_address' => $target,
+ Block::getRangeCond( $start, $end )
+ ),
+ LIST_OR
+ );
$conds['ipb_auto'] = 0;
break;