[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/SimplePie/src/Net/ -> IPv6.php (source)

   1  <?php
   2  
   3  /**
   4   * SimplePie
   5   *
   6   * A PHP-Based RSS and Atom Feed Framework.
   7   * Takes the hard work out of managing a complete RSS/Atom solution.
   8   *
   9   * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors
  10   * All rights reserved.
  11   *
  12   * Redistribution and use in source and binary forms, with or without modification, are
  13   * permitted provided that the following conditions are met:
  14   *
  15   *     * Redistributions of source code must retain the above copyright notice, this list of
  16   *       conditions and the following disclaimer.
  17   *
  18   *     * Redistributions in binary form must reproduce the above copyright notice, this list
  19   *       of conditions and the following disclaimer in the documentation and/or other materials
  20   *       provided with the distribution.
  21   *
  22   *     * Neither the name of the SimplePie Team nor the names of its contributors may be used
  23   *       to endorse or promote products derived from this software without specific prior
  24   *       written permission.
  25   *
  26   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  27   * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  28   * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
  29   * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  31   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  32   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  33   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34   * POSSIBILITY OF SUCH DAMAGE.
  35   *
  36   * @package SimplePie
  37   * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue
  38   * @author Ryan Parman
  39   * @author Sam Sneddon
  40   * @author Ryan McCue
  41   * @link http://simplepie.org/ SimplePie
  42   * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  43   */
  44  
  45  namespace SimplePie\Net;
  46  
  47  /**
  48   * Class to validate and to work with IPv6 addresses.
  49   *
  50   * @package SimplePie
  51   * @subpackage HTTP
  52   * @copyright 2003-2005 The PHP Group
  53   * @license http://www.opensource.org/licenses/bsd-license.php
  54   * @link http://pear.php.net/package/Net_IPv6
  55   * @author Alexander Merz <alexander.merz@web.de>
  56   * @author elfrink at introweb dot nl
  57   * @author Josh Peck <jmp at joshpeck dot org>
  58   * @author Sam Sneddon <geoffers@gmail.com>
  59   */
  60  class IPv6
  61  {
  62      /**
  63       * Uncompresses an IPv6 address
  64       *
  65       * RFC 4291 allows you to compress concecutive zero pieces in an address to
  66       * '::'. This method expects a valid IPv6 address and expands the '::' to
  67       * the required number of zero pieces.
  68       *
  69       * Example:  FF01::101   ->  FF01:0:0:0:0:0:0:101
  70       *           ::1         ->  0:0:0:0:0:0:0:1
  71       *
  72       * @author Alexander Merz <alexander.merz@web.de>
  73       * @author elfrink at introweb dot nl
  74       * @author Josh Peck <jmp at joshpeck dot org>
  75       * @copyright 2003-2005 The PHP Group
  76       * @license http://www.opensource.org/licenses/bsd-license.php
  77       * @param string $ip An IPv6 address
  78       * @return string The uncompressed IPv6 address
  79       */
  80      public static function uncompress($ip)
  81      {
  82          $c1 = -1;
  83          $c2 = -1;
  84          if (substr_count($ip, '::') === 1) {
  85              [$ip1, $ip2] = explode('::', $ip);
  86              if ($ip1 === '') {
  87                  $c1 = -1;
  88              } else {
  89                  $c1 = substr_count($ip1, ':');
  90              }
  91              if ($ip2 === '') {
  92                  $c2 = -1;
  93              } else {
  94                  $c2 = substr_count($ip2, ':');
  95              }
  96              if (strpos($ip2, '.') !== false) {
  97                  $c2++;
  98              }
  99              // ::
 100              if ($c1 === -1 && $c2 === -1) {
 101                  $ip = '0:0:0:0:0:0:0:0';
 102              }
 103              // ::xxx
 104              elseif ($c1 === -1) {
 105                  $fill = str_repeat('0:', 7 - $c2);
 106                  $ip = str_replace('::', $fill, $ip);
 107              }
 108              // xxx::
 109              elseif ($c2 === -1) {
 110                  $fill = str_repeat(':0', 7 - $c1);
 111                  $ip = str_replace('::', $fill, $ip);
 112              }
 113              // xxx::xxx
 114              else {
 115                  $fill = ':' . str_repeat('0:', 6 - $c2 - $c1);
 116                  $ip = str_replace('::', $fill, $ip);
 117              }
 118          }
 119          return $ip;
 120      }
 121  
 122      /**
 123       * Compresses an IPv6 address
 124       *
 125       * RFC 4291 allows you to compress concecutive zero pieces in an address to
 126       * '::'. This method expects a valid IPv6 address and compresses consecutive
 127       * zero pieces to '::'.
 128       *
 129       * Example:  FF01:0:0:0:0:0:0:101   ->  FF01::101
 130       *           0:0:0:0:0:0:0:1        ->  ::1
 131       *
 132       * @see uncompress()
 133       * @param string $ip An IPv6 address
 134       * @return string The compressed IPv6 address
 135       */
 136      public static function compress($ip)
 137      {
 138          // Prepare the IP to be compressed
 139          $ip = self::uncompress($ip);
 140          $ip_parts = self::split_v6_v4($ip);
 141  
 142          // Replace all leading zeros
 143          $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]);
 144  
 145          // Find bunches of zeros
 146          if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE)) {
 147              $max = 0;
 148              $pos = null;
 149              foreach ($matches[0] as $match) {
 150                  if (strlen($match[0]) > $max) {
 151                      $max = strlen($match[0]);
 152                      $pos = $match[1];
 153                  }
 154              }
 155  
 156              $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max);
 157          }
 158  
 159          if ($ip_parts[1] !== '') {
 160              return implode(':', $ip_parts);
 161          }
 162  
 163          return $ip_parts[0];
 164      }
 165  
 166      /**
 167       * Splits an IPv6 address into the IPv6 and IPv4 representation parts
 168       *
 169       * RFC 4291 allows you to represent the last two parts of an IPv6 address
 170       * using the standard IPv4 representation
 171       *
 172       * Example:  0:0:0:0:0:0:13.1.68.3
 173       *           0:0:0:0:0:FFFF:129.144.52.38
 174       *
 175       * @param string $ip An IPv6 address
 176       * @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part
 177       */
 178      private static function split_v6_v4($ip)
 179      {
 180          if (strpos($ip, '.') !== false) {
 181              $pos = strrpos($ip, ':');
 182              $ipv6_part = substr($ip, 0, $pos);
 183              $ipv4_part = substr($ip, $pos + 1);
 184              return [$ipv6_part, $ipv4_part];
 185          }
 186  
 187          return [$ip, ''];
 188      }
 189  
 190      /**
 191       * Checks an IPv6 address
 192       *
 193       * Checks if the given IP is a valid IPv6 address
 194       *
 195       * @param string $ip An IPv6 address
 196       * @return bool true if $ip is a valid IPv6 address
 197       */
 198      public static function check_ipv6($ip)
 199      {
 200          $ip = self::uncompress($ip);
 201          [$ipv6, $ipv4] = self::split_v6_v4($ip);
 202          $ipv6 = explode(':', $ipv6);
 203          $ipv4 = explode('.', $ipv4);
 204          if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) {
 205              foreach ($ipv6 as $ipv6_part) {
 206                  // The section can't be empty
 207                  if ($ipv6_part === '') {
 208                      return false;
 209                  }
 210  
 211                  // Nor can it be over four characters
 212                  if (strlen($ipv6_part) > 4) {
 213                      return false;
 214                  }
 215  
 216                  // Remove leading zeros (this is safe because of the above)
 217                  $ipv6_part = ltrim($ipv6_part, '0');
 218                  if ($ipv6_part === '') {
 219                      $ipv6_part = '0';
 220                  }
 221  
 222                  // Check the value is valid
 223                  $value = hexdec($ipv6_part);
 224                  if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF) {
 225                      return false;
 226                  }
 227              }
 228              if (count($ipv4) === 4) {
 229                  foreach ($ipv4 as $ipv4_part) {
 230                      $value = (int) $ipv4_part;
 231                      if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF) {
 232                          return false;
 233                      }
 234                  }
 235              }
 236              return true;
 237          }
 238  
 239          return false;
 240      }
 241  
 242      /**
 243       * Checks if the given IP is a valid IPv6 address
 244       *
 245       * @codeCoverageIgnore
 246       * @deprecated Use {@see IPv6::check_ipv6()} instead
 247       * @see check_ipv6
 248       * @param string $ip An IPv6 address
 249       * @return bool true if $ip is a valid IPv6 address
 250       */
 251      public static function checkIPv6($ip)
 252      {
 253          return self::check_ipv6($ip);
 254      }
 255  }
 256  
 257  class_alias('SimplePie\Net\IPv6', 'SimplePie_Net_IPv6');


Generated : Thu Nov 21 08:20:01 2024 Cross-referenced by PHPXref