[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/Requests/ -> IPv6.php (source)

   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          elseif ($c1 === -1) {
  55              $fill = str_repeat('0:', 7 - $c2);
  56              $ip   = str_replace('::', $fill, $ip);
  57          }
  58          // xxx::
  59          elseif ($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  }


Generated : Thu Dec 15 08:20:01 2022 Cross-referenced by PHPXref