r11887 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r11886‎ | r11887 | r11888 >
Date:10:37, 1 December 2005
Author:timstarling
Status:old
Tags:
Comment:
Faster IP blocks. Requires schema change.
Modified paths:
  • /trunk/phase3/includes/Block.php (modified) (history)
  • /trunk/phase3/includes/BlockCache.php (deleted) (history)
  • /trunk/phase3/includes/ProxyTools.php (modified) (history)
  • /trunk/phase3/includes/Setup.php (modified) (history)
  • /trunk/phase3/includes/User.php (modified) (history)
  • /trunk/phase3/maintenance/archives/patch-ipb_range_start.sql (added) (history)
  • /trunk/phase3/maintenance/tables.sql (modified) (history)
  • /trunk/phase3/maintenance/updaters.inc (modified) (history)

Diff [purge]

Index: trunk/phase3/maintenance/archives/patch-ipb_range_start.sql
@@ -0,0 +1,25 @@
 2+-- Add the range handling fields
 3+ALTER TABLE /*$wgDBprefix*/ipblocks
 4+ ADD ipb_range_start varchar(32) NOT NULL default '',
 5+ ADD ipb_range_end varchar(32) NOT NULL default '',
 6+ ADD INDEX ipb_range (ipb_range_start(8), ipb_range_end(8));
 7+
 8+
 9+-- Initialise fields
 10+-- Only range blocks match ipb_address LIKE '%/%', this fact is used in the code already
 11+UPDATE /*$wgDBprefix*/ipblocks
 12+ SET
 13+ ipb_range_start = LPAD(HEX(
 14+ (SUBSTRING_INDEX(ipb_address, '.', 1) << 24)
 15+ + (SUBSTRING_INDEX(SUBSTRING_INDEX(ipb_address, '.', 2), '.', -1) << 16)
 16+ + (SUBSTRING_INDEX(SUBSTRING_INDEX(ipb_address, '.', 3), '.', -1) << 24)
 17+ + (SUBSTRING_INDEX(SUBSTRING_INDEX(ipb_address, '/', 1), '.', -1)) ), 8, '0' ),
 18+
 19+ ipb_range_end = LPAD(HEX(
 20+ (SUBSTRING_INDEX(ipb_address, '.', 1) << 24)
 21+ + (SUBSTRING_INDEX(SUBSTRING_INDEX(ipb_address, '.', 2), '.', -1) << 16)
 22+ + (SUBSTRING_INDEX(SUBSTRING_INDEX(ipb_address, '.', 3), '.', -1) << 24)
 23+ + (SUBSTRING_INDEX(SUBSTRING_INDEX(ipb_address, '/', 1), '.', -1))
 24+ + ((1 << (32 - SUBSTRING_INDEX(ipb_address, '/', -1))) - 1) ), 8, '0' )
 25+
 26+ WHERE ipb_address LIKE '%/%';
Property changes on: trunk/phase3/maintenance/archives/patch-ipb_range_start.sql
___________________________________________________________________
Added: svn:eol-style
127 + native
Added: svn:keywords
228 + Author Date Id Revision
Index: trunk/phase3/maintenance/updaters.inc
@@ -49,7 +49,8 @@
5050 array( 'image', 'img_media_type', 'patch-img_media_type.sql' ),
5151 array( 'validate', 'val_ip', 'patch-val_ip.sql' ),
5252 array( 'site_stats', 'ss_total_pages', 'patch-ss_total_articles.sql' ),
53 - array( 'interwiki', 'iw_trans', 'patch-interwiki-trans.sql' ),
 53+ array( 'interwiki', 'iw_trans', 'patch-interwiki-trans.sql' ),
 54+ array( 'ipblocks', 'ipb_range_start', 'patch-ipb_range_start.sql' ),
