Index: trunk/extensions/CheckUser/CheckUser_body.php |
— | — | @@ -223,11 +223,11 @@ |
224 | 224 | protected function addJsCIDRForm() { |
225 | 225 | $s = '<fieldset id="mw-checkuser-cidrform" style="display:none;">'. |
226 | 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') ) . |
| 227 | + $s .= '<textarea id="mw-checkuser-iplist" rows="5" cols="50" onkeyup="updateCIDRresult()" onclick="updateCIDRresult()"></textarea><br/>'; |
| 228 | + $s .= wfMsgHtml('checkuser-cidr-res') . ' ' . |
| 229 | + Xml::input( 'mw-checkuser-cidr-res',35,'',array('id'=>'mw-checkuser-cidr-res') ) . |
230 | 230 | '<span id="mw-checkuser-ipnote"></span>'; |
231 | | - $s .= '</p></fieldset>'; |
| 231 | + $s .= '</fieldset>'; |
232 | 232 | return $s; |
233 | 233 | } |
234 | 234 | |
Index: trunk/extensions/CheckUser/CheckUser.php |
— | — | @@ -34,7 +34,7 @@ |
35 | 35 | # Mass block limits |
36 | 36 | $wgCheckUserMaxBlocks = 200; |
37 | 37 | |
38 | | -$wgCheckUserStyleVersion = 1; |
| 38 | +$wgCheckUserStyleVersion = 2; |
39 | 39 | |
40 | 40 | # Recent changes data hook |
41 | 41 | global $wgHooks; |
Index: trunk/extensions/CheckUser/checkuser.js |
— | — | @@ -15,9 +15,13 @@ |
16 | 16 | // Each line has one IP or range |
17 | 17 | var ips = iplist.value.split("\n"); |
18 | 18 | var bin_prefix = 0; |
| 19 | + var prefix_cidr = 0; |
| 20 | + var prefix = new String( "" ); |
19 | 21 | // Go through each IP in the list, get it's binary form, and track |
20 | 22 | // the largest binary prefix among them |
21 | | - for( i=0; i<ips.length; i++ ) { |
| 23 | + for( var i=0; i<ips.length; i++ ) { |
| 24 | + // Rebuilt formatted bin_prefix for each IP |
| 25 | + var prefix = ""; |
22 | 26 | // ...in the spirit of block.js, call this "addy" |
23 | 27 | var addy = ips[i]; |
24 | 28 | // Match the first IP in each list (ignore other garbage) |
— | — | @@ -25,13 +29,13 @@ |
26 | 30 | 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 | 31 | // Binary form |
28 | 32 | var bin = new String( "" ); |
29 | | - // Convert the IP to binary form |
| 33 | + // Convert the IP to binary form: IPv4 |
30 | 34 | if( ipV4 ) { |
31 | 35 | var ip = ipV4[1]; |
32 | 36 | var cidr = ipV4[2]; // CIDR, if it exists |
33 | 37 | // Get each quad integer |
34 | 38 | var blocs = ip.split('.'); |
35 | | - for( x=0; x<blocs.length; x++ ) { |
| 39 | + for( var x=0; x<blocs.length; x++ ) { |
36 | 40 | bloc = parseInt( blocs[x], 10 ); |
37 | 41 | if( bloc > 255 ) continue; // bad IP! |
38 | 42 | bin_block = bloc.toString(2); // concat bin with binary form of bloc |
— | — | @@ -50,7 +54,7 @@ |
51 | 55 | bin_prefix = new String( bin ); |
52 | 56 | // Get largest common bin_prefix |
53 | 57 | } else { |
54 | | - for( x=0; x<bin_prefix.length; x++ ) { |
| 58 | + for( var x=0; x<bin_prefix.length; x++ ) { |
55 | 59 | // Bin_prefix always smaller than bin unless a CIDR was used on bin |
56 | 60 | if( bin[x] == undefined || bin_prefix[x] != bin[x] ) { |
57 | 61 | bin_prefix = bin_prefix.substring(0,x); // shorten bin_prefix |
— | — | @@ -62,55 +66,130 @@ |
63 | 67 | var prefix_cidr = bin_prefix.length; |
64 | 68 | // CIDR too small? |
65 | 69 | if( prefix_cidr < 16 ) { |
66 | | - document.getElementById( 'mw-checkuser-ipres' ).value = "!"; |
| 70 | + document.getElementById( 'mw-checkuser-cidr-res' ).value = "!"; |
67 | 71 | document.getElementById( 'mw-checkuser-ipnote' ).innerHTML = ''; |
68 | 72 | return; // too big |
69 | 73 | } |
70 | | - var prefix = new String( "" ); |
71 | | - // First bloc (/8) |
72 | | - var bloc = 0; |
73 | | - for( x=0; x<=7; x++ ) { |
74 | | - bloc += parseInt(bin_prefix[x],10)*Math.pow(2,7-x); |
| 74 | + // Build the IP in dotted-quad form |
| 75 | + for( var z=0; z<=3; z++ ) { |
| 76 | + var bloc = 0; |
| 77 | + var start = z*8; |
| 78 | + var end = start + 7; |
| 79 | + for( var x=start; x<=end; x++ ) { |
| 80 | + if( bin_prefix[x] == undefined ) break; |
| 81 | + bloc += parseInt(bin_prefix[x],10)*Math.pow(2,end-x); |
| 82 | + } |
| 83 | + prefix += ( z == 3 ) ? bloc : bloc + '.'; |
75 | 84 | } |
76 | | - prefix += bloc + '.'; |
77 | | - // Second bloc (/16) |
78 | | - var bloc = 0; |
79 | | - for( x=8; x<=15; x++ ) { |
80 | | - bloc += parseInt(bin_prefix[x],10)*Math.pow(2,15-x); |
81 | | - } |
82 | | - prefix += bloc + '.'; |
83 | | - // Third bloc (/24) |
84 | | - var bloc = 0; |
85 | | - for( x=16; x<=23; x++ ) { |
86 | | - if( bin_prefix[x] == undefined ) break; |
87 | | - bloc += parseInt(bin_prefix[x],10)*Math.pow(2,23-x); |
88 | | - } |
89 | | - prefix += bloc + '.'; |
90 | | - // First bloc (/32) |
91 | | - var bloc = 0; |
92 | | - for( x=24; x<=31; x++ ) { |
93 | | - if( bin_prefix[x] == undefined ) break; |
94 | | - bloc += parseInt(bin_prefix[x],10)*Math.pow(2,31-x); |
95 | | - } |
96 | | - prefix += bloc; |
97 | | - document.getElementById( 'mw-checkuser-ipres' ).value = prefix + '/' + prefix_cidr; |
98 | 85 | // Get IPs affected |
99 | 86 | ip_count = Math.pow(2,32-prefix_cidr); |
100 | | - document.getElementById( 'mw-checkuser-ipnote' ).innerHTML = ' ~' + ip_count; |
101 | | - } |
102 | | - /* |
103 | | - TODO: IPv6 |
104 | | - } else if( isIpV6 ) { |
| 87 | + // Is the CIDR meaningful? |
| 88 | + if( prefix_cidr == 32 ) prefix_cidr = false; |
| 89 | + // Convert the IP to binary form: IPv6 |
| 90 | + } else if( ipV6 ) { |
105 | 91 | var ip = ipV6[1]; |
106 | 92 | var cidr = ipV6[2]; |
107 | | - // Get each quad integer |
| 93 | + // Get each hex octant |
108 | 94 | var blocs = ip.split(':'); |
109 | | - for( x=0; x<blocs.length; x++ ) { |
110 | | - if( blocs[x] > "ffff" ) continue; // bad IP! |
| 95 | + for( var x=0; x<=7; x++ ) { |
| 96 | + bloc = blocs[x] ? blocs[x] : "0"; |
| 97 | + if( bloc > "ffff" ) continue; // bad IP! |
| 98 | + int_block = hex2int( bloc ); // convert hex -> int |
| 99 | + bin_block = int_block.toString(2); // concat bin with binary form of bloc |
| 100 | + while( bin_block.length < 16 ) { |
| 101 | + bin_block = "0" + bin_block; // pad out as needed |
| 102 | + } |
| 103 | + bin += bin_block; |
111 | 104 | } |
| 105 | + // Apply any valid CIDRs |
| 106 | + if( cidr ) { |
| 107 | + cidr = cidr.match( /\d+$/ )[0]; // get rid of slash |
| 108 | + if( cidr >= 64 ) bin = bin.substring(0,cidr); // truncate bin |
| 109 | + } |
| 110 | + // Init bin_prefix |
| 111 | + if( bin_prefix === 0 ) { |
| 112 | + bin_prefix = new String( bin ); |
| 113 | + // Get largest common bin_prefix |
| 114 | + } else { |
| 115 | + for( var x=0; x<bin_prefix.length; x++ ) { |
| 116 | + // Bin_prefix always smaller than bin unless a CIDR was used on bin |
| 117 | + if( bin[x] == undefined || bin_prefix[x] != bin[x] ) { |
| 118 | + bin_prefix = bin_prefix.substring(0,x); // shorten bin_prefix |
| 119 | + break; |
| 120 | + } |
| 121 | + } |
| 122 | + } |
| 123 | + // Build the IP in CIDR form |
| 124 | + var prefix_cidr = bin_prefix.length; |
| 125 | + // CIDR too small? |
| 126 | + if( prefix_cidr < 64 ) { |
| 127 | + document.getElementById( 'mw-checkuser-cidr-res' ).value = "!"; |
| 128 | + document.getElementById( 'mw-checkuser-ipnote' ).innerHTML = ''; |
| 129 | + return; // too big |
| 130 | + } |
| 131 | + // Build the IP in dotted-quad form |
| 132 | + for( var z=0; z<=7; z++ ) { |
| 133 | + var bloc = 0; |
| 134 | + var start = z*16; |
| 135 | + var end = start + 15; |
| 136 | + for( var x=start; x<=end; x++ ) { |
| 137 | + if( bin_prefix[x] == undefined ) break; |
| 138 | + bloc += parseInt(bin_prefix[x],10)*Math.pow(2,end-x); |
| 139 | + } |
| 140 | + bloc = bloc.toString(16); // convert to hex |
| 141 | + prefix += ( z == 7 ) ? bloc : bloc + ':'; |
| 142 | + // Is the CIDR meaningful? |
| 143 | + if( prefix_cidr == 128 ) prefix_cidr = false; |
| 144 | + } |
| 145 | + // Get IPs affected |
| 146 | + ip_count = Math.pow(2,128-prefix_cidr); |
112 | 147 | } |
113 | | - */ |
114 | 148 | } |
| 149 | + // Update form |
| 150 | + if( prefix != "" ) { |
| 151 | + if( prefix_cidr != false ) { |
| 152 | + document.getElementById( 'mw-checkuser-cidr-res' ).value = prefix + '/' + prefix_cidr; |
| 153 | + } else { |
| 154 | + document.getElementById( 'mw-checkuser-cidr-res' ).value = prefix; |
| 155 | + } |
| 156 | + document.getElementById( 'mw-checkuser-ipnote' ).innerHTML = ' ~' + ip_count; |
| 157 | + } |
115 | 158 | |
116 | 159 | } |
117 | 160 | addOnloadHook( updateCIDRresult ); |
| 161 | + |
| 162 | +// Utility function to convert hex to integers |
| 163 | +function hex2int( hex ) { |
| 164 | + hex = new String( hex ); |
| 165 | + hex = hex.toLowerCase(); |
| 166 | + var intform = 0; |
| 167 | + for( var i=0; i<hex.length; i++ ) { |
| 168 | + var digit = 0; |
| 169 | + switch( hex[i] ) |
| 170 | + { |
| 171 | + case 'a': |
| 172 | + digit = 10; |
| 173 | + break; |
| 174 | + case 'b': |
| 175 | + digit = 11; |
| 176 | + break; |
| 177 | + case 'c': |
| 178 | + digit = 12; |
| 179 | + break; |
| 180 | + case 'd': |
| 181 | + digit = 13; |
| 182 | + break; |
| 183 | + case 'e': |
| 184 | + digit = 14; |
| 185 | + break; |
| 186 | + case 'f': |
| 187 | + digit = 15; |
| 188 | + break; |
| 189 | + default: |
| 190 | + digit = parseInt( hex[i], 10 ); |
| 191 | + break; |
| 192 | + } |
| 193 | + intform += digit*Math.pow(16,hex.length-1-i); |
| 194 | + } |
| 195 | + return intform; |
| 196 | +} |