X-Git-Url: https://git.cyclocoop.org/%27.WWW_URL.%27admin/?a=blobdiff_plain;f=includes%2FIP.php;h=20760d6a28e9e4103301f727e5d86d47f7b1433c;hb=ad39f2da8660219768f46db739be66a27c8eb651;hp=9b55ad22fc04fc18ee402db86467aec83f59b777;hpb=99f39a47798bc47222064acfc0cc670ee5c70e54;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/IP.php b/includes/IP.php index 9b55ad22fc..20760d6a28 100644 --- a/includes/IP.php +++ b/includes/IP.php @@ -185,6 +185,81 @@ class 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 + * 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 + * @return array + */ + public static function splitHostAndPort( $both ) { + if ( substr( $both, 0, 1 ) === '[' ) { + if ( preg_match( '/^\[(' . RE_IPV6_ADD . ')\](?::(?P\d+))?$/', $both, $m ) ) { + if ( isset( $m['port'] ) ) { + return array( $m[1], intval( $m['port'] ) ); + } else { + return array( $m[1], false ); + } + } else { + // Square bracket found but no IPv6 + return false; + } + } + $numColons = substr_count( $both, ':' ); + if ( $numColons >= 2 ) { + // Is it a bare IPv6 address? + if ( preg_match( '/^' . RE_IPV6_ADD . '$/', $both ) ) { + return array( $both, false ); + } else { + // Not valid IPv6, but too many colons for anything else + return false; + } + } + if ( $numColons >= 1 ) { + // Host:port? + $bits = explode( ':', $both ); + if ( preg_match( '/^\d+/', $bits[1] ) ) { + return array( $bits[0], intval( $bits[1] ) ); + } else { + // Not a valid port + return false; + } + } + // Plain hostname + return array( $both, false ); + } + + /** + * 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 + * 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 ) { + $host = "[$host]"; + } + if ( $defaultPort !== false && $port == $defaultPort ) { + return $host; + } else { + return "$host:$port"; + } + } + /** * Given an unsigned integer, returns an IPv6 address in octet notation * @@ -379,6 +454,10 @@ class IP { return $n; } + /** + * @param $ip + * @return String + */ private static function toUnsigned6( $ip ) { return wfBaseConvert( self::IPv6ToRawHex( $ip ), 16, 10 ); } @@ -478,6 +557,8 @@ class IP { * 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 ) { @@ -515,6 +596,9 @@ class IP { * 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 ) {