5455 );
5556
5657 function rename_table( $from, $to, $patch ) {
Index: trunk/phase3/maintenance/tables.sql
@@ -502,10 +502,16 @@
503503
504504 -- Time at which the block will expire.
505505 ipb_expiry char(14) binary NOT NULL default '',
506 -
 506+
 507+ -- Start and end of an address range, in hexadecimal
 508+ -- Size chosen to allow IPv6
 509+ ipb_range_start varchar(32) NOT NULL default '',
 510+ ipb_range_end varchar(32) NOT NULL default '',
 511+
507512 PRIMARY KEY ipb_id (ipb_id),
508513 INDEX ipb_address (ipb_address),
509 - INDEX ipb_user (ipb_user)
 514+ INDEX ipb_user (ipb_user),
 515+ INDEX ipb_range (ipb_range_start(8), ipb_range_end(8)),
510516
511517 ) TYPE=InnoDB;
512518
Index: trunk/phase3/includes/BlockCache.php
@@ -1,153 +0,0 @@
2 -<?php
3 -/**
4 - * Contain the blockcache class
5 - * @package Cache
6 - */
7 -
8 -/**
9 - * Object for fast lookup of IP blocks
10 - * Represents a memcached value, and in some sense, the entire ipblocks table
11 - * @package MediaWiki
12 - */
13 -class BlockCache
14 -{
15 - var $mData = false, $mMemcKey;
16 -
17 - /**
18 - * Constructor
19 - * Create a new BlockCache object
20 - *
21 - * @param Boolean $deferLoad specifies whether to immediately load the data from memcached.
22 - * @param String $dbName specifies the memcached dbName prefix to be used. Defaults to $wgDBname.
23 - */
24 - function BlockCache( $deferLoad = false, $dbName = '' ) {
25 - global $wgDBname;
26 -
27 - if ( $dbName == '' ) {
28 - $dbName = $wgDBname;
29 - }
30 -
31 - $this->mMemcKey = $dbName.':ipblocks';
32 -
33 - if ( !$deferLoad ) {
34 - $this->load();
35 - }
36 - }
37 -
38 - /**
39 - * Load the blocks from the database and save them to memcached
40 - * @param bool $bFromSlave Whether to load data from slaves or master
41 - */
42 - function loadFromDB( $bFromSlave = false ) {
43 - global $wgUseMemCached, $wgMemc;
44 - $fname = 'BlockCache::loadFromDB';
45 - wfProfileIn( $fname );
46 -
47 - $this->mData = array();
48 - # Selecting FOR UPDATE is a convenient way to serialise the memcached and DB operations,
49 - # which is necessary even though we don't update the DB
50 - if ( !$bFromSlave ) {
51 - Block::enumBlocks( 'wfBlockCacheInsert', '', EB_FOR_UPDATE | EB_RANGE_ONLY );
52 - #$wgMemc->set( $this->mMemcKey, $this->mData, 0 );
53 - } else {
54 - Block::enumBlocks( 'wfBlockCacheInsert', '', EB_RANGE_ONLY );
55 - }
56 - wfProfileOut( $fname );
57 - }
58 -
59 - /**
60 - * Load the cache from memcached or, if that's not possible, from the DB
61 - */
62 - function load( $bFromSlave ) {
63 - global $wgUseMemCached, $wgMemc;
64 -
65 - if ( $this->mData === false) {
66 - $this->loadFromDB( $bFromSlave );
67 -/*
68 - // Memcache disabled for performance issues.
69 - # Try memcached
70 - if ( $wgUseMemCached ) {
71 - $this->mData = $wgMemc->get( $this->mMemcKey );
72 - }
73 -
74 - if ( !is_array( $this->mData ) ) {
75 - $this->loadFromDB( $bFromSlave );
76 - }*/
77 - }
78 - }
79 -
80 - /**
81 - * Add a block to the cache
82 - *
83 - * @param Object &$block Reference to a "Block" object.
84 - */
85 - function insert( &$block ) {
86 - if ( $block->mUser == 0 ) {
87 - $nb = $block->getNetworkBits();
88 - $ipint = $block->getIntegerAddr();
89 - $index = $ipint >> ( 32 - $nb );
90 -
91 - if ( !array_key_exists( $nb, $this->mData ) ) {
92 - $this->mData[$nb] = array();
93 - }
94 -
95 - $this->mData[$nb][$index] = 1;
96 - }
97 - }
98 -
99 - /**
100 - * Find out if a given IP address is blocked
101 - *
102 - * @param String $ip IP address
103 - * @param bool $bFromSlave True means to load check against slave, else check against master.
104 - */
105 - function get( $ip, $bFromSlave ) {
106 - $fname = 'BlockCache::get';
107 - wfProfileIn( $fname );
108 -
109 - $this->load( $bFromSlave );
110 - $ipint = ip2long( $ip );
111 - $blocked = false;
112 -
113 - foreach ( $this->mData as $networkBits => $blockInts ) {
114 - if ( array_key_exists( $ipint >> ( 32 - $networkBits ), $blockInts ) ) {
115 - $blocked = true;
116 - break;
117 - }
118 - }
119 - if ( $blocked ) {
120 - # Clear low order bits
121 - if ( $networkBits != 32 ) {
122 - $ip .= '/'.$networkBits;
123 - $ip = Block::normaliseRange( $ip );
124 - }
125 - $block = new Block();
126 - $block->forUpdate( $bFromSlave );
127 - $block->load( $ip );
128 - } else {
129 - $block = false;
130 - }
131 -
132 - wfProfileOut( $fname );
133 - return $block;
134 - }
135 -
136 - /**
137 - * Clear the local cache
138 - * There was once a clear() to clear memcached too, but I deleted it
139 - */
140 - function clearLocal() {
141 - $this->mData = false;
142 - }
143 -}
144 -
145 -/**
146 - * Add a block to the global $wgBlockCache
147 - *
148 - * @param Object $block A "Block"-object
149 - * @param Any $tag unused
150 - */
151 -function wfBlockCacheInsert( $block, $tag ) {
152 - global $wgBlockCache;
153 - $wgBlockCache->insert( $block );
154 -}
Index: trunk/phase3/includes/ProxyTools.php
@@ -55,7 +55,10 @@
5656 return $ip;
5757 }
5858
59 -/** */
 59+/**
 60+ * Given an IP address in dotted-quad notation, returns an unsigned integer.
 61+ * Like ip2long() except that it actually works and has a consistent error return value.
 62+ */
