define( 'RE_IPV6_WORD', '([0-9A-Fa-f]{1,4})' );
define( 'RE_IPV6_PREFIX', '(12[0-8]|1[01][0-9]|[1-9]?\d)');
define( 'RE_IPV6_ADD',
- '(?:' . // starts with "::" (includes the address "::")
- '::|:(?::' . RE_IPV6_WORD . '){1,7}' .
- '|' . // ends with "::" (not including the address "::")
+ '(?:' . // starts with "::" (including "::")
+ ':(?::|(?::' . RE_IPV6_WORD . '){1,7})' .
+ '|' . // ends with "::" (except "::")
RE_IPV6_WORD . '(?::' . RE_IPV6_WORD . '){0,6}::' .
- '|' . // has no "::"
- RE_IPV6_WORD . '(?::' . RE_IPV6_WORD . '){7}' .
- '|' . // contains one "::" in the middle (awkward regex for PCRE 4.0+ compatibility)
- RE_IPV6_WORD . '(?::(?P<abn>(?!(?P=abn)):(?P<iabn>))?' . RE_IPV6_WORD . '){1,6}(?P=iabn)' .
+ '|' . // contains one "::" in the middle, ending in "::WORD"
+ RE_IPV6_WORD . '(?::' . RE_IPV6_WORD . '){0,5}' . '::' . RE_IPV6_WORD .
+ '|' . // contains one "::" in the middle, not ending in "::WORD" (regex for PCRE 4.0+)
+ RE_IPV6_WORD . '(?::(?P<abn>:(?P<iabn>))?' . RE_IPV6_WORD . '(?!:(?P=abn))){1,5}' .
+ ':' . RE_IPV6_WORD . '(?P=iabn)' .
// NOTE: (?!(?P=abn)) fails iff "::" used twice; (?P=iabn) passes iff a "::" was found.
-
- // Better regexp (PCRE 7.2+ only), allows intuitive regex concatenation
- #RE_IPV6_WORD . '(?::((?(-1)|:))?' . RE_IPV6_WORD . '){1,6}(?(-2)|^)' .
+ '|' . // contains no "::"
+ RE_IPV6_WORD . '(?::' . RE_IPV6_WORD . '){7}' .
')'
+ // NOTE: With PCRE 7.2+, we can combine the two '"::" in the middle' cases into:
+ // RE_IPV6_WORD . '(?::((?(-1)|:))?' . RE_IPV6_WORD . '){1,6}(?(-2)|^)'
+ // This also improves regex concatenation by using relative references.
);
// An IPv6 block is an IP address and a prefix (d1 to d128)
define( 'RE_IPV6_BLOCK', RE_IPV6_ADD . '\/' . RE_IPV6_PREFIX );
// IPv6 loopback address
$m = array();
if ( preg_match( '/^0*' . RE_IPV6_GAP . '1$/', $addr, $m ) ) {
- return '127.0.0.1';
+ return '127.0.0.1';
}
// IPv4-mapped and IPv4-compatible IPv6 addresses
if ( preg_match( '/^' . RE_IPV6_V4_PREFIX . '(' . RE_IP_ADD . ')$/i', $addr, $m ) ) {
return null; // give up
}
+
+ /**
+ * Gets rid of uneeded numbers in quad-dotted/octet IP strings
+ * For example, 127.111.113.151/24 -> 127.111.113.0/24
+ * @param $range String: IP address to normalize
+ * @return string
+ */
+ public static function sanitizeRange( $range ){
+ list( /*...*/, $bits ) = self::parseCIDR( $range );
+ list( $start, /*...*/ ) = self::parseRange( $range );
+ $start = self::formatHex( $start );
+ return "$start/$bits";
+ }
}