Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

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