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-2012, Ryan Parman, Geoffrey 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: * @version 1.3-dev
37: * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
38: * @author Ryan Parman
39: * @author Geoffrey 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:
46: /**
47: * Class to validate and to work with IPv6 addresses.
48: *
49: * @package SimplePie
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 Geoffrey Sneddon <geoffers@gmail.com>
57: */
58: class SimplePie_Net_IPv6
59: {
60: /**
61: * Removes a possible existing netmask specification of an IP address.
62: *
63: * @param string $ip the (compressed) IP as Hex representation
64: * @return string the IP the without netmask
65: * @since 1.1.0
66: * @access public
67: * @static
68: */
69: public static function removeNetmaskSpec($ip)
70: {
71: if (strpos($ip, '/') !== false)
72: {
73: list($addr, $nm) = explode('/', $ip);
74: }
75: else
76: {
77: $addr = $ip;
78: }
79: return $addr;
80: }
81:
82: /**
83: * Uncompresses an IPv6 address
84: *
85: * RFC 2373 allows you to compress zeros in an address to '::'. This
86: * function expects an valid IPv6 address and expands the '::' to
87: * the required zeros.
88: *
89: * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
90: * ::1 -> 0:0:0:0:0:0:0:1
91: *
92: * @access public
93: * @static
94: * @param string $ip a valid IPv6-address (hex format)
95: * @return string the uncompressed IPv6-address (hex format)
96: */
97: public static function Uncompress($ip)
98: {
99: $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
100: $c1 = -1;
101: $c2 = -1;
102: if (strpos($ip, '::') !== false)
103: {
104: list($ip1, $ip2) = explode('::', $ip);
105: if ($ip1 === '')
106: {
107: $c1 = -1;
108: }
109: else
110: {
111: $pos = 0;
112: if (($pos = substr_count($ip1, ':')) > 0)
113: {
114: $c1 = $pos;
115: }
116: else
117: {
118: $c1 = 0;
119: }
120: }
121: if ($ip2 === '')
122: {
123: $c2 = -1;
124: }
125: else
126: {
127: $pos = 0;
128: if (($pos = substr_count($ip2, ':')) > 0)
129: {
130: $c2 = $pos;
131: }
132: else
133: {
134: $c2 = 0;
135: }
136: }
137: if (strstr($ip2, '.'))
138: {
139: $c2++;
140: }
141: // ::
142: if ($c1 === -1 && $c2 === -1)
143: {
144: $uip = '0:0:0:0:0:0:0:0';
145: }
146: // ::xxx
147: else if ($c1 === -1)
148: {
149: $fill = str_repeat('0:', 7 - $c2);
150: $uip = str_replace('::', $fill, $uip);
151: }
152: // xxx::
153: else if ($c2 === -1)
154: {
155: $fill = str_repeat(':0', 7 - $c1);
156: $uip = str_replace('::', $fill, $uip);
157: }
158: // xxx::xxx
159: else
160: {
161: $fill = str_repeat(':0:', 6 - $c2 - $c1);
162: $uip = str_replace('::', $fill, $uip);
163: $uip = str_replace('::', ':', $uip);
164: }
165: }
166: return $uip;
167: }
168:
169: /**
170: * Splits an IPv6 address into the IPv6 and a possible IPv4 part
171: *
172: * RFC 2373 allows you to note the last two parts of an IPv6 address as
173: * an IPv4 compatible address
174: *
175: * Example: 0:0:0:0:0:0:13.1.68.3
176: * 0:0:0:0:0:FFFF:129.144.52.38
177: *
178: * @access public
179: * @static
180: * @param string $ip a valid IPv6-address (hex format)
181: * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
182: */
183: public static function SplitV64($ip)
184: {
185: $ip = SimplePie_Net_IPv6::Uncompress($ip);
186: if (strstr($ip, '.'))
187: {
188: $pos = strrpos($ip, ':');
189: $ip[$pos] = '_';
190: $ipPart = explode('_', $ip);
191: return $ipPart;
192: }
193: else
194: {
195: return array($ip, '');
196: }
197: }
198:
199: /**
200: * Checks an IPv6 address
201: *
202: * Checks if the given IP is IPv6-compatible
203: *
204: * @access public
205: * @static
206: * @param string $ip a valid IPv6-address
207: * @return bool true if $ip is an IPv6 address
208: */
209: public static function checkIPv6($ip)
210: {
211: $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
212: $count = 0;
213: if (!empty($ipPart[0]))
214: {
215: $ipv6 = explode(':', $ipPart[0]);
216: for ($i = 0; $i < count($ipv6); $i++)
217: {
218: $dec = hexdec($ipv6[$i]);
219: $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
220: if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
221: {
222: $count++;
223: }
224: }
225: if ($count === 8)
226: {
227: return true;
228: }
229: elseif ($count === 6 && !empty($ipPart[1]))
230: {
231: $ipv4 = explode('.', $ipPart[1]);
232: $count = 0;
233: foreach ($ipv4 as $ipv4_part)
234: {
235: if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
236: {
237: $count++;
238: }
239: }
240: if ($count === 4)
241: {
242: return true;
243: }
244: }
245: else
246: {
247: return false;
248: }
249:
250: }
251: else
252: {
253: return false;
254: }
255: }
256: }
257:
258: