Index: trunk/extensions/CheckUser/CheckUser_body.php |
— | — | @@ -116,6 +116,9 @@ |
117 | 117 | $this->doUserEditsRequest( $user, $reason, $period ); |
118 | 118 | } |
119 | 119 | } |
| 120 | + # Add CIDR calculation convenience form |
| 121 | + $wgOut->addHTML( $this->addJsCIDRForm() ); |
| 122 | + $this->addStyles(); |
120 | 123 | } |
121 | 124 | |
122 | 125 | /** |
— | — | @@ -190,6 +193,15 @@ |
191 | 194 | $wgOut->addHTML( $form ); |
192 | 195 | } |
193 | 196 | |
| 197 | + /** |
| 198 | + * Add CSS/JS |
| 199 | + */ |
| 200 | + protected function addStyles() { |
| 201 | + global $wgScriptPath, $wgCheckUserStyleVersion, $wgOut; |
| 202 | + $encJSFile = htmlspecialchars( "$wgScriptPath/extensions/CheckUser/checkuser.js?$wgCheckUserStyleVersion" ); |
| 203 | + $wgOut->addScript( "<script type=\"text/javascript\" src=\"$encJSFile\"></script>" ); |
| 204 | + } |
| 205 | + |
194 | 206 | /** |
195 | 207 | * Get a selector of time period options |
196 | 208 | * @param int $selected, selected level |
— | — | @@ -206,6 +218,20 @@ |
207 | 219 | } |
208 | 220 | |
209 | 221 | /** |
| 222 | + * Make a quick JS form for admins to calculate block ranges |
| 223 | + */ |
| 224 | + protected function addJsCIDRForm() { |
| 225 | + $s = '<fieldset id="mw-checkuser-cidrform" style="display:none;">'. |
| 226 | + '<legend>'.wfMsgHtml('checkuser-cidr-label').'</legend>'; |
| 227 | + $s .= '<p><textarea id="mw-checkuser-iplist" rows="5" cols="80" onkeyup="updateCIDRresult()"></textarea></p>'; |
| 228 | + $s .= '<p>'.wfMsgHtml('checkuser-cidr-res') . ' ' . |
| 229 | + Xml::input( 'mw-checkuser-ipres',35,'',array('id'=>'mw-checkuser-ipres') ) . |
| 230 | + '<span id="mw-checkuser-ipnote"></span>'; |
| 231 | + $s .= '</p></fieldset>'; |
| 232 | + return $s; |
| 233 | + } |
| 234 | + |
| 235 | + /** |
210 | 236 | * Block a list of selected users |
211 | 237 | * @param array $users |
212 | 238 | * @param string $reason |
Index: trunk/extensions/CheckUser/CheckUser.i18n.php |
— | — | @@ -35,6 +35,8 @@ |
36 | 36 | 'checkuser-week-2' => 'last two weeks', |
37 | 37 | 'checkuser-month' => 'last 30 days', |
38 | 38 | 'checkuser-all' => 'all', |
| 39 | + 'checkuser-cidr-label' => 'Find common range and affected addresses for a list of IPs', |
| 40 | + 'checkuser-cidr-res' => 'Common CIDR:', |
39 | 41 | 'checkuser-empty' => 'The log contains no items.', |
40 | 42 | 'checkuser-nomatch' => 'No matches found.', |
41 | 43 | 'checkuser-nomatch-edits' => 'No matches found. |
Index: trunk/extensions/CheckUser/CheckUser.php |
— | — | @@ -34,6 +34,8 @@ |
35 | 35 | # Mass block limits |
36 | 36 | $wgCheckUserMaxBlocks = 200; |
37 | 37 | |
| 38 | +$wgCheckUserStyleVersion = 1; |
| 39 | + |
38 | 40 | # Recent changes data hook |
39 | 41 | global $wgHooks; |
40 | 42 | $wgHooks['RecentChange_save'][] = 'efUpdateCheckUserData'; |
Index: trunk/extensions/CheckUser/checkuser.js |
— | — | @@ -0,0 +1,115 @@ |
| 2 | +/* -- (c) Aaron Schulz 2009 */ |
| 3 | + |
| 4 | +/* Every time you change this JS please bump $wgCheckUserStyleVersion in CheckUser.php */ |
| 5 | + |
| 6 | +/* |
| 7 | +* This function calculates the common range of a list of |
| 8 | +* IPs. It should be set to update on keyUp. |
| 9 | +*/ |
| 10 | +function updateCIDRresult() { |
| 11 | + var form = document.getElementById( 'mw-checkuser-cidrform' ); |
| 12 | + if( !form ) return; // no JS form |
| 13 | + form.style.display = 'inline'; // unhide form (JS active) |
| 14 | + var iplist = document.getElementById( 'mw-checkuser-iplist' ); |
| 15 | + if( !iplist ) return; // no JS form |
| 16 | + // Each line has one IP or range |
| 17 | + var ips = iplist.value.split("\n"); |
| 18 | + var bin_prefix = 0; |
| 19 | + // Go through each IP in the list, get it's binary form, and track |
| 20 | + // the largest binary prefix among them |
| 21 | + for( i=0; i<ips.length; i++ ) { |
| 22 | + // ...in the spirit of block.js, call this "addy" |
| 23 | + var addy = ips[i]; |
| 24 | + // Match the first IP in each list (ignore other garbage) |
| 25 | + var ipV4 = addy.match(/\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\/\d+)?\b/); |
| 26 | + var ipV6 = addy.match(/\b(:(:[0-9A-Fa-f]{1,4}){1,7}|[0-9A-Fa-f]{1,4}(:{1,2}[0-9A-Fa-f]{1,4}|::$){1,7})(\/\d+)?\b/); |
| 27 | + // Binary form |
| 28 | + var bin = new String( "" ); |
| 29 | + // Convert the IP to binary form |
| 30 | + if( ipV4 ) { |
| 31 | + var ip = ipV4[1]; |
| 32 | + var cidr = ipV4[2]; // CIDR, if it exists |
| 33 | + // Get each quad integer |
| 34 | + var blocs = ip.split('.'); |
| 35 | + for( x=0; x<blocs.length; x++ ) { |
| 36 | + bloc = parseInt( blocs[x], 10 ); |
| 37 | + if( bloc > 255 ) continue; // bad IP! |
| 38 | + bin_block = bloc.toString(2); // concat bin with binary form of bloc |
| 39 | + while( bin_block.length < 8 ) { |
| 40 | + bin_block = "0" + bin_block; // pad out as needed |
| 41 | + } |
| 42 | + bin += bin_block; |
| 43 | + } |
| 44 | + // Apply any valid CIDRs |
| 45 | + if( cidr ) { |
| 46 | + cidr = cidr.match( /\d+$/ )[0]; // get rid of slash |
| 47 | + if( cidr >= 16 ) bin = bin.substring(0,cidr); // truncate bin |
| 48 | + } |
| 49 | + // Init bin_prefix |
| 50 | + if( bin_prefix === 0 ) { |
| 51 | + bin_prefix = new String( bin ); |
| 52 | + // Get largest common bin_prefix |
| 53 | + } else { |
| 54 | + for( x=0; x<bin_prefix.length; x++ ) { |
| 55 | + if( bin_prefix[x] != bin[x] ) { |
| 56 | + bin_prefix = bin_prefix.substring(0,x); // shorten bin_prefix |
| 57 | + break; |
| 58 | + } |
| 59 | + } |
| 60 | + } |
| 61 | + // Build the IP in CIDR form |
| 62 | + var prefix_cidr = bin_prefix.length; |
| 63 | + // CIDR too small? |
| 64 | + if( prefix_cidr < 16 ) { |
| 65 | + document.getElementById( 'mw-checkuser-ipres' ).value = "!"; |
| 66 | + document.getElementById( 'mw-checkuser-ipnote' ).innerHTML = ''; |
| 67 | + return; // too big |
| 68 | + } |
| 69 | + var prefix = new String( "" ); |
| 70 | + // First bloc (/8) |
| 71 | + var bloc = 0; |
| 72 | + for( x=0; x<=7; x++ ) { |
| 73 | + bloc += parseInt(bin_prefix[x],10)*Math.pow(2,7-x); |
| 74 | + } |
| 75 | + prefix += bloc + '.'; |
| 76 | + // Second bloc (/16) |
| 77 | + var bloc = 0; |
| 78 | + for( x=8; x<=15; x++ ) { |
| 79 | + bloc += parseInt(bin_prefix[x],10)*Math.pow(2,15-x); |
| 80 | + } |
| 81 | + prefix += bloc + '.'; |
| 82 | + // Third bloc (/24) |
| 83 | + var bloc = 0; |
| 84 | + for( x=16; x<=23; x++ ) { |
| 85 | + if( bin_prefix[x] == undefined ) break; |
| 86 | + bloc += parseInt(bin_prefix[x],10)*Math.pow(2,23-x); |
| 87 | + } |
| 88 | + prefix += bloc + '.'; |
| 89 | + // First bloc (/32) |
| 90 | + var bloc = 0; |
| 91 | + for( x=24; x<=31; x++ ) { |
| 92 | + if( bin_prefix[x] == undefined ) break; |
| 93 | + bloc += parseInt(bin_prefix[x],10)*Math.pow(2,31-x); |
| 94 | + } |
| 95 | + prefix += bloc; |
| 96 | + document.getElementById( 'mw-checkuser-ipres' ).value = prefix + '/' + prefix_cidr; |
| 97 | + // Get IPs affected |
| 98 | + ip_count = Math.pow(2,32-prefix_cidr); |
| 99 | + document.getElementById( 'mw-checkuser-ipnote' ).innerHTML = ' ~' + ip_count; |
| 100 | + } |
| 101 | + /* |
| 102 | + TODO: IPv6 |
| 103 | + } else if( isIpV6 ) { |
| 104 | + var ip = ipV6[1]; |
| 105 | + var cidr = ipV6[2]; |
| 106 | + // Get each quad integer |
| 107 | + var blocs = ip.split(':'); |
| 108 | + for( x=0; x<blocs.length; x++ ) { |
| 109 | + if( blocs[x] > "ffff" ) continue; // bad IP! |
| 110 | + } |
| 111 | + } |
| 112 | + */ |
| 113 | + } |
| 114 | + |
| 115 | +} |
| 116 | +addOnloadHook( updateCIDRresult ); |
Property changes on: trunk/extensions/CheckUser/checkuser.js |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 117 | + native |