Deferred loading of DateFormatter.php and IP.php. Standardised IP.php function naming...
[lhc/web/wiklou.git] / includes / IP.php
1 <?php
2 /*
3 * Collection of public static functions to play with IP address
4 * and IP blocks.
5 *
6 * @Author "Ashar Voultoiz" <hashar@altern.org>
7 * @License GPL v2 or later
8 */
9
10 class IP {
11 // Some regex definition to "play" with IP address and IP address blocks
12
13 // An IP is made of 4 bytes from x00 to xFF which is d0 to d255
14 const RE_BYTE = '(25[0-5]|2[0-4]\d|1?\d{1,2})';
15 const RE_ADD = self::RE_BYTE . '\.' . self::RE_BYTE . '\.' . self::RE_BYTE . '\.' . self::RE_BYTE;
16 // An IP block is an IP address and a prefix (d1 to d32)
17 const RE_PREFIX = '(3[0-2]|[12]?\d)';
18 const RE_BLOCK = self::RE_ADD . '\/' . self::RE_PREFIX;
19
20 /**
21 * Validate an IP address.
22 * @return boolean True if it is valid.
23 */
24 public static function isValid( $ip ) {
25 return preg_match( '/^' . self::RE_ADD . '$/', $ip, $matches) ;
26 }
27
28 /**
29 * Validate an IP Block.
30 * @return boolean True if it is valid.
31 */
32 public static function isValidBlock( $ipblock ) {
33 return ( count(self::toArray($ipblock)) == 1 + 5 );
34 }
35
36 /**
37 * Determine if an IP address really is an IP address, and if it is public,
38 * i.e. not RFC 1918 or similar
39 * Comes from ProxyTools.php
40 */
41 function isPublic( $ip ) {
42 $n = IP::toUnsigned( $ip );
43 if ( !$n ) {
44 return false;
45 }
46
47 // ip2long accepts incomplete addresses, as well as some addresses
48 // followed by garbage characters. Check that it's really valid.
49 if( $ip != long2ip( $n ) ) {
50 return false;
51 }
52
53 static $privateRanges = false;
54 if ( !$privateRanges ) {
55 $privateRanges = array(
56 array( '10.0.0.0', '10.255.255.255' ), # RFC 1918 (private)
57 array( '172.16.0.0', '172.31.255.255' ), # "
58 array( '192.168.0.0', '192.168.255.255' ), # "
59 array( '0.0.0.0', '0.255.255.255' ), # this network
60 array( '127.0.0.0', '127.255.255.255' ), # loopback
61 );
62 }
63
64 foreach ( $privateRanges as $r ) {
65 $start = IP::toUnsigned( $r[0] );
66 $end = IP::toUnsigned( $r[1] );
67 if ( $n >= $start && $n <= $end ) {
68 return false;
69 }
70 }
71 return true;
72 }
73
74 /**
75 * Split out an IP block as an array of 4 bytes and a mask,
76 * return false if it cant be determined
77 *
78 * @parameter $ip string A quad dotted IP address
79 * @return array
80 */
81 public static function toArray( $ipblock ) {
82 if(! preg_match( '/^' . self::RE_ADD . '(?:\/(?:'.self::RE_PREFIX.'))?' . '$/', $ipblock, $matches ) ) {
83 return false;
84 } else {
85 return $matches;
86 }
87 }
88
89 /**
90 * Return a zero-padded hexadecimal representation of an IP address
91 * Comes from ProxyTools.php
92 * @param $ip Quad dotted IP address.
93 */
94 public static function toHex( $ip ) {
95 $n = self::toUnsigned( $ip );
96 if ( $n !== false ) {
97 $n = sprintf( '%08X', $n );
98 }
99 return $n;
100 }
101
102 /**
103 * Given an IP address in dotted-quad notation, returns an unsigned integer.
104 * Like ip2long() except that it actually works and has a consistent error return value.
105 * Comes from ProxyTools.php
106 * @param $ip Quad dotted IP address.
107 */
108 public static function toUnsigned( $ip ) {
109 $n = ip2long( $ip );
110 if ( $n == -1 || $n === false ) { # Return value on error depends on PHP version
111 $n = false;
112 } elseif ( $n < 0 ) {
113 $n += pow( 2, 32 );
114 }
115 return $n;
116 }
117 }
118 ?>