Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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