6063 function wfIP2Unsigned( $ip ) {
6164 $n = ip2long( $ip );
6265 if ( $n == -1 || $n === false ) { # Return value on error depends on PHP version
@@ -67,6 +70,17 @@
6871 }
6972
7073 /**
 74+ * Return a zero-padded hexadecimal representation of an IP address
 75+ */
 76+function wfIP2Hex( $ip ) {
 77+ $n = wfIP2Unsigned( $ip );
 78+ if ( $n !== false ) {
 79+ $n = sprintf( '%08X', $n );
 80+ }
 81+ return $n;
 82+}
 83+
 84+/**
7185 * Determine if an IP address really is an IP address, and if it is public,
7286 * i.e. not RFC 1918 or similar
7387 */
@@ -143,4 +157,22 @@
144158 }
145159 }
146160
 161+/**
 162+ * Convert a network specification in CIDR notation to an integer network and a number of bits
 163+ */
 164+function wfParseCIDR( $range ) {
 165+ $parts = explode( '/', $range, 2 );
 166+ if ( count( $parts ) != 2 ) {
 167+ return array( false, false );
 168+ }
 169+ $network = wfIP2Unsigned( $parts[0] );
 170+ if ( $network !== false && is_numeric( $parts[1] ) && $parts[1] >= 0 && $parts[1] <= 32 ) {
 171+ $bits = $parts[1];
 172+ } else {
 173+ $network = false;
 174+ $bits = false;
 175+ }
 176+ return array( $network, $bits );
 177+}
 178+
