From 456177bdee4fb7690773ef1aa995bb9737573d1b Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 11 May 2012 10:53:14 -0700 Subject: [PATCH] [IP] Added an IP::prettifyIP() function for displaying IPs. Change-Id: I53b3fe70bd0091ef02740f2b8950c36a0e4cf32e --- includes/IP.php | 45 ++++++++++++++++++++++++++++++- tests/phpunit/includes/IPTest.php | 34 +++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/includes/IP.php b/includes/IP.php index e1c1f6d0a6..1828249889 100644 --- a/includes/IP.php +++ b/includes/IP.php @@ -133,7 +133,7 @@ class IP { } /** - * 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. * @@ -185,6 +185,49 @@ class IP { return $ip; } + /** + * 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 diff --git a/tests/phpunit/includes/IPTest.php b/tests/phpunit/includes/IPTest.php index e38fa7e43c..f50b2fe9be 100644 --- a/tests/phpunit/includes/IPTest.php +++ b/tests/phpunit/includes/IPTest.php @@ -1,6 +1,7 @@ assertEquals( $prettified, IP::prettifyIP( $ip ), "Prettify of $ip" ); + } + + /** + * Provider for IP::testPrettifyIP() + */ + function provideIPsToPrettify() { + return array( + array( '0:0:0:0:0:0:0:0', '::' ), + array( '0:0:0::0:0:0', '::' ), + array( '0:0:0:1:0:0:0:0', '0:0:0:1::' ), + array( '0:0::f', '::f' ), + array( '0::0:0:0:33:fef:b', '::33:fef:b' ), + array( '3f:535:0:0:0:0:e:fbb', '3f:535::e:fbb' ), + array( '0:0:fef:0:0:0:e:fbb', '0:0:fef::e:fbb' ), + array( 'abbc:2004::0:0:0:0', 'abbc:2004::' ), + array( 'cebc:2004:f:0:0:0:0:0', 'cebc:2004:f::' ), + array( '0:0:0:0:0:0:0:0/16', '::/16' ), + array( '0:0:0::0:0:0/64', '::/64' ), + array( '0:0::f/52', '::f/52' ), + array( '::0:0:33:fef:b/52', '::33:fef:b/52' ), + array( '3f:535:0:0:0:0:e:fbb/48', '3f:535::e:fbb/48' ), + array( '0:0:fef:0:0:0:e:fbb/96', '0:0:fef::e:fbb/96' ), + array( 'abbc:2004:0:0::0:0/40', 'abbc:2004::/40' ), + array( 'aebc:2004:f:0:0:0:0:0/80', 'aebc:2004:f::/80' ), + ); + } } -- 2.20.1