[ticket/16189] Deprecate inet_ntop and inet_pton wrappers

PHPBB3-16189
This commit is contained in:
rubencm 2019-10-24 19:32:47 +00:00
parent ce35aa8b0b
commit f09f5bc51c
4 changed files with 170 additions and 250 deletions

View file

@ -2980,165 +2980,25 @@ function short_ipv6($ip, $length)
* @return mixed false if specified address is not valid,
* string otherwise
*/
function phpbb_ip_normalise($address)
function phpbb_ip_normalise(string $address)
{
$address = trim($address);
$ip_normalised = false;
if (empty($address) || !is_string($address))
if(filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
{
return false;
$ip_normalised = $address;
}
else if (filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
{
$ip_normalised = inet_ntop(inet_pton($address));
// If is ipv4
if(stripos($ip_normalised, '::ffff:') === 0) {
$ip_normalised = substr($ip_normalised, 7);
}
}
if (preg_match(get_preg_expression('ipv4'), $address))
{
return $address;
}
return phpbb_inet_ntop(phpbb_inet_pton($address));
}
/**
* Wrapper for inet_ntop()
*
* Converts a packed internet address to a human readable representation
* inet_ntop() is supported by PHP since 5.1.0, since 5.3.0 also on Windows.
*
* @param string $in_addr A 32bit IPv4, or 128bit IPv6 address.
*
* @return mixed false on failure,
* string otherwise
*/
function phpbb_inet_ntop($in_addr)
{
$in_addr = bin2hex($in_addr);
switch (strlen($in_addr))
{
case 8:
return implode('.', array_map('hexdec', str_split($in_addr, 2)));
case 32:
if (substr($in_addr, 0, 24) === '00000000000000000000ffff')
{
return phpbb_inet_ntop(pack('H*', substr($in_addr, 24)));
}
$parts = str_split($in_addr, 4);
$parts = preg_replace('/^0+(?!$)/', '', $parts);
$ret = implode(':', $parts);
$matches = array();
preg_match_all('/(?<=:|^)(?::?0){2,}/', $ret, $matches, PREG_OFFSET_CAPTURE);
$matches = $matches[0];
if (empty($matches))
{
return $ret;
}
$longest_match = '';
$longest_match_offset = 0;
foreach ($matches as $match)
{
if (strlen($match[0]) > strlen($longest_match))
{
$longest_match = $match[0];
$longest_match_offset = $match[1];
}
}
$ret = substr_replace($ret, '', $longest_match_offset, strlen($longest_match));
if ($longest_match_offset == strlen($ret))
{
$ret .= ':';
}
if ($longest_match_offset == 0)
{
$ret = ':' . $ret;
}
return $ret;
default:
return false;
}
}
/**
* Wrapper for inet_pton()
*
* Converts a human readable IP address to its packed in_addr representation
* inet_pton() is supported by PHP since 5.1.0, since 5.3.0 also on Windows.
*
* @param string $address A human readable IPv4 or IPv6 address.
*
* @return mixed false if address is invalid,
* in_addr representation of the given address otherwise (string)
*/
function phpbb_inet_pton($address)
{
$ret = '';
if (preg_match(get_preg_expression('ipv4'), $address))
{
foreach (explode('.', $address) as $part)
{
$ret .= ($part <= 0xF ? '0' : '') . dechex($part);
}
return pack('H*', $ret);
}
if (preg_match(get_preg_expression('ipv6'), $address))
{
$parts = explode(':', $address);
$missing_parts = 8 - count($parts) + 1;
if (substr($address, 0, 2) === '::')
{
++$missing_parts;
}
if (substr($address, -2) === '::')
{
++$missing_parts;
}
$embedded_ipv4 = false;
$last_part = end($parts);
if (preg_match(get_preg_expression('ipv4'), $last_part))
{
$parts[count($parts) - 1] = '';
$last_part = phpbb_inet_pton($last_part);
$embedded_ipv4 = true;
--$missing_parts;
}
foreach ($parts as $i => $part)
{
if (strlen($part))
{
$ret .= str_pad($part, 4, '0', STR_PAD_LEFT);
}
else if ($i && $i < count($parts) - 1)
{
$ret .= str_repeat('0000', $missing_parts);
}
}
$ret = pack('H*', $ret);
if ($embedded_ipv4)
{
$ret .= $last_part;
}
return $ret;
}
return false;
return $ip_normalised;
}
// Handler, header and footer

View file

@ -623,3 +623,151 @@ function phpbb_checkdnsrr($host, $type = 'MX')
{
return checkdnsrr($host, $type);
}
/*
* Wrapper for inet_ntop()
*
* Converts a packed internet address to a human readable representation
* inet_ntop() is supported by PHP since 5.1.0, since 5.3.0 also on Windows.
*
* @param string $in_addr A 32bit IPv4, or 128bit IPv6 address.
*
* @return mixed false on failure,
* string otherwise
*
* @deprecated 3.2.9 (To be removed: 4.0.0)
*/
function phpbb_inet_ntop($in_addr)
{
$in_addr = bin2hex($in_addr);
switch (strlen($in_addr))
{
case 8:
return implode('.', array_map('hexdec', str_split($in_addr, 2)));
case 32:
if (substr($in_addr, 0, 24) === '00000000000000000000ffff')
{
return phpbb_inet_ntop(pack('H*', substr($in_addr, 24)));
}
$parts = str_split($in_addr, 4);
$parts = preg_replace('/^0+(?!$)/', '', $parts);
$ret = implode(':', $parts);
$matches = array();
preg_match_all('/(?<=:|^)(?::?0){2,}/', $ret, $matches, PREG_OFFSET_CAPTURE);
$matches = $matches[0];
if (empty($matches))
{
return $ret;
}
$longest_match = '';
$longest_match_offset = 0;
foreach ($matches as $match)
{
if (strlen($match[0]) > strlen($longest_match))
{
$longest_match = $match[0];
$longest_match_offset = $match[1];
}
}
$ret = substr_replace($ret, '', $longest_match_offset, strlen($longest_match));
if ($longest_match_offset == strlen($ret))
{
$ret .= ':';
}
if ($longest_match_offset == 0)
{
$ret = ':' . $ret;
}
return $ret;
default:
return false;
}
}
/**
* Wrapper for inet_pton()
*
* Converts a human readable IP address to its packed in_addr representation
* inet_pton() is supported by PHP since 5.1.0, since 5.3.0 also on Windows.
*
* @param string $address A human readable IPv4 or IPv6 address.
*
* @return mixed false if address is invalid,
* in_addr representation of the given address otherwise (string)
*
* @deprecated 3.2.9 (To be removed: 4.0.0)
*/
function phpbb_inet_pton($address)
{
$ret = '';
if (preg_match(get_preg_expression('ipv4'), $address))
{
foreach (explode('.', $address) as $part)
{
$ret .= ($part <= 0xF ? '0' : '') . dechex($part);
}
return pack('H*', $ret);
}
if (preg_match(get_preg_expression('ipv6'), $address))
{
$parts = explode(':', $address);
$missing_parts = 8 - count($parts) + 1;
if (substr($address, 0, 2) === '::')
{
++$missing_parts;
}
if (substr($address, -2) === '::')
{
++$missing_parts;
}
$embedded_ipv4 = false;
$last_part = end($parts);
if (preg_match(get_preg_expression('ipv4'), $last_part))
{
$parts[count($parts) - 1] = '';
$last_part = phpbb_inet_pton($last_part);
$embedded_ipv4 = true;
--$missing_parts;
}
foreach ($parts as $i => $part)
{
if (strlen($part))
{
$ret .= str_pad($part, 4, '0', STR_PAD_LEFT);
}
else if ($i && $i < count($parts) - 1)
{
$ret .= str_repeat('0000', $missing_parts);
}
}
$ret = pack('H*', $ret);
if ($embedded_ipv4)
{
$ret .= $last_part;
}
return $ret;
}
return false;
}

View file

@ -311,49 +311,17 @@ class session
foreach ($ips as $ip)
{
if (function_exists('phpbb_ip_normalise'))
// Normalise IP address
$ip = phpbb_ip_normalise($ip);
if ($ip === false)
{
// Normalise IP address
$ip = phpbb_ip_normalise($ip);
if (empty($ip))
{
// IP address is invalid.
break;
}
// IP address is valid.
$this->ip = $ip;
// Skip legacy code.
continue;
}
if (preg_match(get_preg_expression('ipv4'), $ip))
{
$this->ip = $ip;
}
else if (preg_match(get_preg_expression('ipv6'), $ip))
{
// Quick check for IPv4-mapped address in IPv6
if (stripos($ip, '::ffff:') === 0)
{
$ipv4 = substr($ip, 7);
if (preg_match(get_preg_expression('ipv4'), $ipv4))
{
$ip = $ipv4;
}
}
$this->ip = $ip;
}
else
{
// We want to use the last valid address in the chain
// Leave foreach loop when address is invalid
// IP address is invalid.
break;
}
// IP address is valid.
$this->ip = $ip;
}
$this->load = false;

View file

@ -1,56 +0,0 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
class phpbb_network_inet_ntop_pton_test extends phpbb_test_case
{
public function data_provider()
{
return array(
array('127.0.0.1', '7f000001'),
array('192.232.131.223', 'c0e883df'),
array('13.1.68.3', '0d014403'),
array('129.144.52.38', '81903426'),
array('2001:280:0:10::5', '20010280000000100000000000000005'),
array('fe80::200:4cff:fefe:172f', 'fe8000000000000002004cfffefe172f'),
array('::', '00000000000000000000000000000000'),
array('::1', '00000000000000000000000000000001'),
array('1::', '00010000000000000000000000000000'),
array('1:1:0:0:1::', '00010001000000000001000000000000'),
array('0:2:3:4:5:6:7:8', '00000002000300040005000600070008'),
array('1:2:0:4:5:6:7:8', '00010002000000040005000600070008'),
array('1:2:3:4:5:6:7:0', '00010002000300040005000600070000'),
array('2001:0:0:1::1', '20010000000000010000000000000001'),
);
}
/**
* @dataProvider data_provider
*/
public function test_inet_ntop($address, $hex)
{
$this->assertEquals($address, phpbb_inet_ntop(pack('H*', $hex)));
}
/**
* @dataProvider data_provider
*/
public function test_inet_pton($address, $hex)
{
$this->assertEquals($hex, bin2hex(phpbb_inet_pton($address)));
}
}