* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @author Ashar Voultoiz <hashar at free dot fr>, Aaron Schulz
+ * @author Antoine Musso <hashar at free dot fr>, Aaron Schulz
*/
// Some regex definition to "play" with IP address and IP address blocks
}
/**
- * Convert an IP into a nice standard form.
+ * Convert an IP into a verbose, uppercase, normalized form.
* IPv6 addresses in octet notation are expanded to 8 words.
* IPv4 addresses are just trimmed.
*
}
/**
- * Given a host/port string, like one might find in the host part of a URL
- * per RFC 2732, split the hostname part and the port part and return an
- * array with an element for each. If there is no port part, the array will
- * have false in place of the port. If the string was invalid in some way,
+ * Prettify an IP for display to end users.
+ * This will make it more compact and lower-case.
+ *
+ * @param $ip string
+ * @return string
+ */
+ public static function prettifyIP( $ip ) {
+ $ip = self::sanitizeIP( $ip ); // normalize (removes '::')
+ if ( self::isIPv6( $ip ) ) {
+ // Split IP into an address and a CIDR
+ if ( strpos( $ip, '/' ) !== false ) {
+ list( $ip, $cidr ) = explode( '/', $ip, 2 );
+ } else {
+ list( $ip, $cidr ) = array( $ip, '' );
+ }
+ // Get the largest slice of words with multiple zeros
+ $offset = 0;
+ $longest = $longestPos = false;
+ while ( preg_match(
+ '!(?:^|:)0(?::0)+(?:$|:)!', $ip, $m, PREG_OFFSET_CAPTURE, $offset
+ ) ) {
+ list( $match, $pos ) = $m[0]; // full match
+ if ( strlen( $match ) > strlen( $longest ) ) {
+ $longest = $match;
+ $longestPos = $pos;
+ }
+ $offset += ( $pos + strlen( $match ) ); // advance
+ }
+ if ( $longest !== false ) {
+ // Replace this portion of the string with the '::' abbreviation
+ $ip = substr_replace( $ip, '::', $longestPos, strlen( $longest ) );
+ }
+ // Add any CIDR back on
+ if ( $cidr !== '' ) {
+ $ip = "{$ip}/{$cidr}";
+ }
+ // Convert to lower case to make it more readable
+ $ip = strtolower( $ip );
+ }
+ return $ip;
+ }
+
+ /**
+ * Given a host/port string, like one might find in the host part of a URL
+ * per RFC 2732, split the hostname part and the port part and return an
+ * array with an element for each. If there is no port part, the array will
+ * have false in place of the port. If the string was invalid in some way,
* false is returned.
*
- * This was easy with IPv4 and was generally done in an ad-hoc way, but
- * with IPv6 it's somewhat more complicated due to the need to parse the
+ * This was easy with IPv4 and was generally done in an ad-hoc way, but
+ * with IPv6 it's somewhat more complicated due to the need to parse the
* square brackets and colons.
*
* A bare IPv6 address is accepted despite the lack of square brackets.
*
- * @param $both The string with the host and port
+ * @param $both string The string with the host and port
* @return array
*/
public static function splitHostAndPort( $both ) {
/**
* Given a host name and a port, combine them into host/port string like
* you might find in a URL. If the host contains a colon, wrap it in square
- * brackets like in RFC 2732. If the port matches the default port, omit
+ * brackets like in RFC 2732. If the port matches the default port, omit
* the port specification
+ *
+ * @param $host string
+ * @param $port int
+ * @param $defaultPort bool|int
+ * @return string
*/
public static function combineHostAndPort( $host, $port, $defaultPort = false ) {
if ( strpos( $host, ':' ) !== false ) {
static $privateRanges = false;
if ( !$privateRanges ) {
$privateRanges = array(
- array( 'fc::', 'fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' ), # RFC 4193 (local)
+ array( 'fc00::', 'fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' ), # RFC 4193 (local)
array( '0:0:0:0:0:0:0:1', '0:0:0:0:0:0:0:1' ), # loopback
);
}
return $n;
}
+ /**
+ * @param $ip
+ * @return String
+ */
private static function toUnsigned6( $ip ) {
return wfBaseConvert( self::IPv6ToRawHex( $ip ), 16, 10 );
}
* Convert a network specification in IPv6 CIDR notation to an
* integer network and a number of bits
*
+ * @param $range
+ *
* @return array(string, int)
*/
private static function parseCIDR6( $range ) {
* 2001:0db8:85a3::7344/96 CIDR
* 2001:0db8:85a3::7344 - 2001:0db8:85a3::7344 Explicit range
* 2001:0db8:85a3::7344/96 Single IP
+ *
+ * @param $range
+ *
* @return array(string, string)
*/
private static function parseRange6( $range ) {
* @param $range String: IP address to normalize
* @return string
*/
- public static function sanitizeRange( $range ){
+ public static function sanitizeRange( $range ) {
list( /*...*/, $bits ) = self::parseCIDR( $range );
list( $start, /*...*/ ) = self::parseRange( $range );
$start = self::formatHex( $start );
+ if ( $bits === false ) {
+ return $start; // wasn't actually a range
+ }
return "$start/$bits";
}
}