Note that there are some explanatory texts on larger screens.

plurals
  1. POWorking with IPv6 Addresses in PHP
    text
    copied!<p>After searching around somewhat thoroughly, I noticed a slight lack of functions in PHP for handling <a href="http://en.wikipedia.org/wiki/IPv6" rel="nofollow noreferrer">IPv6</a>. For my own personal satisfaction I created a few functions to help the transition.</p> <p>The <code>IPv6ToLong()</code> function is a temporary solution to that brought up here: <a href="https://stackoverflow.com/questions/420680/">How to store IPv6-compatible address in a relational database</a>. It will split the IP in to two integers and return them in an array.</p> <pre><code>/** * Convert an IPv4 address to IPv6 * * @param string IP Address in dot notation (192.168.1.100) * @return string IPv6 formatted address or false if invalid input */ function IPv4To6($Ip) { static $Mask = '::ffff:'; // This tells IPv6 it has an IPv4 address $IPv6 = (strpos($Ip, '::') === 0); $IPv4 = (strpos($Ip, '.') &gt; 0); if (!$IPv4 &amp;&amp; !$IPv6) return false; if ($IPv6 &amp;&amp; $IPv4) $Ip = substr($Ip, strrpos($Ip, ':')+1); // Strip IPv4 Compatibility notation elseif (!$IPv4) return $Ip; // Seems to be IPv6 already? $Ip = array_pad(explode('.', $Ip), 4, 0); if (count($Ip) &gt; 4) return false; for ($i = 0; $i &lt; 4; $i++) if ($Ip[$i] &gt; 255) return false; $Part7 = base_convert(($Ip[0] * 256) + $Ip[1], 10, 16); $Part8 = base_convert(($Ip[2] * 256) + $Ip[3], 10, 16); return $Mask.$Part7.':'.$Part8; } /** * Replace '::' with appropriate number of ':0' */ function ExpandIPv6Notation($Ip) { if (strpos($Ip, '::') !== false) $Ip = str_replace('::', str_repeat(':0', 8 - substr_count($Ip, ':')).':', $Ip); if (strpos($Ip, ':') === 0) $Ip = '0'.$Ip; return $Ip; } /** * Convert IPv6 address to an integer * * Optionally split in to two parts. * * @see https://stackoverflow.com/questions/420680/ */ function IPv6ToLong($Ip, $DatabaseParts= 2) { $Ip = ExpandIPv6Notation($Ip); $Parts = explode(':', $Ip); $Ip = array('', ''); for ($i = 0; $i &lt; 4; $i++) $Ip[0] .= str_pad(base_convert($Parts[$i], 16, 2), 16, 0, STR_PAD_LEFT); for ($i = 4; $i &lt; 8; $i++) $Ip[1] .= str_pad(base_convert($Parts[$i], 16, 2), 16, 0, STR_PAD_LEFT); if ($DatabaseParts == 2) return array(base_convert($Ip[0], 2, 10), base_convert($Ip[1], 2, 10)); else return base_convert($Ip[0], 2, 10) + base_convert($Ip[1], 2, 10); } </code></pre> <p>For these functions I typically implement them by calling this function first:</p> <pre><code>/** * Attempt to find the client's IP Address * * @param bool Should the IP be converted using ip2long? * @return string|long The IP Address */ function GetRealRemoteIp($ForDatabase= false, $DatabaseParts= 2) { $Ip = '0.0.0.0'; if (isset($_SERVER['HTTP_CLIENT_IP']) &amp;&amp; $_SERVER['HTTP_CLIENT_IP'] != '') $Ip = $_SERVER['HTTP_CLIENT_IP']; elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) &amp;&amp; $_SERVER['HTTP_X_FORWARDED_FOR'] != '') $Ip = $_SERVER['HTTP_X_FORWARDED_FOR']; elseif (isset($_SERVER['REMOTE_ADDR']) &amp;&amp; $_SERVER['REMOTE_ADDR'] != '') $Ip = $_SERVER['REMOTE_ADDR']; if (($CommaPos = strpos($Ip, ',')) &gt; 0) $Ip = substr($Ip, 0, ($CommaPos - 1)); $Ip = IPv4To6($Ip); return ($ForDatabase ? IPv6ToLong($Ip, $DatabaseParts) : $Ip); } </code></pre> <p>Someone please tell me if I'm reinventing the wheel here or I've done something wrong.</p> <p>This implementation converts IPv4 to IPv6. Any IPv6 address it doesn't touch.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload