Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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');