home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress2 / wp-includes / Requests / IPv6.php < prev    next >
Encoding:
PHP Script  |  2016-05-12  |  4.8 KB  |  191 lines

  1. <?php
  2. /**
  3.  * Class to validate and to work with IPv6 addresses
  4.  *
  5.  * @package Requests
  6.  * @subpackage Utilities
  7.  */
  8.  
  9. /**
  10.  * Class to validate and to work with IPv6 addresses
  11.  *
  12.  * This was originally based on the PEAR class of the same name, but has been
  13.  * entirely rewritten.
  14.  *
  15.  * @package Requests
  16.  * @subpackage Utilities
  17.  */
  18. class Requests_IPv6 {
  19.     /**
  20.      * Uncompresses an IPv6 address
  21.      *
  22.      * RFC 4291 allows you to compress consecutive zero pieces in an address to
  23.      * '::'. This method expects a valid IPv6 address and expands the '::' to
  24.      * the required number of zero pieces.
  25.      *
  26.      * Example:  FF01::101   ->  FF01:0:0:0:0:0:0:101
  27.      *           ::1         ->  0:0:0:0:0:0:0:1
  28.      *
  29.      * @author Alexander Merz <alexander.merz@web.de>
  30.      * @author elfrink at introweb dot nl
  31.      * @author Josh Peck <jmp at joshpeck dot org>
  32.      * @copyright 2003-2005 The PHP Group
  33.      * @license http://www.opensource.org/licenses/bsd-license.php
  34.      * @param string $ip An IPv6 address
  35.      * @return string The uncompressed IPv6 address
  36.      */
  37.     public static function uncompress($ip) {
  38.         if (substr_count($ip, '::') !== 1) {
  39.             return $ip;
  40.         }
  41.  
  42.         list($ip1, $ip2) = explode('::', $ip);
  43.         $c1 = ($ip1 === '') ? -1 : substr_count($ip1, ':');
  44.         $c2 = ($ip2 === '') ? -1 : substr_count($ip2, ':');
  45.  
  46.         if (strpos($ip2, '.') !== false) {
  47.             $c2++;
  48.         }
  49.         // ::
  50.         if ($c1 === -1 && $c2 === -1) {
  51.             $ip = '0:0:0:0:0:0:0:0';
  52.         }
  53.         // ::xxx
  54.         else if ($c1 === -1) {
  55.             $fill = str_repeat('0:', 7 - $c2);
  56.             $ip = str_replace('::', $fill, $ip);
  57.         }
  58.         // xxx::
  59.         else if ($c2 === -1) {
  60.             $fill = str_repeat(':0', 7 - $c1);
  61.             $ip = str_replace('::', $fill, $ip);
  62.         }
  63.         // xxx::xxx
  64.         else {
  65.             $fill = ':' . str_repeat('0:', 6 - $c2 - $c1);
  66.             $ip = str_replace('::', $fill, $ip);
  67.         }
  68.         return $ip;
  69.     }
  70.  
  71.     /**
  72.      * Compresses an IPv6 address
  73.      *
  74.      * RFC 4291 allows you to compress consecutive zero pieces in an address to
  75.      * '::'. This method expects a valid IPv6 address and compresses consecutive
  76.      * zero pieces to '::'.
  77.      *
  78.      * Example:  FF01:0:0:0:0:0:0:101   ->  FF01::101
  79.      *           0:0:0:0:0:0:0:1        ->  ::1
  80.      *
  81.      * @see uncompress()
  82.      * @param string $ip An IPv6 address
  83.      * @return string The compressed IPv6 address
  84.      */
  85.     public static function compress($ip) {
  86.         // Prepare the IP to be compressed
  87.         $ip = self::uncompress($ip);
  88.         $ip_parts = self::split_v6_v4($ip);
  89.  
  90.         // Replace all leading zeros
  91.         $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]);
  92.  
  93.         // Find bunches of zeros
  94.         if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE)) {
  95.             $max = 0;
  96.             $pos = null;
  97.             foreach ($matches[0] as $match) {
  98.                 if (strlen($match[0]) > $max) {
  99.                     $max = strlen($match[0]);
  100.                     $pos = $match[1];
  101.                 }
  102.             }
  103.  
  104.             $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max);
  105.         }
  106.  
  107.         if ($ip_parts[1] !== '') {
  108.             return implode(':', $ip_parts);
  109.         }
  110.         else {
  111.             return $ip_parts[0];
  112.         }
  113.     }
  114.  
  115.     /**
  116.      * Splits an IPv6 address into the IPv6 and IPv4 representation parts
  117.      *
  118.      * RFC 4291 allows you to represent the last two parts of an IPv6 address
  119.      * using the standard IPv4 representation
  120.      *
  121.      * Example:  0:0:0:0:0:0:13.1.68.3
  122.      *           0:0:0:0:0:FFFF:129.144.52.38
  123.      *
  124.      * @param string $ip An IPv6 address
  125.      * @return string[] [0] contains the IPv6 represented part, and [1] the IPv4 represented part
  126.      */
  127.     protected static function split_v6_v4($ip) {
  128.         if (strpos($ip, '.') !== false) {
  129.             $pos = strrpos($ip, ':');
  130.             $ipv6_part = substr($ip, 0, $pos);
  131.             $ipv4_part = substr($ip, $pos + 1);
  132.             return array($ipv6_part, $ipv4_part);
  133.         }
  134.         else {
  135.             return array($ip, '');
  136.         }
  137.     }
  138.  
  139.     /**
  140.      * Checks an IPv6 address
  141.      *
  142.      * Checks if the given IP is a valid IPv6 address
  143.      *
  144.      * @param string $ip An IPv6 address
  145.      * @return bool true if $ip is a valid IPv6 address
  146.      */
  147.     public static function check_ipv6($ip) {
  148.         $ip = self::uncompress($ip);
  149.         list($ipv6, $ipv4) = self::split_v6_v4($ip);
  150.         $ipv6 = explode(':', $ipv6);
  151.         $ipv4 = explode('.', $ipv4);
  152.         if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) {
  153.             foreach ($ipv6 as $ipv6_part) {
  154.                 // The section can't be empty
  155.                 if ($ipv6_part === '') {
  156.                     return false;
  157.                 }
  158.  
  159.                 // Nor can it be over four characters
  160.                 if (strlen($ipv6_part) > 4) {
  161.                     return false;
  162.                 }
  163.  
  164.                 // Remove leading zeros (this is safe because of the above)
  165.                 $ipv6_part = ltrim($ipv6_part, '0');
  166.                 if ($ipv6_part === '') {
  167.                     $ipv6_part = '0';
  168.                 }
  169.  
  170.                 // Check the value is valid
  171.                 $value = hexdec($ipv6_part);
  172.                 if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF) {
  173.                     return false;
  174.                 }
  175.             }
  176.             if (count($ipv4) === 4) {
  177.                 foreach ($ipv4 as $ipv4_part) {
  178.                     $value = (int) $ipv4_part;
  179.                     if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF) {
  180.                         return false;
  181.                     }
  182.                 }
  183.             }
  184.             return true;
  185.         }
  186.         else {
  187.             return false;
  188.         }
  189.     }
  190. }
  191.