MediaWiki
REL1_23
|
00001 <?php 00012 class IPTest extends MediaWikiTestCase { 00017 public function testisIPAddress() { 00018 $this->assertFalse( IP::isIPAddress( false ), 'Boolean false is not an IP' ); 00019 $this->assertFalse( IP::isIPAddress( true ), 'Boolean true is not an IP' ); 00020 $this->assertFalse( IP::isIPAddress( "" ), 'Empty string is not an IP' ); 00021 $this->assertFalse( IP::isIPAddress( 'abc' ), 'Garbage IP string' ); 00022 $this->assertFalse( IP::isIPAddress( ':' ), 'Single ":" is not an IP' ); 00023 $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::1' ), 'IPv6 with a double :: occurrence' ); 00024 $this->assertFalse( 00025 IP::isIPAddress( '2001:0DB8::A:1::' ), 00026 'IPv6 with a double :: occurrence, last at end' 00027 ); 00028 $this->assertFalse( 00029 IP::isIPAddress( '::2001:0DB8::5:1' ), 00030 'IPv6 with a double :: occurrence, firt at beginning' 00031 ); 00032 $this->assertFalse( IP::isIPAddress( '124.24.52' ), 'IPv4 not enough quads' ); 00033 $this->assertFalse( IP::isIPAddress( '24.324.52.13' ), 'IPv4 out of range' ); 00034 $this->assertFalse( IP::isIPAddress( '.24.52.13' ), 'IPv4 starts with period' ); 00035 $this->assertFalse( IP::isIPAddress( 'fc:100:300' ), 'IPv6 with only 3 words' ); 00036 00037 $this->assertTrue( IP::isIPAddress( '::' ), 'RFC 4291 IPv6 Unspecified Address' ); 00038 $this->assertTrue( IP::isIPAddress( '::1' ), 'RFC 4291 IPv6 Loopback Address' ); 00039 $this->assertTrue( IP::isIPAddress( '74.24.52.13/20', 'IPv4 range' ) ); 00040 $this->assertTrue( IP::isIPAddress( 'fc:100:a:d:1:e:ac:0/24' ), 'IPv6 range' ); 00041 $this->assertTrue( IP::isIPAddress( 'fc::100:a:d:1:e:ac/96' ), 'IPv6 range with "::"' ); 00042 00043 $validIPs = array( 'fc:100::', 'fc:100:a:d:1:e:ac::', 'fc::100', '::fc:100:a:d:1:e:ac', 00044 '::fc', 'fc::100:a:d:1:e:ac', 'fc:100:a:d:1:e:ac:0', '124.24.52.13', '1.24.52.13' ); 00045 foreach ( $validIPs as $ip ) { 00046 $this->assertTrue( IP::isIPAddress( $ip ), "$ip is a valid IP address" ); 00047 } 00048 } 00049 00053 public function testisIPv6() { 00054 $this->assertFalse( IP::isIPv6( ':fc:100::' ), 'IPv6 starting with lone ":"' ); 00055 $this->assertFalse( IP::isIPv6( 'fc:100:::' ), 'IPv6 ending with a ":::"' ); 00056 $this->assertFalse( IP::isIPv6( 'fc:300' ), 'IPv6 with only 2 words' ); 00057 $this->assertFalse( IP::isIPv6( 'fc:100:300' ), 'IPv6 with only 3 words' ); 00058 00059 $this->assertTrue( IP::isIPv6( 'fc:100::' ) ); 00060 $this->assertTrue( IP::isIPv6( 'fc:100:a::' ) ); 00061 $this->assertTrue( IP::isIPv6( 'fc:100:a:d::' ) ); 00062 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1::' ) ); 00063 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e::' ) ); 00064 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac::' ) ); 00065 00066 $this->assertFalse( IP::isIPv6( 'fc:100:a:d:1:e:ac:0::' ), 'IPv6 with 8 words ending with "::"' ); 00067 $this->assertFalse( 00068 IP::isIPv6( 'fc:100:a:d:1:e:ac:0:1::' ), 00069 'IPv6 with 9 words ending with "::"' 00070 ); 00071 00072 $this->assertFalse( IP::isIPv6( ':::' ) ); 00073 $this->assertFalse( IP::isIPv6( '::0:' ), 'IPv6 ending in a lone ":"' ); 00074 00075 $this->assertTrue( IP::isIPv6( '::' ), 'IPv6 zero address' ); 00076 $this->assertTrue( IP::isIPv6( '::0' ) ); 00077 $this->assertTrue( IP::isIPv6( '::fc' ) ); 00078 $this->assertTrue( IP::isIPv6( '::fc:100' ) ); 00079 $this->assertTrue( IP::isIPv6( '::fc:100:a' ) ); 00080 $this->assertTrue( IP::isIPv6( '::fc:100:a:d' ) ); 00081 $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1' ) ); 00082 $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1:e' ) ); 00083 $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1:e:ac' ) ); 00084 00085 $this->assertFalse( IP::isIPv6( '::fc:100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' ); 00086 $this->assertFalse( IP::isIPv6( '::fc:100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' ); 00087 00088 $this->assertFalse( IP::isIPv6( ':fc::100' ), 'IPv6 starting with lone ":"' ); 00089 $this->assertFalse( IP::isIPv6( 'fc::100:' ), 'IPv6 ending with lone ":"' ); 00090 $this->assertFalse( IP::isIPv6( 'fc:::100' ), 'IPv6 with ":::" in the middle' ); 00091 00092 $this->assertTrue( IP::isIPv6( 'fc::100' ), 'IPv6 with "::" and 2 words' ); 00093 $this->assertTrue( IP::isIPv6( 'fc::100:a' ), 'IPv6 with "::" and 3 words' ); 00094 $this->assertTrue( IP::isIPv6( 'fc::100:a:d', 'IPv6 with "::" and 4 words' ) ); 00095 $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' ); 00096 $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e' ), 'IPv6 with "::" and 6 words' ); 00097 $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' ); 00098 $this->assertTrue( IP::isIPv6( '2001::df' ), 'IPv6 with "::" and 2 words' ); 00099 $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' ); 00100 $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' ); 00101 00102 $this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' ); 00103 $this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' ); 00104 00105 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac:0' ) ); 00106 } 00107 00111 public function testisIPv4() { 00112 $this->assertFalse( IP::isIPv4( false ), 'Boolean false is not an IP' ); 00113 $this->assertFalse( IP::isIPv4( true ), 'Boolean true is not an IP' ); 00114 $this->assertFalse( IP::isIPv4( "" ), 'Empty string is not an IP' ); 00115 $this->assertFalse( IP::isIPv4( 'abc' ) ); 00116 $this->assertFalse( IP::isIPv4( ':' ) ); 00117 $this->assertFalse( IP::isIPv4( '124.24.52' ), 'IPv4 not enough quads' ); 00118 $this->assertFalse( IP::isIPv4( '24.324.52.13' ), 'IPv4 out of range' ); 00119 $this->assertFalse( IP::isIPv4( '.24.52.13' ), 'IPv4 starts with period' ); 00120 00121 $this->assertTrue( IP::isIPv4( '124.24.52.13' ) ); 00122 $this->assertTrue( IP::isIPv4( '1.24.52.13' ) ); 00123 $this->assertTrue( IP::isIPv4( '74.24.52.13/20', 'IPv4 range' ) ); 00124 } 00125 00129 public function testValidIPs() { 00130 foreach ( range( 0, 255 ) as $i ) { 00131 $a = sprintf( "%03d", $i ); 00132 $b = sprintf( "%02d", $i ); 00133 $c = sprintf( "%01d", $i ); 00134 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) { 00135 $ip = "$f.$f.$f.$f"; 00136 $this->assertTrue( IP::isValid( $ip ), "$ip is a valid IPv4 address" ); 00137 } 00138 } 00139 foreach ( range( 0x0, 0xFFFF, 0xF ) as $i ) { 00140 $a = sprintf( "%04x", $i ); 00141 $b = sprintf( "%03x", $i ); 00142 $c = sprintf( "%02x", $i ); 00143 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) { 00144 $ip = "$f:$f:$f:$f:$f:$f:$f:$f"; 00145 $this->assertTrue( IP::isValid( $ip ), "$ip is a valid IPv6 address" ); 00146 } 00147 } 00148 // test with some abbreviations 00149 $this->assertFalse( IP::isValid( ':fc:100::' ), 'IPv6 starting with lone ":"' ); 00150 $this->assertFalse( IP::isValid( 'fc:100:::' ), 'IPv6 ending with a ":::"' ); 00151 $this->assertFalse( IP::isValid( 'fc:300' ), 'IPv6 with only 2 words' ); 00152 $this->assertFalse( IP::isValid( 'fc:100:300' ), 'IPv6 with only 3 words' ); 00153 00154 $this->assertTrue( IP::isValid( 'fc:100::' ) ); 00155 $this->assertTrue( IP::isValid( 'fc:100:a:d:1:e::' ) ); 00156 $this->assertTrue( IP::isValid( 'fc:100:a:d:1:e:ac::' ) ); 00157 00158 $this->assertTrue( IP::isValid( 'fc::100' ), 'IPv6 with "::" and 2 words' ); 00159 $this->assertTrue( IP::isValid( 'fc::100:a' ), 'IPv6 with "::" and 3 words' ); 00160 $this->assertTrue( IP::isValid( '2001::df' ), 'IPv6 with "::" and 2 words' ); 00161 $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' ); 00162 $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' ); 00163 $this->assertTrue( IP::isValid( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' ); 00164 $this->assertTrue( IP::isValid( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' ); 00165 00166 $this->assertFalse( 00167 IP::isValid( 'fc:100:a:d:1:e:ac:0::' ), 00168 'IPv6 with 8 words ending with "::"' 00169 ); 00170 $this->assertFalse( 00171 IP::isValid( 'fc:100:a:d:1:e:ac:0:1::' ), 00172 'IPv6 with 9 words ending with "::"' 00173 ); 00174 } 00175 00179 public function testInvalidIPs() { 00180 // Out of range... 00181 foreach ( range( 256, 999 ) as $i ) { 00182 $a = sprintf( "%03d", $i ); 00183 $b = sprintf( "%02d", $i ); 00184 $c = sprintf( "%01d", $i ); 00185 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) { 00186 $ip = "$f.$f.$f.$f"; 00187 $this->assertFalse( IP::isValid( $ip ), "$ip is not a valid IPv4 address" ); 00188 } 00189 } 00190 foreach ( range( 'g', 'z' ) as $i ) { 00191 $a = sprintf( "%04s", $i ); 00192 $b = sprintf( "%03s", $i ); 00193 $c = sprintf( "%02s", $i ); 00194 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) { 00195 $ip = "$f:$f:$f:$f:$f:$f:$f:$f"; 00196 $this->assertFalse( IP::isValid( $ip ), "$ip is not a valid IPv6 address" ); 00197 } 00198 } 00199 // Have CIDR 00200 $ipCIDRs = array( 00201 '212.35.31.121/32', 00202 '212.35.31.121/18', 00203 '212.35.31.121/24', 00204 '::ff:d:321:5/96', 00205 'ff::d3:321:5/116', 00206 'c:ff:12:1:ea:d:321:5/120', 00207 ); 00208 foreach ( $ipCIDRs as $i ) { 00209 $this->assertFalse( IP::isValid( $i ), 00210 "$i is an invalid IP address because it is a block" ); 00211 } 00212 // Incomplete/garbage 00213 $invalid = array( 00214 'www.xn--var-xla.net', 00215 '216.17.184.G', 00216 '216.17.184.1.', 00217 '216.17.184', 00218 '216.17.184.', 00219 '256.17.184.1' 00220 ); 00221 foreach ( $invalid as $i ) { 00222 $this->assertFalse( IP::isValid( $i ), "$i is an invalid IP address" ); 00223 } 00224 } 00225 00229 public function testValidBlocks() { 00230 $valid = array( 00231 '116.17.184.5/32', 00232 '0.17.184.5/30', 00233 '16.17.184.1/24', 00234 '30.242.52.14/1', 00235 '10.232.52.13/8', 00236 '30.242.52.14/0', 00237 '::e:f:2001/96', 00238 '::c:f:2001/128', 00239 '::10:f:2001/70', 00240 '::fe:f:2001/1', 00241 '::6d:f:2001/8', 00242 '::fe:f:2001/0', 00243 ); 00244 foreach ( $valid as $i ) { 00245 $this->assertTrue( IP::isValidBlock( $i ), "$i is a valid IP block" ); 00246 } 00247 } 00248 00252 public function testInvalidBlocks() { 00253 $invalid = array( 00254 '116.17.184.5/33', 00255 '0.17.184.5/130', 00256 '16.17.184.1/-1', 00257 '10.232.52.13/*', 00258 '7.232.52.13/ab', 00259 '11.232.52.13/', 00260 '::e:f:2001/129', 00261 '::c:f:2001/228', 00262 '::10:f:2001/-1', 00263 '::6d:f:2001/*', 00264 '::86:f:2001/ab', 00265 '::23:f:2001/', 00266 ); 00267 foreach ( $invalid as $i ) { 00268 $this->assertFalse( IP::isValidBlock( $i ), "$i is not a valid IP block" ); 00269 } 00270 } 00271 00276 public function testSanitizeIP() { 00277 $this->assertNull( IP::sanitizeIP( '' ) ); 00278 $this->assertNull( IP::sanitizeIP( ' ' ) ); 00279 } 00280 00285 public function testToUnsigned( $expected, $input ) { 00286 $result = IP::toUnsigned( $input ); 00287 $this->assertTrue( $result === false || is_string( $result ) || is_int( $result ) ); 00288 $this->assertEquals( $expected, $result ); 00289 } 00290 00294 public static function provideToUnsigned() { 00295 return array( 00296 array( 1, '0.0.0.1' ), 00297 array( 16909060, '1.2.3.4' ), 00298 array( 2130706433, '127.0.0.1' ), 00299 array( '2147483648', '128.0.0.0' ), 00300 array( 2130706440, '127.0.0.08' ), 00301 array( 2130706441, '127.0.0.09' ), 00302 array( '3735931646', '222.173.202.254' ), 00303 array( pow( 2, 32 ) - 1, '255.255.255.255' ), 00304 array( false, 'IN.VA.LI.D' ), 00305 array( 1, '::1' ), 00306 array( '42540766452641154071740215577757643572', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ), 00307 array( '42540766452641154071740215577757643572', '2001:db8:85a3::8a2e:0370:7334' ), 00308 array( false, 'IN:VA::LI:D' ), 00309 array( false, ':::1' ) 00310 ); 00311 } 00312 00317 public function testToHex( $expected, $input ) { 00318 $result = IP::toHex( $input ); 00319 $this->assertTrue( $result === false || is_string( $result ) ); 00320 $this->assertEquals( $expected, $result ); 00321 } 00322 00326 public static function provideToHex() { 00327 return array( 00328 array( '00000001', '0.0.0.1' ), 00329 array( '01020304', '1.2.3.4' ), 00330 array( '7F000001', '127.0.0.1' ), 00331 array( '80000000', '128.0.0.0' ), 00332 array( 'DEADCAFE', '222.173.202.254' ), 00333 array( 'FFFFFFFF', '255.255.255.255' ), 00334 array( false, 'IN.VA.LI.D' ), 00335 array( 'v6-00000000000000000000000000000001', '::1' ), 00336 array( 'v6-20010DB885A3000000008A2E03707334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ), 00337 array( 'v6-20010DB885A3000000008A2E03707334', '2001:db8:85a3::8a2e:0370:7334' ), 00338 array( false, 'IN:VA::LI:D' ), 00339 array( false, ':::1' ) 00340 ); 00341 } 00342 00346 public function testPrivateIPs() { 00347 $private = array( 'fc00::3', 'fc00::ff', '::1', '10.0.0.1', '172.16.0.1', '192.168.0.1' ); 00348 foreach ( $private as $p ) { 00349 $this->assertFalse( IP::isPublic( $p ), "$p is not a public IP address" ); 00350 } 00351 $public = array( '2001:5c0:1000:a::133', 'fc::3', '00FC::' ); 00352 foreach ( $public as $p ) { 00353 $this->assertTrue( IP::isPublic( $p ), "$p is a public IP address" ); 00354 } 00355 } 00356 00357 // Private wrapper used to test CIDR Parsing. 00358 private function assertFalseCIDR( $CIDR, $msg = '' ) { 00359 $ff = array( false, false ); 00360 $this->assertEquals( $ff, IP::parseCIDR( $CIDR ), $msg ); 00361 } 00362 00363 // Private wrapper to test network shifting using only dot notation 00364 private function assertNet( $expected, $CIDR ) { 00365 $parse = IP::parseCIDR( $CIDR ); 00366 $this->assertEquals( $expected, long2ip( $parse[0] ), "network shifting $CIDR" ); 00367 } 00368 00372 public function testHexToQuad() { 00373 $this->assertEquals( '0.0.0.1', IP::hexToQuad( '00000001' ) ); 00374 $this->assertEquals( '255.0.0.0', IP::hexToQuad( 'FF000000' ) ); 00375 $this->assertEquals( '255.255.255.255', IP::hexToQuad( 'FFFFFFFF' ) ); 00376 $this->assertEquals( '10.188.222.255', IP::hexToQuad( '0ABCDEFF' ) ); 00377 // hex not left-padded... 00378 $this->assertEquals( '0.0.0.0', IP::hexToQuad( '0' ) ); 00379 $this->assertEquals( '0.0.0.1', IP::hexToQuad( '1' ) ); 00380 $this->assertEquals( '0.0.0.255', IP::hexToQuad( 'FF' ) ); 00381 $this->assertEquals( '0.0.255.0', IP::hexToQuad( 'FF00' ) ); 00382 } 00383 00387 public function testHexToOctet() { 00388 $this->assertEquals( '0:0:0:0:0:0:0:1', 00389 IP::hexToOctet( '00000000000000000000000000000001' ) ); 00390 $this->assertEquals( '0:0:0:0:0:0:FF:3', 00391 IP::hexToOctet( '00000000000000000000000000FF0003' ) ); 00392 $this->assertEquals( '0:0:0:0:0:0:FF00:6', 00393 IP::hexToOctet( '000000000000000000000000FF000006' ) ); 00394 $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF', 00395 IP::hexToOctet( '000000000000000000000000FCCFFAFF' ) ); 00396 $this->assertEquals( 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF', 00397 IP::hexToOctet( 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ) ); 00398 // hex not left-padded... 00399 $this->assertEquals( '0:0:0:0:0:0:0:0', IP::hexToOctet( '0' ) ); 00400 $this->assertEquals( '0:0:0:0:0:0:0:1', IP::hexToOctet( '1' ) ); 00401 $this->assertEquals( '0:0:0:0:0:0:0:FF', IP::hexToOctet( 'FF' ) ); 00402 $this->assertEquals( '0:0:0:0:0:0:0:FFD0', IP::hexToOctet( 'FFD0' ) ); 00403 $this->assertEquals( '0:0:0:0:0:0:FA00:0', IP::hexToOctet( 'FA000000' ) ); 00404 $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF', IP::hexToOctet( 'FCCFFAFF' ) ); 00405 } 00406 00412 public function testCIDRParsing() { 00413 $this->assertFalseCIDR( '192.0.2.0', "missing mask" ); 00414 $this->assertFalseCIDR( '192.0.2.0/', "missing bitmask" ); 00415 00416 // Verify if statement 00417 $this->assertFalseCIDR( '256.0.0.0/32', "invalid net" ); 00418 $this->assertFalseCIDR( '192.0.2.0/AA', "mask not numeric" ); 00419 $this->assertFalseCIDR( '192.0.2.0/-1', "mask < 0" ); 00420 $this->assertFalseCIDR( '192.0.2.0/33', "mask > 32" ); 00421 00422 // Check internal logic 00423 # 0 mask always result in array(0,0) 00424 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '192.0.0.2/0' ) ); 00425 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '0.0.0.0/0' ) ); 00426 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '255.255.255.255/0' ) ); 00427 00428 // @todo FIXME: Add more tests. 00429 00430 # This part test network shifting 00431 $this->assertNet( '192.0.0.0', '192.0.0.2/24' ); 00432 $this->assertNet( '192.168.5.0', '192.168.5.13/24' ); 00433 $this->assertNet( '10.0.0.160', '10.0.0.161/28' ); 00434 $this->assertNet( '10.0.0.0', '10.0.0.3/28' ); 00435 $this->assertNet( '10.0.0.0', '10.0.0.3/30' ); 00436 $this->assertNet( '10.0.0.4', '10.0.0.4/30' ); 00437 $this->assertNet( '172.17.32.0', '172.17.35.48/21' ); 00438 $this->assertNet( '10.128.0.0', '10.135.0.0/9' ); 00439 $this->assertNet( '134.0.0.0', '134.0.5.1/8' ); 00440 } 00441 00445 public function testIPCanonicalizeOnValidIp() { 00446 $this->assertEquals( '192.0.2.152', IP::canonicalize( '192.0.2.152' ), 00447 'Canonicalization of a valid IP returns it unchanged' ); 00448 } 00449 00453 public function testIPCanonicalizeMappedAddress() { 00454 $this->assertEquals( 00455 '192.0.2.152', 00456 IP::canonicalize( '::ffff:192.0.2.152' ) 00457 ); 00458 $this->assertEquals( 00459 '192.0.2.152', 00460 IP::canonicalize( '::192.0.2.152' ) 00461 ); 00462 } 00463 00469 public function testIPIsInRange( $expected, $addr, $range, $message = '' ) { 00470 $this->assertEquals( 00471 $expected, 00472 IP::isInRange( $addr, $range ), 00473 $message 00474 ); 00475 } 00476 00478 public static function provideIPsAndRanges() { 00479 # Format: (expected boolean, address, range, optional message) 00480 return array( 00481 # IPv4 00482 array( true, '192.0.2.0', '192.0.2.0/24', 'Network address' ), 00483 array( true, '192.0.2.77', '192.0.2.0/24', 'Simple address' ), 00484 array( true, '192.0.2.255', '192.0.2.0/24', 'Broadcast address' ), 00485 00486 array( false, '0.0.0.0', '192.0.2.0/24' ), 00487 array( false, '255.255.255', '192.0.2.0/24' ), 00488 00489 # IPv6 00490 array( false, '::1', '2001:DB8::/32' ), 00491 array( false, '::', '2001:DB8::/32' ), 00492 array( false, 'FE80::1', '2001:DB8::/32' ), 00493 00494 array( true, '2001:DB8::', '2001:DB8::/32' ), 00495 array( true, '2001:0DB8::', '2001:DB8::/32' ), 00496 array( true, '2001:DB8::1', '2001:DB8::/32' ), 00497 array( true, '2001:0DB8::1', '2001:DB8::/32' ), 00498 array( true, '2001:0DB8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF', 00499 '2001:DB8::/32' ), 00500 00501 array( false, '2001:0DB8:F::', '2001:DB8::/96' ), 00502 ); 00503 } 00504 00509 public function testSplitHostAndPort( $expected, $input, $description ) { 00510 $this->assertEquals( $expected, IP::splitHostAndPort( $input ), $description ); 00511 } 00512 00516 public static function provideSplitHostAndPort() { 00517 return array( 00518 array( false, '[', 'Unclosed square bracket' ), 00519 array( false, '[::', 'Unclosed square bracket 2' ), 00520 array( array( '::', false ), '::', 'Bare IPv6 0' ), 00521 array( array( '::1', false ), '::1', 'Bare IPv6 1' ), 00522 array( array( '::', false ), '[::]', 'Bracketed IPv6 0' ), 00523 array( array( '::1', false ), '[::1]', 'Bracketed IPv6 1' ), 00524 array( array( '::1', 80 ), '[::1]:80', 'Bracketed IPv6 with port' ), 00525 array( false, '::x', 'Double colon but no IPv6' ), 00526 array( array( 'x', 80 ), 'x:80', 'Hostname and port' ), 00527 array( false, 'x:x', 'Hostname and invalid port' ), 00528 array( array( 'x', false ), 'x', 'Plain hostname' ) 00529 ); 00530 } 00531 00536 public function testCombineHostAndPort( $expected, $input, $description ) { 00537 list( $host, $port, $defaultPort ) = $input; 00538 $this->assertEquals( 00539 $expected, 00540 IP::combineHostAndPort( $host, $port, $defaultPort ), 00541 $description ); 00542 } 00543 00547 public static function provideCombineHostAndPort() { 00548 return array( 00549 array( '[::1]', array( '::1', 2, 2 ), 'IPv6 default port' ), 00550 array( '[::1]:2', array( '::1', 2, 3 ), 'IPv6 non-default port' ), 00551 array( 'x', array( 'x', 2, 2 ), 'Normal default port' ), 00552 array( 'x:2', array( 'x', 2, 3 ), 'Normal non-default port' ), 00553 ); 00554 } 00555 00560 public function testSanitizeRange( $input, $expected, $description ) { 00561 $this->assertEquals( $expected, IP::sanitizeRange( $input ), $description ); 00562 } 00563 00567 public static function provideIPCIDRs() { 00568 return array( 00569 array( '35.56.31.252/16', '35.56.0.0/16', 'IPv4 range' ), 00570 array( '135.16.21.252/24', '135.16.21.0/24', 'IPv4 range' ), 00571 array( '5.36.71.252/32', '5.36.71.252/32', 'IPv4 silly range' ), 00572 array( '5.36.71.252', '5.36.71.252', 'IPv4 non-range' ), 00573 array( '0:1:2:3:4:c5:f6:7/96', '0:1:2:3:4:C5:0:0/96', 'IPv6 range' ), 00574 array( '0:1:2:3:4:5:6:7/120', '0:1:2:3:4:5:6:0/120', 'IPv6 range' ), 00575 array( '0:e1:2:3:4:5:e6:7/128', '0:E1:2:3:4:5:E6:7/128', 'IPv6 silly range' ), 00576 array( '0:c1:A2:3:4:5:c6:7', '0:C1:A2:3:4:5:C6:7', 'IPv6 non range' ), 00577 ); 00578 } 00579 00584 public function testPrettifyIP( $ip, $prettified ) { 00585 $this->assertEquals( $prettified, IP::prettifyIP( $ip ), "Prettify of $ip" ); 00586 } 00587 00591 public static function provideIPsToPrettify() { 00592 return array( 00593 array( '0:0:0:0:0:0:0:0', '::' ), 00594 array( '0:0:0::0:0:0', '::' ), 00595 array( '0:0:0:1:0:0:0:0', '0:0:0:1::' ), 00596 array( '0:0::f', '::f' ), 00597 array( '0::0:0:0:33:fef:b', '::33:fef:b' ), 00598 array( '3f:535:0:0:0:0:e:fbb', '3f:535::e:fbb' ), 00599 array( '0:0:fef:0:0:0:e:fbb', '0:0:fef::e:fbb' ), 00600 array( 'abbc:2004::0:0:0:0', 'abbc:2004::' ), 00601 array( 'cebc:2004:f:0:0:0:0:0', 'cebc:2004:f::' ), 00602 array( '0:0:0:0:0:0:0:0/16', '::/16' ), 00603 array( '0:0:0::0:0:0/64', '::/64' ), 00604 array( '0:0::f/52', '::f/52' ), 00605 array( '::0:0:33:fef:b/52', '::33:fef:b/52' ), 00606 array( '3f:535:0:0:0:0:e:fbb/48', '3f:535::e:fbb/48' ), 00607 array( '0:0:fef:0:0:0:e:fbb/96', '0:0:fef::e:fbb/96' ), 00608 array( 'abbc:2004:0:0::0:0/40', 'abbc:2004::/40' ), 00609 array( 'aebc:2004:f:0:0:0:0:0/80', 'aebc:2004:f::/80' ), 00610 ); 00611 } 00612 }