Index: trunk/phase3/skins/common/block.js |
— | — | @@ -1,15 +1,16 @@ |
2 | 2 | // @TODO: find some better JS file for this |
3 | 3 | // Note: borrows from IP.php |
4 | 4 | window.isIPv4Address = function( address, allowBlock ) { |
| 5 | + var block = allowBlock ? '(?:\\/(?:3[0-2]|[12]?\\d))?' : ''; |
5 | 6 | var RE_IP_BYTE = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])'; |
6 | | - var RE_IP_ADD = '(?:' + RE_IP_BYTE + '\.){3}' + RE_IP_BYTE; |
7 | | - var block = allowBlock ? '(?:\/(?:3[0-2]|[12]?\\d))?' : ''; |
| 7 | + var RE_IP_ADD = '(?:' + RE_IP_BYTE + '\\.){3}' + RE_IP_BYTE; |
8 | 8 | return address.search( new RegExp( '^' + RE_IP_ADD + block + '$' ) ) != -1; |
9 | 9 | }; |
10 | 10 | |
11 | 11 | // @TODO: find some better JS file for this |
12 | 12 | // Note: borrows from IP.php |
13 | 13 | window.isIPv6Address = function( address, allowBlock ) { |
| 14 | + var block = allowBlock ? '(?:\\/(?:12[0-8]|1[01][0-9]|[1-9]?\\d))?' : ''; |
14 | 15 | var RE_IPV6_ADD = |
15 | 16 | '(?:' + // starts with "::" (including "::") |
16 | 17 | ':(?::|(?::' + '[0-9A-Fa-f]{1,4}' + '){1,7})' + |
— | — | @@ -17,11 +18,14 @@ |
18 | 19 | '[0-9A-Fa-f]{1,4}' + '(?::' + '[0-9A-Fa-f]{1,4}' + '){0,6}::' + |
19 | 20 | '|' + // contains no "::" |
20 | 21 | '[0-9A-Fa-f]{1,4}' + '(?::' + '[0-9A-Fa-f]{1,4}' + '){7}' + |
21 | | - '|' + // contains one "::" in the middle |
22 | | - '[0-9A-Fa-f]{1,4}' + '(?::(:())?' + '[0-9A-Fa-f]{1,4}' + '(?!\1)){1,6}\2' + |
23 | 22 | ')'; |
24 | | - var block = allowBlock ? '(?:\/(?:12[0-8]|1[01][0-9]|[1-9]?\\d))?' : ''; |
25 | | - return address.search( new RegExp( '^' + RE_IPV6_ADD + block + '$' ) ) != -1; |
| 23 | + if ( address.search( new RegExp( '^' + RE_IPV6_ADD + block + '$' ) ) != -1 ) { |
| 24 | + return true; |
| 25 | + } |
| 26 | + var RE_IPV6_ADD = // contains one "::" in the middle (single '::' check below) |
| 27 | + '[0-9A-Fa-f]{1,4}' + '(?:::?' + '[0-9A-Fa-f]{1,4}' + '){1,6}'; |
| 28 | + return address.search( new RegExp( '^' + RE_IPV6_ADD + block + '$' ) ) != -1 |
| 29 | + && address.search( /::/ ) != -1 && address.search( /::.*::/ ) == -1; |
26 | 30 | }; |
27 | 31 | |
28 | 32 | window.considerChangingExpiryFocus = function() { |
Index: trunk/extensions/CheckUser/CheckUser_body.php |
— | — | @@ -115,7 +115,7 @@ |
116 | 116 | } |
117 | 117 | # Add CIDR calculation convenience form |
118 | 118 | $this->addJsCIDRForm(); |
119 | | - $this->addStyles(); |
| 119 | + $wgOut->addModules( 'ext.checkUser' ); // JS |
120 | 120 | } |
121 | 121 | |
122 | 122 | /** |
— | — | @@ -204,16 +204,6 @@ |
205 | 205 | } |
206 | 206 | |
207 | 207 | /** |
208 | | - * Add CSS/JS |
209 | | - */ |
210 | | - protected function addStyles() { |
211 | | - global $wgScriptPath, $wgCheckUserStyleVersion, $wgOut; |
212 | | - // FIXME, use Html:: |
213 | | - $encJSFile = htmlspecialchars( "$wgScriptPath/extensions/CheckUser/checkuser.js?$wgCheckUserStyleVersion" ); |
214 | | - $wgOut->addScript( "<script type=\"text/javascript\" src=\"$encJSFile\"></script>" ); |
215 | | - } |
216 | | - |
217 | | - /** |
218 | 208 | * Get a selector of time period options |
219 | 209 | * @param int $selected, selected level |
220 | 210 | */ |
Index: trunk/extensions/CheckUser/CheckUser.php |
— | — | @@ -61,7 +61,6 @@ |
62 | 62 | $wgCheckUserStyleVersion = 5; |
63 | 63 | |
64 | 64 | # Recent changes data hook |
65 | | -global $wgHooks; |
66 | 65 | $wgHooks['RecentChange_save'][] = 'efUpdateCheckUserData'; |
67 | 66 | $wgHooks['EmailUser'][] = 'efUpdateCUEmailData'; |
68 | 67 | $wgHooks['User::mailPasswordInternal'][] = 'efUpdateCUPasswordResetData'; |
— | — | @@ -71,6 +70,15 @@ |
72 | 71 | $wgHooks['LoadExtensionSchemaUpdates'][] = 'efCheckUserSchemaUpdates'; |
73 | 72 | $wgHooks['ContributionsToolLinks'][] = 'efLoadCheckUserLink'; |
74 | 73 | |
| 74 | +$wgResourceModules['ext.checkUser'] = array( |
| 75 | + 'scripts' => 'checkuser.js', |
| 76 | + 'dependencies' => array( 'mediawiki.legacy.block' ), // IP stuff |
| 77 | + 'localBasePath' => dirname( __FILE__ ), |
| 78 | + 'remoteExtPath' => 'CheckUser', |
| 79 | +); |
| 80 | + |
| 81 | +// TODO: move hooks to CheckUser.hooks.php |
| 82 | + |
75 | 83 | /** |
76 | 84 | * Hook function for RecentChange_save |
77 | 85 | * Saves user data into the cu_changes table |
Index: trunk/extensions/CheckUser/checkuser.js |
— | — | @@ -6,7 +6,7 @@ |
7 | 7 | * This function calculates the common range of a list of |
8 | 8 | * IPs. It should be set to update on keyUp. |
9 | 9 | */ |
10 | | -function updateCIDRresult() { |
| 10 | +window.updateCIDRresult = function() { |
11 | 11 | var form = document.getElementById( 'mw-checkuser-cidrform' ); |
12 | 12 | if( !form ) { |
13 | 13 | return; // no JS form |
— | — | @@ -20,7 +20,7 @@ |
21 | 21 | // Each line should have one IP or range |
22 | 22 | if( text.indexOf("\n") != -1 ) { |
23 | 23 | var ips = text.split("\n"); |
24 | | - // Try some other delimiters too |
| 24 | + // Try some other delimiters too... |
25 | 25 | } else if( text.indexOf("\t") != -1 ) { |
26 | 26 | var ips = text.split("\t"); |
27 | 27 | } else if( text.indexOf(",") != -1 ) { |
— | — | @@ -35,24 +35,29 @@ |
36 | 36 | var bin_prefix = 0; |
37 | 37 | var prefix_cidr = 0; |
38 | 38 | var prefix = new String( '' ); |
| 39 | + var foundV4 = false; |
| 40 | + var foundV6 = false; |
39 | 41 | // Go through each IP in the list, get its binary form, and |
40 | 42 | // track the largest binary prefix among them... |
41 | 43 | for( var i = 0; i < ips.length; i++ ) { |
42 | 44 | var invalid = false; |
43 | 45 | // ...in the spirit of block.js, call this "addy" |
44 | | - var addy = ips[i]; |
45 | | - // @TODO: get some core JS IP functions |
| 46 | + var addy = ips[i].replace(/^\s*|\s*$/, '' ); // trim |
46 | 47 | // Match the first IP in each list (ignore other garbage) |
47 | | - var ipV4 = addy.match(/(^|\b)(\d+\.\d+\.\d+\.\d+)(\/\d+)?\b/); |
48 | | - // Regexp has 3 cases: (starts with '::',ends with '::',neither) |
49 | | - var ipV6 = !addy.match(/::.*::/) // not ambiguous |
50 | | - && addy.match(/(^|\b)(:(:[0-9A-Fa-f]{1,4}){1,7}|[0-9A-Fa-f]{1,4}(::?[0-9A-Fa-f]{1,4}){0,6}::|[0-9A-Fa-f]{1,4}(::?[0-9A-Fa-f]{1,4}){1,7})(\/\d+)?\b/); |
| 48 | + var ipV4 = isIPv4Address( addy, true ); // from block.js |
| 49 | + var ipV6 = isIPv6Address( addy, true ); // from block.js |
| 50 | + var ip_cidr = addy.match(/^(.*)(?:\/(\d+))?$/); |
51 | 51 | // Binary form |
52 | 52 | var bin = new String( '' ); |
53 | 53 | // Convert the IP to binary form: IPv4 |
54 | 54 | if( ipV4 ) { |
55 | | - var ip = ipV4[2]; |
56 | | - var cidr = ipV4[3]; // CIDR, if it exists |
| 55 | + foundV4 = true; |
| 56 | + if ( foundV6 ) { // disjoint address space |
| 57 | + prefix = ''; |
| 58 | + break; |
| 59 | + } |
| 60 | + var ip = ip_cidr[1]; |
| 61 | + var cidr = ip_cidr[2] ? ip_cidr[2] : null; // CIDR, if it exists |
57 | 62 | // Get each quad integer |
58 | 63 | var blocs = ip.split('.'); |
59 | 64 | // IANA 1.0.0.0/8, 2.0.0.0/8 |
— | — | @@ -77,7 +82,6 @@ |
78 | 83 | prefix = ''; // Rebuild formatted bin_prefix for each IP |
79 | 84 | // Apply any valid CIDRs |
80 | 85 | if( cidr ) { |
81 | | - cidr = cidr.match( /\d+$/ )[0]; // get rid of slash |
82 | 86 | bin = bin.substring( 0, cidr ); // truncate bin |
83 | 87 | } |
84 | 88 | // Init bin_prefix |
— | — | @@ -122,14 +126,15 @@ |
123 | 127 | } |
124 | 128 | // Convert the IP to binary form: IPv6 |
125 | 129 | } else if( ipV6 ) { |
126 | | - var ip = ipV6[2]; |
127 | | - var cidr = ipV6[0].match( /\/\d+$/ ); |
128 | | - cidr = cidr ? cidr[0] : false; |
129 | | - var abbrevs = ip.match( /::/g ); |
130 | | - if( abbrevs && abbrevs.length > 1 ) { |
131 | | - continue; // bad IP! |
| 130 | + foundV6 = true; |
| 131 | + if ( foundV4 ) { // disjoint address space |
| 132 | + prefix = ''; |
| 133 | + break; |
132 | 134 | } |
| 135 | + var ip = ip_cidr[1]; |
| 136 | + var cidr = ip_cidr[2] ? ip_cidr[2] : null; // CIDR, if it exists |
133 | 137 | // Expand out "::"s |
| 138 | + var abbrevs = ip.match( /::/g ); |
134 | 139 | if( abbrevs && abbrevs.length > 0 ) { |
135 | 140 | var colons = ip.match( /:/g ); |
136 | 141 | var needed = 7 - ( colons.length - 2 ); // 2 from "::" |
— | — | @@ -139,7 +144,8 @@ |
140 | 145 | needed--; |
141 | 146 | } |
142 | 147 | ip = ip.replace( '::', insert + ':' ); |
143 | | - // For IPs that start with "::", correct the final IP so that it starts with '0' and not ':' |
| 148 | + // For IPs that start with "::", correct the final IP |
| 149 | + // so that it starts with '0' and not ':' |
144 | 150 | if( ip[0] == ':' ) { |
145 | 151 | ip = '0' + ip; |
146 | 152 | } |
— | — | @@ -165,7 +171,6 @@ |
166 | 172 | prefix = ''; // Rebuild formatted bin_prefix for each IP |
167 | 173 | // Apply any valid CIDRs |
168 | 174 | if( cidr ) { |
169 | | - cidr = cidr.match( /\d+$/ )[0]; // get rid of slash |
170 | 175 | bin = bin.substring( 0, cidr ); // truncate bin |
171 | 176 | } |
172 | 177 | // Init bin_prefix |
— | — | @@ -228,7 +233,7 @@ |
229 | 234 | addOnloadHook( updateCIDRresult ); |
230 | 235 | |
231 | 236 | // Utility function to convert hex to integers |
232 | | -function hex2int( hex ) { |
| 237 | +window.hex2int = function( hex ) { |
233 | 238 | hex = new String( hex ); |
234 | 239 | hex = hex.toLowerCase(); |
235 | 240 | var intform = 0; |