- /**
- * Convert a network specification in IPv6 CIDR notation to an
- * integer network and a number of bits
- * @return array(string, int)
- */
- private static function parseCIDR6( $range ) {
- # Explode into <expanded IP,range>
- $parts = explode( '/', IP::sanitizeIP( $range ), 2 );
- if ( count( $parts ) != 2 ) {
- return array( false, false );
- }
- list( $network, $bits ) = $parts;
- $network = self::IPv6ToRawHex( $network );
- if ( $network !== false && is_numeric( $bits ) && $bits >= 0 && $bits <= 128 ) {
- if ( $bits == 0 ) {
- $network = "0";
- } else {
- # Native 32 bit functions WONT work here!!!
- # Convert to a padded binary number
- $network = wfBaseConvert( $network, 16, 2, 128 );
- # Truncate the last (128-$bits) bits and replace them with zeros
- $network = str_pad( substr( $network, 0, $bits ), 128, 0, STR_PAD_RIGHT );
- # Convert back to an integer
- $network = wfBaseConvert( $network, 2, 10 );
- }
- } else {
- $network = false;
- $bits = false;
- }
- return array( $network, (int)$bits );
- }
-
- /**
- * Given a string range in a number of formats, return the
- * start and end of the range in hexadecimal. For IPv6.
- *
- * Formats are:
- * 2001:0db8:85a3::7344/96 CIDR
- * 2001:0db8:85a3::7344 - 2001:0db8:85a3::7344 Explicit range
- * 2001:0db8:85a3::7344/96 Single IP
- * @return array(string, int)
- */
- private static function parseRange6( $range ) {
- # Expand any IPv6 IP
- $range = IP::sanitizeIP( $range );
- // CIDR notation...
- if ( strpos( $range, '/' ) !== false ) {
- list( $network, $bits ) = self::parseCIDR6( $range );
- if ( $network === false ) {
- $start = $end = false;
- } else {
- $start = wfBaseConvert( $network, 10, 16, 32, false );
- # Turn network to binary (again)
- $end = wfBaseConvert( $network, 10, 2, 128 );
- # Truncate the last (128-$bits) bits and replace them with ones
- $end = str_pad( substr( $end, 0, $bits ), 128, 1, STR_PAD_RIGHT );
- # Convert to hex
- $end = wfBaseConvert( $end, 2, 16, 32, false );
- # see toHex() comment
- $start = "v6-$start";
- $end = "v6-$end";
- }
- // Explicit range notation...
- } elseif ( strpos( $range, '-' ) !== false ) {
- list( $start, $end ) = array_map( 'trim', explode( '-', $range, 2 ) );
- $start = self::toUnsigned6( $start );
- $end = self::toUnsigned6( $end );
- if ( $start > $end ) {
- $start = $end = false;
- } else {
- $start = wfBaseConvert( $start, 10, 16, 32, false );
- $end = wfBaseConvert( $end, 10, 16, 32, false );
- }
- # see toHex() comment
- $start = "v6-$start";
- $end = "v6-$end";
- } else {
- # Single IP
- $start = $end = self::toHex( $range );
- }
- if ( $start === false || $end === false ) {
- return array( false, false );
- } else {
- return array( $start, $end );
- }
- }
-
- /**
- * Validate an IP address. Ranges are NOT considered valid.
- * @param string $ip
- * @return boolean True if it is valid.
- */
- public static function isValid( $ip ) {
- return ( preg_match( '/^' . RE_IP_ADD . '$/', $ip )
- || preg_match( '/^' . RE_IPV6_ADD . '$/', $ip ) );
- }
-
- /**
- * Validate an IP Block (valid address WITH a valid prefix).
- * @param string $ipblock
- * @return boolean True if it is valid.
- */
- public static function isValidBlock( $ipblock ) {
- return ( preg_match( '/^' . RE_IPV6_BLOCK . '$/', $ipblock )
- || preg_match( '/^' . RE_IPV4_BLOCK . '$/', $ipblock ) );
- }
-