147179 ?>
Index: trunk/phase3/includes/User.php
@@ -372,14 +372,9 @@
373373 * @param bool $bFromSlave Specify whether to check slave or master. To improve performance,
374374 * non-critical checks are done against slaves. Check when actually saving should be done against
375375 * master.
376 - *
377 - * Note that even if $bFromSlave is false, the check is done first against slave, then master.
378 - * The logic is that if blocked on slave, we'll assume it's either blocked on master or
379 - * just slightly outta sync and soon corrected - safer to block slightly more that less.
380 - * And it's cheaper to check slave first, then master if needed, than master always.
381376 */
382377 function getBlockedStatus( $bFromSlave = true ) {
383 - global $wgBlockCache, $wgProxyList, $wgEnableSorbs, $wgProxyWhitelist;
 378+ global $wgProxyList, $wgEnableSorbs, $wgProxyWhitelist;
384379
385380 if ( -1 != $this->mBlockedby ) {
386381 wfDebug( "User::getBlockedStatus: already loaded.\n" );
@@ -395,7 +390,7 @@
396391
397392 # User/IP blocking
398393 $block = new Block();
399 - $block->forUpdate( $bFromSlave );
 394+ $block->fromMaster( !$bFromSlave );
400395 if ( $block->load( $ip , $this->mId ) ) {
401396 wfDebug( "$fname: Found block.\n" );
402397 $this->mBlockedby = $block->mBy;
@@ -407,23 +402,6 @@
408403 wfDebug( "$fname: No block.\n" );
409404 }
410405
411 - # Range blocking
412 - if ( !$this->mBlockedby ) {
413 - # Check first against slave, and optionally from master.
414 - wfDebug( "$fname: Checking range blocks\n" );
415 - $block = $wgBlockCache->get( $ip, true );
416 - if ( !$block && !$bFromSlave )
417 - {
418 - # Not blocked: check against master, to make sure.
419 - $wgBlockCache->clearLocal( );
420 - $block = $wgBlockCache->get( $ip, false );
421 - }
422 - if ( $block !== false ) {
423 - $this->mBlockedby = $block->mBy;
424 - $this->mBlockreason = $block->mReason;
425 - }
426 - }
427 -
428406 # Proxy blocking
429407 if ( !$this->isSysop() && !in_array( $ip, $wgProxyWhitelist ) ) {
430408
Index: trunk/phase3/includes/Setup.php
@@ -62,7 +62,6 @@
6363 require_once( 'MagicWord.php' );
6464 require_once( 'Block.php' );
6565 require_once( 'MessageCache.php' );
66 -require_once( 'BlockCache.php' );
6766 require_once( 'Parser.php' );
6867 require_once( 'ParserCache.php' );
6968 require_once( 'WebRequest.php' );
@@ -269,11 +268,6 @@
270269 $wgOut = new OutputPage();
271270
272271 wfProfileOut( $fname.'-OutputPage' );
273 -wfProfileIn( $fname.'-BlockCache' );
274 -
275 -$wgBlockCache = new BlockCache( true );
276 -
277 -wfProfileOut( $fname.'-BlockCache' );
278272 wfProfileIn( $fname.'-misc2' );
279273
280274 $wgDeferredUpdateList = array();
Index: trunk/phase3/includes/Block.php
@@ -17,15 +17,16 @@
1818 * loaded or filled. It is not load-on-demand. There are no accessors.
1919 *
2020 * To use delete(), you only need to fill $mAddress
21 - * Globals used: $wgBlockCache, $wgAutoblockExpiry
 21+ * Globals used: $wgAutoblockExpiry, $wgAntiLockFlags
2222 *
2323 * @todo This could be used everywhere, but it isn't.
2424 * @package MediaWiki
2525 */
2626 class Block
2727 {
28 - /* public*/ var $mAddress, $mUser, $mBy, $mReason, $mTimestamp, $mAuto, $mId, $mExpiry;
29 - /* private */ var $mNetworkBits, $mIntegerAddr, $mForUpdate, $mByName;
 28+ /* public*/ var $mAddress, $mUser, $mBy, $mReason, $mTimestamp, $mAuto, $mId, $mExpiry,
 29+ $mRangeStart, $mRangeEnd;
 30+ /* private */ var $mNetworkBits, $mIntegerAddr, $mForUpdate, $mFromMaster, $mByName;
3031
3132 function Block( $address = '', $user = '', $by = 0, $reason = '',
3233 $timestamp = '' , $auto = 0, $expiry = '' )
@@ -43,6 +44,7 @@
4445 }
4546
4647 $this->mForUpdate = false;
 48+ $this->mFromMaster = false;
4749 $this->mByName = false;
4850 $this->initialiseRange();
4951 }
@@ -63,19 +65,14 @@
6466 }
6567
6668 /**
67 - * Get a ban from the DB, with either the given address or the given username
 69+ * Get the DB object and set the reference parameter to the query options
6870 */
69 - function load( $address = '', $user = 0, $killExpired = true )
 71+ function &getDBOptions( &$options )
7072 {
7173 global $wgAntiLockFlags;
72 - $fname = 'Block::load';
73 - wfDebug( "Block::load: '$address', '$user', $killExpired\n" );
74 -
75 - $ret = false;
76 - $killed = false;
77 - if ( $this->forUpdate() ) {
 74+ if ( $this->mForUpdate || $this->mFromMaster ) {
7875 $db =& wfGetDB( DB_MASTER );
79 - if ( $wgAntiLockFlags & ALF_NO_BLOCK_LOCK ) {
 76+ if ( !$this->mForUpdate || ($wgAntiLockFlags & ALF_NO_BLOCK_LOCK) ) {
8077 $options = '';
8178 } else {
8279 $options = 'FOR UPDATE';
@@ -84,15 +81,33 @@
8582 $db =& wfGetDB( DB_SLAVE );
8683 $options = '';
8784 }
 85+ return $db;
 86+ }
 87+
 88+ /**
 89+ * Get a ban from the DB, with either the given address or the given username
 90+ */
 91+ function load( $address = '', $user = 0, $killExpired = true )
 92+ {
 93+ $fname = 'Block::load';
 94+ wfDebug( "Block::load: '$address', '$user', $killExpired\n" );
 95+
 96+ $options = '';
 97+ $db =& $this->getDBOptions( $options );
 98+
 99+ $ret = false;
 100+ $killed = false;
88101 $ipblocks = $db->tableName( 'ipblocks' );
89102
90 - if ( 0 == $user && $address=='' ) {
91 - $sql = "SELECT * from $ipblocks $options";
92 - } elseif ($address=="") {
 103+ if ( 0 == $user && $address == '' ) {
 104+ # Invalid user specification, not blocked
 105+ $this->clear();
 106+ return false;
 107+ } elseif ( $address == '' ) {
93108 $sql = "SELECT * FROM $ipblocks WHERE ipb_user={$user} $options";
94 - } elseif ($user=="") {
95 - $sql = "SELECT * FROM $ipblocks WHERE ipb_address='" . $db->strencode( $address ) . "' $options";
96 - } elseif ( $options=='' ) {
 109+ } elseif ( $user == '' ) {
 110+ $sql = "SELECT * FROM $ipblocks WHERE ipb_address=" . $db->addQuotes( $address ) . " $options";
 111+ } elseif ( $options == '' ) {
97112 # If there are no options (e.g. FOR UPDATE), use a UNION
98113 # so that the query can make efficient use of indices
99114 $sql = "SELECT * FROM $ipblocks WHERE ipb_address='" . $db->strencode( $address ) .
@@ -105,10 +120,7 @@
106121 }
107122
108123 $res = $db->query( $sql, $fname );
109 - if ( 0 == $db->numRows( $res ) ) {
110 - # User is not blocked
111 - $this->clear();
112 - } else {
 124+ if ( 0 != $db->numRows( $res ) ) {
113125 # Get first block
114126 $row = $db->fetchObject( $res );
115127 $this->initFromRow( $row );
@@ -137,9 +149,72 @@
138150 }
139151 }
140152 $db->freeResult( $res );
 153+
 154+ # No blocks found yet? Try looking for range blocks
 155+ if ( !$ret && $address != '' ) {
 156+ $ret = $this->loadRange( $address, $killExpired );
 157+ }
 158+ if ( !$ret ) {
 159+ $this->clear();
 160+ }
 161+
141162 return $ret;
142163 }
143164
 165+ /**
 166+ * Search the database for any range blocks matching the given address, and
 167+ * load the row if one is found.
 168+ */
 169+ function loadRange( $address, $killExpired = true )
 170+ {
 171+ $fname = 'Block::loadRange';
 172+
 173+ $iaddr = wfIP2Hex( $address );
 174+ if ( $iaddr === false ) {
 175+ # Invalid address
 176+ return false;
 177+ }
 178+
 179+ # Only scan ranges which start in this /16, this improves search speed
 180+ # Blocks should not cross a /16 boundary.
 181+ $range = substr( $iaddr, 0, 4 );
 182+
 183+ $options = '';
 184+ $db =& $this->getDBOptions( $options );
 185+ $ipblocks = $db->tableName( 'ipblocks' );
 186+ $sql = "SELECT * FROM $ipblocks WHERE ipb_range_start LIKE '$range%' ".
 187+ "AND ipb_range_start <= '$iaddr' AND ipb_range_end >= '$iaddr' $options";
 188+ $res = $db->query( $sql, $fname );
 189+ $row = $db->fetchObject( $res );
 190+
 191+ $success = false;
 192+ if ( $row ) {
 193+ # Found a row, initialise this object
 194+ $this->initFromRow( $row );
 195+
 196+ # Is it expired?
 197+ if ( !$killExpired || !$this->deleteIfExpired() ) {
 198+ # No, return true
 199+ $success = true;
 200+ }
 201+ }
 202+
 203+ $db->freeResult( $res );
 204+ return $success;
 205+ }
 206+
 207+ /**
 208+ * Determine if a given integer IPv4 address is in a given CIDR network
 209+ */
 210+ function isAddressInRange( $addr, $range ) {
 211+ list( $network, $bits ) = wfParseCIDR( $range );
 212+ if ( $network !== false && $addr >> ( 32 - $bits ) == $network >> ( 32 - $bits ) ) {
 213+ return true;
 214+ } else {
 215+ return false;
 216+ }
 217+ }
 218+
144219 function initFromRow( $row )
145220 {
146221 $this->mAddress = $row->ipb_address;
@@ -157,24 +232,21 @@
158233 } else {
159234 $this->mByName = false;
160235 }
161 -
162 - $this->initialiseRange();
 236+ $this->mRangeStart = $row->ipb_range_start;
 237+ $this->mRangeEnd = $row->ipb_range_end;
163238 }
164239
165240 function initialiseRange()
166241 {
 242+ $this->mRangeStart = '';
 243+ $this->mRangeEnd = '';
167244 if ( $this->mUser == 0 ) {
168 - $rangeParts = explode( '/', $this->mAddress );
169 - if ( count( $rangeParts ) == 2 ) {
170 - $this->mNetworkBits = $rangeParts[1];
171 - } else {
172 - $this->mNetworkBits = 32;
 245+ list( $network, $bits ) = wfParseCIDR( $this->mAddress );
 246+ if ( $network !== false ) {
 247+ $this->mRangeStart = sprintf( '%08X', $network );
 248+ $this->mRangeEnd = sprintf( '%08X', $network + (1 << (32 - $bits)) - 1 );
173249 }
174 - $this->mIntegerAddr = ip2long( $rangeParts[0] );
175 - } else {
176 - $this->mNetworkBits = false;
177 - $this->mIntegerAddr = false;
178 - }
 250+ }
179251 }
180252
181253 /**
@@ -199,7 +271,7 @@
200272 $options = '';
201273 }
202274 if ( $flags & EB_RANGE_ONLY ) {
203 - $cond = " AND ipb_address LIKE '%/%'";
 275+ $cond = " AND ipb_range_start <> ''";
204276 } else {
205277 $cond = '';
206278 }
@@ -215,7 +287,7 @@
216288
217289 while ( $row = $db->fetchObject( $res ) ) {
218290 $block->initFromRow( $row );
219 - if ( ( $flags & EB_RANGE_ONLY ) && $block->getNetworkBits() == 32 ) {
 291+ if ( ( $flags & EB_RANGE_ONLY ) && $block->mRangeStart == '' ) {
220292 continue;
221293 }
222294
@@ -247,7 +319,6 @@
248320 $condition = array( 'ipb_address' => $this->mAddress );
249321 }
250322 $dbw->delete( 'ipblocks', $condition, $fname );
251 - $this->clearCache();
252323 }
253324
254325 function insert()
@@ -267,10 +338,10 @@
268339 'ipb_expiry' => $this->mExpiry ?
269340 $dbw->timestamp($this->mExpiry) :
270341 $this->mExpiry,
 342+ 'ipb_range_start' => $this->mRangeStart,
 343+ 'ipb_range_end' => $this->mRangeEnd,
271344 ), 'Block::insert'
272345 );
273 -
274 - $this->clearCache();
275346 }
276347
277348 function deleteIfExpired()
@@ -319,19 +390,10 @@
320391 'ipb_address' => $this->mAddress
321392 ), 'Block::updateTimestamp'
322393 );
323 -
324 - $this->clearCache();
325394 }
326395 }
327396
328 - /* private */ function clearCache()
329 - {
330 - global $wgBlockCache;
331 - if ( is_object( $wgBlockCache ) ) {
332 - $wgBlockCache->loadFromDB();
333 - }
334 - }
335 -
 397+ /*
336398 function getIntegerAddr()
337399 {
338400 return $this->mIntegerAddr;
@@ -340,7 +402,7 @@
341403 function getNetworkBits()
342404 {
343405 return $this->mNetworkBits;
344 - }
 406+ }*/
345407
346408 function getByName()
347409 {
@@ -354,6 +416,10 @@
355417 return wfSetVar( $this->mForUpdate, $x );
356418 }
357419
 420+ function fromMaster( $x = NULL ) {
 421+ return wfSetVar( $this->mFromMaster, $x );
 422+ }
 423+
358424 /* static */ function getAutoblockExpiry( $timestamp )
359425 {
360426 global $wgAutoblockExpiry;
@@ -365,7 +431,7 @@
366432 $parts = explode( '/', $range );
367433 if ( count( $parts ) == 2 ) {
368434 $shift = 32 - $parts[1];
369 - $ipint = ip2long( $parts[0] );
 435+ $ipint = wfIP2Unsigned( $parts[0] );
370436 $ipint = $ipint >> $shift << $shift;
371437 $newip = long2ip( $ipint );
372438 $range = "$newip/{$parts[1]}";

Status & tagging log