* Fixed unclosed <p> tag
[lhc/web/wiklou.git] / includes / Block.php
1 <?php
2 /**
3 * Blocks and bans object
4 * @package MediaWiki
5 */
6
7 /**
8 * Some globals
9 */
10 define ( 'EB_KEEP_EXPIRED', 1 );
11 define ( 'EB_FOR_UPDATE', 2 );
12
13 /**
14 * The block class
15 * All the functions in this class assume the object is either explicitly
16 * loaded or filled. It is not load-on-demand. There are no accessors.
17 *
18 * To use delete(), you only need to fill $mAddress
19 * Globals used: $wgBlockCache, $wgAutoblockExpiry
20 *
21 * @todo This could be used everywhere, but it isn't.
22 * @package MediaWiki
23 */
24 class Block
25 {
26 /* public*/ var $mAddress, $mUser, $mBy, $mReason, $mTimestamp, $mAuto, $mId, $mExpiry;
27 /* private */ var $mNetworkBits, $mIntegerAddr, $mForUpdate;
28
29 function Block( $address = '', $user = '', $by = 0, $reason = '',
30 $timestamp = '' , $auto = 0, $expiry = '' )
31 {
32 $this->mAddress = $address;
33 $this->mUser = $user;
34 $this->mBy = $by;
35 $this->mReason = $reason;
36 $this->mTimestamp = wfTimestamp(TS_MW,$timestamp);
37 $this->mAuto = $auto;
38 if( empty( $expiry ) ) {
39 $this->mExpiry = $expiry;
40 } else {
41 $this->mExpiry = wfTimestamp( TS_MW, $expiry );
42 }
43
44 $this->mForUpdate = false;
45 $this->initialiseRange();
46 }
47
48 /*static*/ function newFromDB( $address, $user = 0, $killExpired = true )
49 {
50 $ban = new Block();
51 $ban->load( $address, $user, $killExpired );
52 return $ban;
53 }
54
55 function clear()
56 {
57 $mAddress = $mReason = $mTimestamp = '';
58 $mUser = $mBy = 0;
59 }
60
61 /**
62 * Get a ban from the DB, with either the given address or the given username
63 */
64 function load( $address = '', $user = 0, $killExpired = true )
65 {
66 global $wgDBmysql4 ;
67 $fname = 'Block::load';
68 wfDebug( "Block::load: '$address', '$user', $killExpired\n" );
69
70 $ret = false;
71 $killed = false;
72 if ( $this->forUpdate() ) {
73 $db =& wfGetDB( DB_MASTER );
74 $options = 'FOR UPDATE';
75 } else {
76 $db =& wfGetDB( DB_SLAVE );
77 $options = '';
78 }
79 $ipblocks = $db->tableName( 'ipblocks' );
80
81 if ( 0 == $user && $address=='' ) {
82 $sql = "SELECT * from $ipblocks $options";
83 } elseif ($address=="") {
84 $sql = "SELECT * FROM $ipblocks WHERE ipb_user={$user} $options";
85 } elseif ($user=="") {
86 $sql = "SELECT * FROM $ipblocks WHERE ipb_address='" . $db->strencode( $address ) . "' $options";
87 } elseif ( $options=='' && $wgDBmysql4 ) {
88 # If there are no optiones (e.g. FOR UPDATE), use a UNION
89 # so that the query can make efficient use of indices
90 $sql = "SELECT * FROM $ipblocks WHERE ipb_address='" . $db->strencode( $address ) .
91 "' UNION SELECT * FROM $ipblocks WHERE ipb_user={$user}";
92 } else {
93 # If there are options, a UNION can not be used, use one
94 # SELECT instead. Will do a full table scan.
95 $sql = "SELECT * FROM $ipblocks WHERE (ipb_address='" . $db->strencode( $address ) .
96 "' OR ipb_user={$user}) $options";
97 }
98
99 $res = $db->query( $sql, $fname );
100 if ( 0 == $db->numRows( $res ) ) {
101 # User is not blocked
102 $this->clear();
103 } else {
104 # Get first block
105 $row = $db->fetchObject( $res );
106 $this->initFromRow( $row );
107
108 if ( $killExpired ) {
109 # If requested, delete expired rows
110 do {
111 $killed = $this->deleteIfExpired();
112 if ( $killed ) {
113 $row = $db->fetchObject( $res );
114 if ( $row ) {
115 $this->initFromRow( $row );
116 }
117 }
118 } while ( $killed && $row );
119
120 # If there were any left after the killing finished, return true
121 if ( !$row ) {
122 $ret = false;
123 $this->clear();
124 } else {
125 $ret = true;
126 }
127 } else {
128 $ret = true;
129 }
130 }
131 $db->freeResult( $res );
132 return $ret;
133 }
134
135 function initFromRow( $row )
136 {
137 $this->mAddress = $row->ipb_address;
138 $this->mReason = $row->ipb_reason;
139 $this->mTimestamp = wfTimestamp(TS_MW,$row->ipb_timestamp);
140 $this->mUser = $row->ipb_user;
141 $this->mBy = $row->ipb_by;
142 $this->mAuto = $row->ipb_auto;
143 $this->mId = $row->ipb_id;
144 $this->mExpiry = $row->ipb_expiry ?
145 wfTimestamp(TS_MW,$row->ipb_expiry) :
146 $row->ipb_expiry;
147
148 $this->initialiseRange();
149 }
150
151 function initialiseRange()
152 {
153 if ( $this->mUser == 0 ) {
154 $rangeParts = explode( '/', $this->mAddress );
155 if ( count( $rangeParts ) == 2 ) {
156 $this->mNetworkBits = $rangeParts[1];
157 } else {
158 $this->mNetworkBits = 32;
159 }
160 $this->mIntegerAddr = ip2long( $rangeParts[0] );
161 } else {
162 $this->mNetworkBits = false;
163 $this->mIntegerAddr = false;
164 }
165 }
166
167 /**
168 * Callback with a Block object for every block
169 */
170 /*static*/ function enumBlocks( $callback, $tag, $flags = 0 )
171 {
172 $block = new Block();
173 if ( $flags & EB_FOR_UPDATE ) {
174 $db =& wfGetDB( DB_MASTER );
175 $options = 'FOR UPDATE';
176 $block->forUpdate( true );
177 } else {
178 $db =& wfGetDB( DB_SLAVE );
179 $options = '';
180 }
181 $ipblocks = $db->tableName( 'ipblocks' );
182
183 $sql = "SELECT * FROM $ipblocks ORDER BY ipb_timestamp DESC $options";
184 $res = $db->query( $sql, 'Block::enumBans' );
185
186 while ( $row = $db->fetchObject( $res ) ) {
187 $block->initFromRow( $row );
188 if ( !( $flags & EB_KEEP_EXPIRED ) ) {
189 if ( !$block->deleteIfExpired() ) {
190 $callback( $block, $tag );
191 }
192 } else {
193 $callback( $block, $tag );
194 }
195 }
196 wfFreeResult( $res );
197 }
198
199 function delete()
200 {
201 $fname = 'Block::delete';
202 if (wfReadOnly()) {
203 return;
204 }
205 $dbw =& wfGetDB( DB_MASTER );
206
207 if ( $this->mAddress == '' ) {
208 $condition = array( 'ipb_id' => $this->mId );
209 } else {
210 $condition = array( 'ipb_address' => $this->mAddress );
211 }
212 $dbw->delete( 'ipblocks', $condition, $fname );
213 $this->clearCache();
214 }
215
216 function insert()
217 {
218 wfDebug( "Block::insert; timestamp {$this->mTimestamp}\n" );
219 $dbw =& wfGetDB( DB_MASTER );
220 $dbw->insert( 'ipblocks',
221 array(
222 'ipb_address' => $this->mAddress,
223 'ipb_user' => $this->mUser,
224 'ipb_by' => $this->mBy,
225 'ipb_reason' => $this->mReason,
226 'ipb_timestamp' => $dbw->timestamp($this->mTimestamp),
227 'ipb_auto' => $this->mAuto,
228 'ipb_expiry' => $this->mExpiry ?
229 $dbw->timestamp($this->mExpiry) :
230 $this->mExpiry,
231 ), 'Block::insert'
232 );
233
234 $this->clearCache();
235 }
236
237 function deleteIfExpired()
238 {
239 if ( $this->isExpired() ) {
240 wfDebug( "Block::deleteIfExpired() -- deleting\n" );
241 $this->delete();
242 return true;
243 } else {
244 wfDebug( "Block::deleteIfExpired() -- not expired\n" );
245 return false;
246 }
247 }
248
249 function isExpired()
250 {
251 wfDebug( "Block::isExpired() checking current " . wfTimestampNow() . " vs $this->mExpiry\n" );
252 if ( !$this->mExpiry ) {
253 return false;
254 } else {
255 return wfTimestampNow() > $this->mExpiry;
256 }
257 }
258
259 function isValid()
260 {
261 return $this->mAddress != '';
262 }
263
264 function updateTimestamp()
265 {
266 if ( $this->mAuto ) {
267 $this->mTimestamp = wfTimestamp();
268 $this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp );
269
270 $dbw =& wfGetDB( DB_MASTER );
271 $dbw->update( 'ipblocks',
272 array( /* SET */
273 'ipb_timestamp' => $dbw->timestamp($this->mTimestamp),
274 'ipb_expiry' => $dbw->timestamp($this->mExpiry),
275 ), array( /* WHERE */
276 'ipb_address' => $this->mAddress
277 ), 'Block::updateTimestamp'
278 );
279
280 $this->clearCache();
281 }
282 }
283
284 /* private */ function clearCache()
285 {
286 global $wgBlockCache;
287 if ( is_object( $wgBlockCache ) ) {
288 $wgBlockCache->loadFromDB();
289 }
290 }
291
292 function getIntegerAddr()
293 {
294 return $this->mIntegerAddr;
295 }
296
297 function getNetworkBits()
298 {
299 return $this->mNetworkBits;
300 }
301
302 function forUpdate( $x = NULL ) {
303 return wfSetVar( $this->mForUpdate, $x );
304 }
305
306 /* static */ function getAutoblockExpiry( $timestamp )
307 {
308 global $wgAutoblockExpiry;
309 return wfTimestamp( TS_MW, wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
310 }
311
312 /* static */ function normaliseRange( $range )
313 {
314 $parts = explode( '/', $range );
315 if ( count( $parts ) == 2 ) {
316 $shift = 32 - $parts[1];
317 $ipint = ip2long( $parts[0] );
318 $ipint = $ipint >> $shift << $shift;
319 $newip = long2ip( $ipint );
320 $range = "$newip/{$parts[1]}";
321 }
322 return $range;
323 }
324
325 }
326 ?>