2 issues in session_begin()'s handling of REMOTE_ADDR and HTTP_X_FORWARDED_FOR:
1. the regex done on both $this->ip and $this->forwarded_for is redundant and adds a considerable delay
Code: Select all
$this->ip = preg_replace('#[ ]{2,}#', ' ', str_replace(array(',', ' '), ' ', $this->ip));
Consider the follow demo (phpbb's regex vs. modified regex):
Code: Select all
<?php
function show_ips($ip_ary, $start, $end)
{
echo "<pre>\n";
foreach ($ip_ary as $ip) echo $ip . "\n";
echo "</pre>\n";
$time = round(($end-$start)*1000,6);
echo 'Took: '.$time.' ms<br /><br /><br />'."\n\n\n";
}
$ips = array(
'1.2.3.4',
'1.2.3.4 1.2.3.5',
'1.2.3.4 1.2.3.5',
'1.2.3.4 1.2.3.5',
'1.2.3.4,1.2.3.5',
'1.2.3.4, 1.2.3.5',
'1.2.3.4 , 1.2.3.5',
'1.2.3.4 , 1.2.3.5 , 1.2.3.6',
"1.2.3.4,1.2.3.5, 1.2.3.6 1.2.3.7",
);
echo '<b>phpBB:</b><br />'."\n";
$s = microtime(true);
$ips_ary = preg_replace('#[ ]{2,}#', ' ', str_replace(array(',', ' '), ' ', $ips));
$e = microtime(true);
show_ips($ips_ary, $s, $e);
// Cleanup
unset($s, $e, $ips_ary);
echo '<b>MOD:</b><br />'."\n";
$s = microtime(true);
$ips_ary = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $ips));
$e = microtime(true);
show_ips($ips_ary, $s, $e);
?>
2. Additional code, which is seldom needed, is executed every time. That is, REMOTE_ADDR rarely contains spaces or commas (and multiple addresses). This could be alleviated by using strpos in an if statement to check if $this->ip contains a comma or a space.phpBB:
1.2.3.4
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5 1.2.3.6
1.2.3.4 1.2.3.5 1.2.3.6 1.2.3.7
Took: 0.046015 ms
MOD:
1.2.3.4
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5
1.2.3.4 1.2.3.5 1.2.3.6
1.2.3.4 1.2.3.5 1.2.3.6 1.2.3.7
Took: 0.015974 ms
Consider the follow demo (emulating session_begin()'s current behavior vs. modified):
Code: Select all
<?php
define('IN_PHPBB', true);
$phpbb_root_path = 'phpbb3/';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
$this_ip = '1.2.3.4';
echo '<b>phpBB:</b><br />'."\n";
$s = microtime(true);
$this_ip = preg_replace('#[ ]{2,}#', ' ', str_replace(array(',', ' '), ' ', $this_ip));
// split the list of IPs
$ips = explode(' ', $this_ip);
// Default IP if REMOTE_ADDR is invalid
$this_ip = '127.0.0.1';
foreach ($ips as $ip)
{
// check IPv4 first, the IPv6 is hopefully only going to be used very seldomly
if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip))
{
// Just break
break;
}
// Use the last in chain
$this_ip = $ip;
}
$e = microtime(true);
$time = round(($e-$s)*1000,6);
echo '$this_ip = ' . $this_ip . '<br />'."\n";
echo 'Took: '.$time.' ms<br /><br /><br />'."\n\n\n";
// Cleanup
unset($s, $e, $time);
echo '<b>MOD:</b><br />'."\n";
$s = microtime(true);
if (strpos($this_ip, ',') !== FALSE || strpos($this_ip, ' ') !== FALSE)
{
$this_ip = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $this_ip));
// split the list of IPs
$ips = explode(' ', $this_ip);
// Default IP if REMOTE_ADDR is invalid
$this_ip = '127.0.0.1';
foreach ($ips as $ip)
{
// check IPv4 first, the IPv6 is hopefully only going to be used very seldomly
if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip))
{
// Just break
break;
}
// Use the last in chain
$this_ip = $ip;
}
}
else
{
if (empty($this_ip) || (!preg_match(get_preg_expression('ipv4'), $this_ip) && !preg_match(get_preg_expression('ipv6'), $this_ip)))
{
$this_ip = '127.0.0.1';
}
}
$e = microtime(true);
$time = round(($e-$s)*1000,6);
echo '$this_ip = ' . $this_ip . '<br />'."\n";
echo 'Took: '.$time.' ms<br /><br /><br />'."\n\n\n";
?>
Hope that helpsphpBB:
$this_ip = 1.2.3.4
Took: 0.030994 ms
MOD:
$this_ip = 1.2.3.4
Took: 0.007868 ms