Dotclear

Ticket #1348: iplookup_IPv6.patch

File iplookup_IPv6.patch, 28.7 KB (added by JcDenis, 13 years ago)

Ajout du support IPv6 dans iplookup

  • plugins/antispam/_prepend.php

    # HG changeset patch
    # User JcDenis
    # Date 1353274587 -3600
    # Node ID 80b9f0ff171c91b2df7d8d8673c197eca836159f
    # Parent  3a6e40cdb9c27ecf91fba7cfb923b188823c98b1
    iplookup for IPv6
    
    diff -r 3a6e40cdb9c2 -r 80b9f0ff171c plugins/antispam/_prepend.php
    a b  
    1313 
    1414global $__autoload, $core; 
    1515 
     16if (!class_exists('Net_IPv6')) { 
     17     $__autoload['Net_IPv6'] = dirname(__FILE__).'/inc/libs/IPv6.php'; 
     18} 
     19 
    1620$__autoload['dcSpamFilter'] = dirname(__FILE__).'/inc/class.dc.spamfilter.php'; 
    1721$__autoload['dcSpamFilters'] = dirname(__FILE__).'/inc/class.dc.spamfilters.php'; 
    1822$__autoload['dcAntispam'] = dirname(__FILE__).'/inc/lib.dc.antispam.php'; 
  • plugins/antispam/filters/class.dc.filter.iplookup.php

    diff -r 3a6e40cdb9c2 -r 80b9f0ff171c plugins/antispam/filters/class.dc.filter.iplookup.php
    a b  
    3939 
    4040     public function isSpam($type,$author,$email,$site,$ip,$content,$post_id,&$status) 
    4141     { 
    42           if (!$ip || long2ip(ip2long($ip)) != $ip) { 
     42          # not an IP ? 
     43          if (!$ip) { 
    4344               return; 
    4445          } 
     46          # not an IPv4 ? 
     47          elseif(long2ip(ip2long($ip)) != $ip) { 
     48               # not an IPv6 ? 
     49               if (!Net_IPv6::checkIPv6($ip)) { 
     50                    return; 
     51               } 
     52          } 
    4553 
    4654          $match = array(); 
    4755 
     
    108116 
    109117     private function dnsblLookup($ip,$bl) 
    110118     { 
    111           $revIp = implode('.',array_reverse(explode('.',$ip))); 
     119          # Ipv6 
     120          if (Net_IPv6::checkIPv6($ip)) { 
     121               // expand "::" to "0" 
     122               $revIp = Net_IPv6::uncompress($ip,true); 
     123               // prepare dnsbl format 
     124               $revIp = str_split(str_replace(':','',$ip)); 
     125          } 
     126          # IPv4 
     127          else { 
     128               $revIp = explode('.',$ip); 
     129          } 
     130           
     131          $revIp = implode('.',array_reverse($revIp)); 
    112132 
    113133          $host = $revIp.'.'.$bl.'.'; 
    114134          if (gethostbyname($host) != $host) { 
  • new file plugins/antispam/inc/libs/IPv6.php

    diff -r 3a6e40cdb9c2 -r 80b9f0ff171c plugins/antispam/inc/libs/IPv6.php
    - +  
     1<?php 
     2 
     3/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 
     4 
     5/** 
     6 * This file contains the implementation of the Net_IPv6 class 
     7 * 
     8 * PHP versions 4 and 5 
     9 * 
     10 * LICENSE: This source file is subject to the New BSD license, that is 
     11 * available through the world-wide-web at  
     12 * http://www.opensource.org/licenses/bsd-license.php 
     13 * If you did not receive a copy of the new BSDlicense and are unable 
     14 * to obtain it through the world-wide-web, please send a note to 
     15 * license@php.net so we can mail you a copy immediately 
     16 * 
     17 * @category  Net 
     18 * @package   Net_IPv6 
     19 * @author    Alexander Merz <alexander.merz@web.de> 
     20 * @copyright 2003-2005 The PHP Group 
     21 * @license   BSD License http://www.opensource.org/licenses/bsd-license.php 
     22 * @version   CVS: $Id$ 
     23 * @link      http://pear.php.net/package/Net_IPv6 
     24 */ 
     25 
     26// {{{ constants 
     27 
     28/** 
     29 * Error message if netmask bits was not found 
     30 * @see isInNetmask 
     31 */ 
     32define("NET_IPV6_NO_NETMASK_MSG", "Netmask length not found"); 
     33 
     34/** 
     35 * Error code if netmask bits was not found 
     36 * @see isInNetmask 
     37 */ 
     38define("NET_IPV6_NO_NETMASK", 10); 
     39 
     40/** 
     41 * Address Type: Unassigned (RFC 1884, Section 2.3) 
     42 * @see getAddressType() 
     43 */ 
     44define("NET_IPV6_UNASSIGNED", 1); 
     45 
     46/** 
     47 * Address Type: Reserved (RFC 1884, Section 2.3) 
     48 * @see getAddressType() 
     49 */ 
     50define("NET_IPV6_RESERVED", 11); 
     51 
     52/** 
     53 * Address Type: Reserved for NSAP Allocation (RFC 1884, Section 2.3) 
     54 * @see getAddressType() 
     55 */ 
     56define("NET_IPV6_RESERVED_NSAP", 12); 
     57 
     58/** 
     59 * Address Type: Reserved for IPX Allocation (RFC 1884, Section 2.3) 
     60 * @see getAddressType() 
     61 */ 
     62define("NET_IPV6_RESERVED_IPX", 13); 
     63 
     64/** 
     65 * Address Type: Reserved for Geographic-Based Unicast Addresses  
     66 * (RFC 1884, Section 2.3) 
     67 * @see getAddressType() 
     68 */ 
     69define("NET_IPV6_RESERVED_UNICAST_GEOGRAPHIC", 14); 
     70 
     71/** 
     72 * Address Type: Provider-Based Unicast Address (RFC 1884, Section 2.3) 
     73 * @see getAddressType() 
     74 */ 
     75define("NET_IPV6_UNICAST_PROVIDER", 22); 
     76 
     77/** 
     78 * Address Type: Multicast Addresses (RFC 1884, Section 2.3) 
     79 * @see getAddressType() 
     80 */ 
     81define("NET_IPV6_MULTICAST", 31); 
     82 
     83/** 
     84 * Address Type: Link Local Use Addresses (RFC 1884, Section 2.3) 
     85 * @see getAddressType() 
     86 */ 
     87define("NET_IPV6_LOCAL_LINK", 42); 
     88 
     89/** 
     90 * Address Type: Link Local Use Addresses (RFC 1884, Section 2.3) 
     91 * @see getAddressType() 
     92 */ 
     93define("NET_IPV6_LOCAL_SITE", 43); 
     94 
     95/** 
     96 * Address Type: Address range to embedded IPv4 ip in an IPv6 address (RFC 4291, Section 2.5.5) 
     97 * @see getAddressType() 
     98 */ 
     99define("NET_IPV6_IPV4MAPPING", 51); 
     100 
     101/** 
     102 * Address Type: Unspecified (RFC 4291, Section 2.5.2) 
     103 * @see getAddressType() 
     104 */ 
     105define("NET_IPV6_UNSPECIFIED", 52); 
     106 
     107/** 
     108 * Address Type: Unspecified (RFC 4291, Section 2.5.3) 
     109 * @see getAddressType() 
     110 */ 
     111define("NET_IPV6_LOOPBACK", 53); 
     112 
     113/** 
     114 * Address Type: address can not assigned to a specific type 
     115 * @see getAddressType() 
     116 */ 
     117define("NET_IPV6_UNKNOWN_TYPE", 1001); 
     118 
     119// }}} 
     120// {{{ Net_IPv6 
     121 
     122/** 
     123 * Class to validate and to work with IPv6 addresses. 
     124 * 
     125 * @category  Net 
     126 * @package   Net_IPv6 
     127 * @author    Alexander Merz <alexander.merz@web.de> 
     128 * @author    <elfrink at introweb dot nl> 
     129 * @author    Josh Peck <jmp at joshpeck dot org> 
     130 * @copyright 2003-2010 The PHP Group 
     131 * @license   BSD License http://www.opensource.org/licenses/bsd-license.php 
     132 * @version   Release: 1.1.0RC5 
     133 * @link      http://pear.php.net/package/Net_IPv6 
     134 */ 
     135class Net_IPv6 
     136{ 
     137 
     138    // {{{ separate() 
     139    /** 
     140     * Separates an IPv6 address into the address and a prefix length part 
     141     * 
     142     * @param String $ip the (compressed) IP as Hex representation 
     143     * 
     144     * @return Array the first element is the IP, the second the prefix length 
     145     * @since  1.2.0 
     146     * @access public 
     147     * @static      
     148     */ 
     149    function separate($ip)  
     150    { 
     151         
     152        $addr = $ip; 
     153        $spec = ''; 
     154 
     155        if(false === strrpos($ip, '/')) { 
     156 
     157            return array($addr, $spec); 
     158 
     159        } 
     160 
     161        $elements = explode('/', $ip); 
     162 
     163        if(2 == count($elements)) { 
     164 
     165            $addr = $elements[0]; 
     166            $spec = $elements[1]; 
     167 
     168        } 
     169 
     170        return array($addr, $spec); 
     171 
     172    } 
     173    // }}} 
     174 
     175    // {{{ removeNetmaskSpec() 
     176 
     177    /** 
     178     * Removes a possible existing prefix length/ netmask specification at an IP addresse. 
     179     * 
     180     * @param String $ip the (compressed) IP as Hex representation 
     181     * 
     182     * @return String the IP without netmask length 
     183     * @since  1.1.0 
     184     * @access public 
     185     * @static 
     186     */ 
     187    function removeNetmaskSpec($ip) 
     188    { 
     189 
     190        $elements = Net_IPv6::separate($ip); 
     191 
     192        return $elements[0]; 
     193 
     194    } 
     195    // }}} 
     196    // {{{ removePrefixLength() 
     197 
     198    /** 
     199     * Tests for a prefix length specification in the address 
     200     * and removes the prefix length, if exists 
     201     * 
     202     * The method is technically identical to removeNetmaskSpec() and  
     203     * will be dropped in a future release. 
     204     * 
     205     * @param String $ip a valid ipv6 address 
     206     * 
     207     * @return String the address without a prefix length 
     208     * @access public 
     209     * @static 
     210     * @see removeNetmaskSpec() 
     211     * @deprecated 
     212     */ 
     213    function removePrefixLength($ip) 
     214    { 
     215        $pos = strrpos($ip, '/'); 
     216 
     217        if (false !== $pos) { 
     218 
     219            return substr($ip, 0, $pos); 
     220 
     221        } 
     222 
     223        return $ip; 
     224    } 
     225 
     226    // }}} 
     227    // {{{ getNetmaskSpec() 
     228 
     229    /** 
     230     * Returns a possible existing prefix length/netmask specification on an IP addresse. 
     231     * 
     232     * @param String $ip the (compressed) IP as Hex representation 
     233     * 
     234     * @return String the netmask spec 
     235     * @since  1.1.0 
     236     * @access public 
     237     * @static 
     238     */ 
     239    function getNetmaskSpec($ip)  
     240    { 
     241 
     242        $elements = Net_IPv6::separate($ip); 
     243 
     244        return $elements[1]; 
     245 
     246    } 
     247 
     248    // }}} 
     249    // {{{ getPrefixLength() 
     250 
     251    /** 
     252     * Tests for a prefix length specification in the address 
     253     * and returns the prefix length, if exists 
     254     * 
     255     * The method is technically identical to getNetmaskSpec() and  
     256     * will be dropped in a future release. 
     257     * 
     258     * @param String $ip a valid ipv6 address 
     259     * 
     260     * @return Mixed the prefix as String or false, if no prefix was found 
     261     * @access public 
     262     * @static 
     263     * @deprecated 
     264     */ 
     265    function getPrefixLength($ip)  
     266    { 
     267        if (preg_match("/^([0-9a-fA-F:]{2,39})\/(\d{1,3})*$/",  
     268                        $ip, $matches)) { 
     269 
     270            return $matches[2]; 
     271 
     272        } else { 
     273 
     274            return false; 
     275 
     276        } 
     277 
     278    } 
     279 
     280    // }}} 
     281    // {{{ getNetmask() 
     282 
     283    /** 
     284     * Calculates the network prefix based on the netmask bits. 
     285     * 
     286     * @param String $ip   the (compressed) IP in Hex format 
     287     * @param int    $bits if the number of netmask bits is not part of the IP 
     288     *                     you must provide the number of bits 
     289     * 
     290     * @return String the network prefix 
     291     * @since  1.1.0 
     292     * @access public 
     293     * @static 
     294     */ 
     295    function getNetmask($ip, $bits = null) 
     296    { 
     297        if (null==$bits) { 
     298 
     299            $elements = explode('/', $ip); 
     300 
     301            if (2 == count($elements)) { 
     302 
     303                $addr = $elements[0]; 
     304                $bits = $elements[1]; 
     305 
     306            } else { 
     307 
     308                include_once 'PEAR.php'; 
     309 
     310                return PEAR::raiseError(NET_IPV6_NO_NETMASK_MSG, 
     311                                        NET_IPV6_NO_NETMASK); 
     312            } 
     313 
     314        } else { 
     315 
     316            $addr = $ip; 
     317 
     318        } 
     319 
     320        $addr       = Net_IPv6::uncompress($addr); 
     321        $binNetmask = str_repeat('1', $bits).str_repeat('0', 128 - $bits); 
     322 
     323        return Net_IPv6::_bin2Ip(Net_IPv6::_ip2Bin($addr) & $binNetmask); 
     324    } 
     325 
     326    // }}} 
     327    // {{{ isInNetmask() 
     328 
     329    /** 
     330     * Checks if an (compressed) IP is in a specific address space. 
     331     * 
     332     * IF the IP does not contains the number of netmask bits (F8000::FFFF/16) 
     333     * then you have to use the $bits parameter. 
     334     * 
     335     * @param String $ip      the IP to check (eg. F800::FFFF) 
     336     * @param String $netmask the netmask (eg F800::) 
     337     * @param int    $bits    the number of netmask bits to compare, 
     338     *                        if not given in $ip 
     339     * 
     340     * @return boolean true if $ip is in the netmask 
     341     * @since  1.1.0 
     342     * @access public 
     343     * @static 
     344     */ 
     345    function isInNetmask($ip, $netmask, $bits=null) 
     346    { 
     347        // try to get the bit count 
     348 
     349        if (null == $bits) { 
     350 
     351            $elements = explode('/', $ip); 
     352 
     353            if (2 == count($elements)) { 
     354 
     355                $ip   = $elements[0]; 
     356                $bits = $elements[1]; 
     357 
     358            } else if (null == $bits) { 
     359 
     360                $elements = explode('/', $netmask); 
     361 
     362                if (2 == count($elements)) { 
     363 
     364                     $netmask = $elements[0]; 
     365                     $bits    = $elements[1]; 
     366 
     367                } 
     368 
     369                if (null == $bits) { 
     370 
     371                    include_once 'PEAR.php'; 
     372                    return PEAR::raiseError(NET_IPV6_NO_NETMASK_MSG, 
     373                                            NET_IPV6_NO_NETMASK); 
     374 
     375                } 
     376 
     377            } 
     378 
     379        } 
     380 
     381        $binIp      = Net_IPv6::_ip2Bin(Net_IPv6::removeNetmaskSpec($ip)); 
     382        $binNetmask = Net_IPv6::_ip2Bin(Net_IPv6::removeNetmaskSpec($netmask)); 
     383 
     384        if (null != $bits 
     385            && "" != $bits 
     386            && 0 == strncmp($binNetmask, $binIp, $bits)) { 
     387 
     388            return true; 
     389 
     390        } 
     391 
     392        return false; 
     393    } 
     394 
     395    // }}} 
     396    // {{{ getAddressType() 
     397 
     398    /** 
     399     * Returns the type of an IPv6 address. 
     400     * 
     401     * RFC 2373, Section 2.3 describes several types of addresses in 
     402     * the IPv6 addresse space. 
     403     * Several addresse types are markers for reserved spaces and as 
     404     * consequence a subject to change. 
     405     * 
     406     * @param String $ip the IP address in Hex format, 
     407     *                    compressed IPs are allowed 
     408     * 
     409     * @return int one of the addresse type constants 
     410     * @access public 
     411     * @since  1.1.0 
     412     * @static 
     413     * 
     414     * @see    NET_IPV6_UNASSIGNED 
     415     * @see    NET_IPV6_RESERVED 
     416     * @see    NET_IPV6_RESERVED_NSAP 
     417     * @see    NET_IPV6_RESERVED_IPX 
     418     * @see    NET_IPV6_RESERVED_UNICAST_GEOGRAPHIC 
     419     * @see    NET_IPV6_UNICAST_PROVIDER 
     420     * @see    NET_IPV6_MULTICAST 
     421     * @see    NET_IPV6_LOCAL_LINK 
     422     * @see    NET_IPV6_LOCAL_SITE 
     423     * @see    NET_IPV6_IPV4MAPPING   
     424     * @see    NET_IPV6_UNSPECIFIED   
     425     * @see    NET_IPV6_LOOPBACK   
     426     * @see    NET_IPV6_UNKNOWN_TYPE 
     427     */ 
     428    function getAddressType($ip)  
     429    { 
     430        $ip    = Net_IPv6::removeNetmaskSpec($ip); 
     431        $binip = Net_IPv6::_ip2Bin($ip); 
     432 
     433        if(0 == strncmp(str_repeat('0', 128), $binip, 128)) { // ::/128 
     434 
     435            return NET_IPV6_UNSPECIFIED; 
     436 
     437        } else if(0 == strncmp(str_repeat('0', 127).'1', $binip, 128)) { // ::/128 
     438 
     439            return NET_IPV6_LOOPBACK; 
     440 
     441        } else if (0 == strncmp(str_repeat('0', 80).str_repeat('1', 16), $binip, 96)) { // ::ffff/96 
     442 
     443            return NET_IPV6_IPV4MAPPING;  
     444 
     445        } else if (0 == strncmp('1111111010', $binip, 10)) { 
     446 
     447            return NET_IPV6_LOCAL_LINK; 
     448 
     449        } else if (0 == strncmp('1111111011', $binip, 10)) { 
     450 
     451            return NET_IPV6_LOCAL_SITE; 
     452 
     453        } else if (0 == strncmp('111111100', $binip, 9)) { 
     454 
     455            return NET_IPV6_UNASSIGNED; 
     456 
     457        } else if (0 == strncmp('11111111', $binip, 8)) { 
     458 
     459            return NET_IPV6_MULTICAST; 
     460 
     461        } else if (0 == strncmp('00000000', $binip, 8)) {  
     462 
     463            return NET_IPV6_RESERVED; 
     464 
     465        } else if (0 == strncmp('00000001', $binip, 8) 
     466                    || 0 == strncmp('1111110', $binip, 7)) { 
     467 
     468            return NET_IPV6_UNASSIGNED; 
     469 
     470        } else if (0 == strncmp('0000001', $binip, 7)) { 
     471 
     472            return NET_IPV6_RESERVED_NSAP; 
     473 
     474        } else if (0 == strncmp('0000010', $binip, 7)) { 
     475 
     476            return NET_IPV6_RESERVED_IPX;; 
     477 
     478        } else if (0 == strncmp('0000011', $binip, 7) || 
     479                    0 == strncmp('111110', $binip, 6) || 
     480                    0 == strncmp('11110', $binip, 5) || 
     481                    0 == strncmp('00001', $binip, 5) || 
     482                    0 == strncmp('1110', $binip, 4) || 
     483                    0 == strncmp('0001', $binip, 4) || 
     484                    0 == strncmp('001', $binip, 3) || 
     485                    0 == strncmp('011', $binip, 3) || 
     486                    0 == strncmp('101', $binip, 3) || 
     487                    0 == strncmp('110', $binip, 3)) { 
     488 
     489            return NET_IPV6_UNASSIGNED; 
     490 
     491        } else if (0 == strncmp('010', $binip, 3)) { 
     492 
     493            return NET_IPV6_UNICAST_PROVIDER; 
     494 
     495        } else if (0 == strncmp('100', $binip, 3)) { 
     496 
     497            return NET_IPV6_RESERVED_UNICAST_GEOGRAPHIC; 
     498 
     499        } 
     500 
     501        return NET_IPV6_UNKNOWN_TYPE; 
     502    } 
     503 
     504    // }}} 
     505    // {{{ Uncompress() 
     506 
     507    /** 
     508     * Uncompresses an IPv6 adress 
     509     * 
     510     * RFC 2373 allows you to compress zeros in an adress to '::'. This 
     511     * function expects an valid IPv6 adress and expands the '::' to 
     512     * the required zeros. 
     513     * 
     514     * Example:  FF01::101  ->  FF01:0:0:0:0:0:0:101 
     515     *           ::1        ->  0:0:0:0:0:0:0:1 
     516     * 
     517     * @param String $ip a valid IPv6-adress (hex format) 
     518     * @param Boolean $leadingZeros if true, leading zeros are added to each  
     519     *                              block of the address  
     520     *                              (FF01::101  ->   
     521     *                               FF01:0000:0000:0000:0000:0000:0000:0101)  
     522     * 
     523     * @return String the uncompressed IPv6-adress (hex format) 
     524     * @access public 
     525     * @see Compress() 
     526     * @static 
     527     * @author Pascal Uhlmann 
     528     */ 
     529    function uncompress($ip, $leadingZeros = false) 
     530    { 
     531 
     532        $prefix = Net_IPv6::getPrefixLength($ip); 
     533 
     534        if (false === $prefix) { 
     535 
     536            $prefix = ''; 
     537 
     538        } else { 
     539 
     540            $ip     = Net_IPv6::removePrefixLength($ip); 
     541            $prefix = '/'.$prefix; 
     542 
     543        } 
     544 
     545        $netmask = Net_IPv6::getNetmaskSpec($ip); 
     546        $uip     = Net_IPv6::removeNetmaskSpec($ip); 
     547 
     548        $c1 = -1; 
     549        $c2 = -1; 
     550 
     551        if (false !== strpos($uip, '::') ) { 
     552 
     553            list($ip1, $ip2) = explode('::', $uip); 
     554 
     555            if ("" == $ip1) { 
     556 
     557                $c1 = -1; 
     558 
     559            } else { 
     560 
     561                $pos = 0; 
     562 
     563                if (0 < ($pos = substr_count($ip1, ':'))) { 
     564 
     565                    $c1 = $pos; 
     566 
     567                } else { 
     568 
     569                    $c1 = 0; 
     570 
     571                } 
     572            } 
     573            if ("" == $ip2) { 
     574 
     575                $c2 = -1; 
     576 
     577            } else { 
     578 
     579                $pos = 0; 
     580 
     581                if (0 < ($pos = substr_count($ip2, ':'))) { 
     582 
     583                    $c2 = $pos; 
     584 
     585                } else { 
     586 
     587                    $c2 = 0; 
     588 
     589                } 
     590 
     591            } 
     592 
     593            if (strstr($ip2, '.')) { 
     594 
     595                $c2++; 
     596 
     597            } 
     598            if (-1 == $c1 && -1 == $c2) { // :: 
     599 
     600                $uip = "0:0:0:0:0:0:0:0"; 
     601 
     602            } else if (-1 == $c1) {              // ::xxx 
     603 
     604                $fill = str_repeat('0:', 7-$c2); 
     605                $uip  = str_replace('::', $fill, $uip); 
     606 
     607            } else if (-1 == $c2) {              // xxx:: 
     608 
     609                $fill = str_repeat(':0', 7-$c1); 
     610                $uip  = str_replace('::', $fill, $uip); 
     611 
     612            } else {                          // xxx::xxx 
     613 
     614                $fill = str_repeat(':0:', 6-$c2-$c1); 
     615                $uip  = str_replace('::', $fill, $uip); 
     616                $uip  = str_replace('::', ':', $uip); 
     617 
     618            } 
     619        } 
     620 
     621        if(true == $leadingZeros) { 
     622             
     623            $uipT    = array(); 
     624            $uiparts = explode(':', $uip); 
     625 
     626            foreach($uiparts as $p) { 
     627 
     628                $uipT[] = sprintf('%04s', $p); 
     629             
     630            } 
     631 
     632            $uip = implode(':', $uipT); 
     633        } 
     634 
     635        if ('' != $netmask) { 
     636 
     637                $uip = $uip.'/'.$netmask; 
     638 
     639        } 
     640 
     641        return $uip.$prefix; 
     642    } 
     643 
     644    // }}} 
     645    // {{{ Compress() 
     646 
     647    /** 
     648     * Compresses an IPv6 adress 
     649     * 
     650     * RFC 2373 allows you to compress zeros in an adress to '::'. This 
     651     * function expects an valid IPv6 adress and compresses successive zeros 
     652     * to '::' 
     653     * 
     654     * Example:  FF01:0:0:0:0:0:0:101   -> FF01::101 
     655     *           0:0:0:0:0:0:0:1        -> ::1 
     656     * 
     657     * Whe $ip is an already compressed adress the methode returns the value as is, 
     658     * also if the adress can be compressed further. 
     659     * 
     660     * Example: FF01::0:1 -> FF01::0:1 
     661     * 
     662     * To enforce maximum compression, you can set the second argument $force to true. 
     663     * 
     664     * Example: FF01::0:1 -> FF01::1  
     665     * 
     666     * @param String  $ip    a valid IPv6-adress (hex format) 
     667     * @param boolean $force if true the adress will be compresses as best as possible (since 1.2.0) 
     668     * 
     669     * @return tring the compressed IPv6-adress (hex format) 
     670     * @access public 
     671     * @see    Uncompress() 
     672     * @static 
     673     * @author elfrink at introweb dot nl 
     674     */ 
     675    function compress($ip, $force = false)   
     676    { 
     677         
     678        if(false !== strpos($ip, '::')) { // its already compressed 
     679 
     680            if(true == $force) { 
     681 
     682                $ip = Net_IPv6::uncompress($ip);  
     683 
     684            } else { 
     685 
     686                return $ip; 
     687 
     688            } 
     689 
     690        } 
     691 
     692        $prefix = Net_IPv6::getPrefixLength($ip); 
     693 
     694        if (false === $prefix) { 
     695 
     696            $prefix = ''; 
     697 
     698        } else { 
     699 
     700            $ip     = Net_IPv6::removePrefixLength($ip); 
     701            $prefix = '/'.$prefix; 
     702 
     703        } 
     704 
     705        $netmask = Net_IPv6::getNetmaskSpec($ip); 
     706        $ip      = Net_IPv6::removeNetmaskSpec($ip); 
     707 
     708        $ipp = explode(':', $ip); 
     709 
     710        for ($i = 0; $i < count($ipp); $i++) { 
     711 
     712            $ipp[$i] = dechex(hexdec($ipp[$i])); 
     713 
     714        } 
     715 
     716        $cip = ':' . join(':', $ipp) . ':'; 
     717 
     718        preg_match_all("/(:0)(:0)+/", $cip, $zeros); 
     719 
     720        if (count($zeros[0]) > 0) { 
     721 
     722            $match = ''; 
     723 
     724            foreach ($zeros[0] as $zero) { 
     725 
     726                if (strlen($zero) > strlen($match)) { 
     727 
     728                    $match = $zero; 
     729 
     730                } 
     731            } 
     732 
     733            $cip = preg_replace('/' . $match . '/', ':', $cip, 1); 
     734 
     735        } 
     736 
     737        $cip = preg_replace('/((^:)|(:$))/', '', $cip); 
     738        $cip = preg_replace('/((^:)|(:$))/', '::', $cip); 
     739 
     740        if ('' != $netmask) { 
     741 
     742            $cip = $cip.'/'.$netmask; 
     743 
     744        } 
     745 
     746        return $cip.$prefix; 
     747 
     748    } 
     749 
     750    // }}} 
     751    // {{{ recommendedFormat() 
     752    /** 
     753     * Represent IPv6 address in RFC5952 format. 
     754     * 
     755     * @param String  $ip a valid IPv6-adress (hex format) 
     756     * 
     757     * @return String the recommended representation of IPv6-adress (hex format) 
     758     * @access public 
     759     * @see    compress() 
     760     * @static 
     761     * @author koyama at hoge dot org 
     762     * @todo This method may become a part of compress() in a further releases 
     763     */ 
     764    function recommendedFormat($ip) 
     765    { 
     766        $compressed = self::compress($ip, true); 
     767        // RFC5952 4.2.2 
     768        // The symbol "::" MUST NOT be used to shorten just one 
     769        // 16-bit 0 field. 
     770        if ((substr_count($compressed, ':') == 7) && 
     771            (strpos($compressed, '::') !== false)) { 
     772            $compressed = str_replace('::', ':0:', $compressed); 
     773        } 
     774        return $compressed; 
     775    } 
     776    // }}} 
     777 
     778    // {{{ isCompressible() 
     779 
     780    /** 
     781     * Checks, if an IPv6 adress can be compressed 
     782     * 
     783     * @param String $ip a valid IPv6 adress 
     784     *  
     785     * @return Boolean true, if adress can be compressed 
     786     *  
     787     * @access public 
     788     * @since 1.2.0b 
     789     * @static 
     790     * @author Manuel Schmitt 
     791     */ 
     792    function isCompressible($ip)  
     793    { 
     794 
     795        return (bool)($ip != Net_IPv6::compress($address)); 
     796 
     797    }     
     798 
     799    // }}} 
     800    // {{{ SplitV64() 
     801 
     802    /** 
     803     * Splits an IPv6 adress into the IPv6 and a possible IPv4 part 
     804     * 
     805     * RFC 2373 allows you to note the last two parts of an IPv6 adress as 
     806     * an IPv4 compatible adress 
     807     * 
     808     * Example:  0:0:0:0:0:0:13.1.68.3 
     809     *           0:0:0:0:0:FFFF:129.144.52.38 
     810     * 
     811     * @param String  $ip         a valid IPv6-adress (hex format) 
     812     * @param Boolean $uncompress if true, the address will be uncompressed  
     813     *                            before processing 
     814     * 
     815     * @return Array  [0] contains the IPv6 part, 
     816     *                [1] the IPv4 part (hex format) 
     817     * @access public 
     818     * @static 
     819     */ 
     820    function SplitV64($ip, $uncompress = true) 
     821    { 
     822        $ip = Net_IPv6::removeNetmaskSpec($ip); 
     823 
     824        if ($uncompress) { 
     825 
     826            $ip = Net_IPv6::Uncompress($ip); 
     827 
     828        } 
     829 
     830        if (strstr($ip, '.')) { 
     831 
     832            $pos      = strrpos($ip, ':'); 
     833            $ip{$pos} = '_'; 
     834            $ipPart   = explode('_', $ip); 
     835 
     836            return $ipPart; 
     837 
     838        } else { 
     839 
     840            return array($ip, ""); 
     841 
     842        } 
     843    } 
     844 
     845    // }}} 
     846    // {{{ checkIPv6() 
     847 
     848    /** 
     849     * Checks an IPv6 adress 
     850     * 
     851     * Checks if the given IP is IPv6-compatible 
     852     * 
     853     * @param String $ip a valid IPv6-adress 
     854     * 
     855     * @return Boolean true if $ip is an IPv6 adress 
     856     * @access public 
     857     * @static 
     858     */ 
     859    function checkIPv6($ip) 
     860    { 
     861 
     862        $elements = Net_IPv6::separate($ip); 
     863     
     864        $ip = $elements[0]; 
     865 
     866        if('' != $elements[1] && ( !is_numeric($elements[1]) || 0 > $elements || 128 < $elements[1])) { 
     867 
     868            return false; 
     869 
     870        }  
     871 
     872        $ipPart = Net_IPv6::SplitV64($ip); 
     873        $count  = 0; 
     874 
     875        if (!empty($ipPart[0])) { 
     876            $ipv6 = explode(':', $ipPart[0]); 
     877 
     878            foreach($ipv6 as $element) { // made a validate precheck 
     879                if(!preg_match('/[0-9a-fA-F]*/', $element)) { 
     880                    return false; 
     881                } 
     882            } 
     883 
     884            for ($i = 0; $i < count($ipv6); $i++) { 
     885 
     886                if(4 < strlen($ipv6[$i])) { 
     887                     
     888                    return false; 
     889 
     890                } 
     891 
     892                $dec = hexdec($ipv6[$i]); 
     893                $hex = strtoupper(preg_replace("/^[0]{1,3}(.*[0-9a-fA-F])$/", 
     894                                                "\\1",  
     895                                                $ipv6[$i])); 
     896 
     897                if ($ipv6[$i] >= 0 && $dec <= 65535 
     898                    && $hex == strtoupper(dechex($dec))) { 
     899 
     900                    $count++; 
     901 
     902                } 
     903 
     904            } 
     905 
     906            if (8 == $count) { 
     907 
     908                return true; 
     909 
     910            } else if (6 == $count and !empty($ipPart[1])) { 
     911 
     912                $ipv4  = explode('.', $ipPart[1]); 
     913                $count = 0; 
     914 
     915                for ($i = 0; $i < count($ipv4); $i++) { 
     916 
     917                    if ($ipv4[$i] >= 0 && (integer)$ipv4[$i] <= 255 
     918                        && preg_match("/^\d{1,3}$/", $ipv4[$i])) { 
     919 
     920                        $count++; 
     921 
     922                    } 
     923 
     924                } 
     925 
     926                if (4 == $count) { 
     927 
     928                    return true; 
     929 
     930                } 
     931 
     932            } else { 
     933 
     934                return false; 
     935 
     936            } 
     937 
     938        } else { 
     939 
     940            return false; 
     941 
     942        } 
     943 
     944    } 
     945 
     946    // }}} 
     947 
     948    // {{{ _parseAddress() 
     949 
     950    /** 
     951     * Returns the lowest and highest IPv6 address 
     952     * for a given IP and netmask specification 
     953     *  
     954     * The netmask may be a part of the $ip or  
     955     * the number of netwask bits is provided via $bits 
     956     * 
     957     * The result is an indexed array. The key 'start' 
     958     * contains the lowest possible IP adress. The key 
     959     * 'end' the highest address. 
     960     * 
     961     * @param String $ipToParse the IPv6 address 
     962     * @param String $bits      the optional count of netmask bits 
     963     * 
     964     * @return Array ['start', 'end'] the lowest and highest IPv6 address 
     965     * @access public 
     966     * @static 
     967     * @author Nicholas Williams 
     968     */ 
     969 
     970    function parseAddress($ipToParse, $bits = null) 
     971    { 
     972 
     973        $ip      = null; 
     974        $bitmask = null; 
     975 
     976        if ( null == $bits ) {   
     977 
     978            $elements = explode('/', $ipToParse); 
     979 
     980            if ( 2 == count($elements) ) { 
     981 
     982                $ip      = Net_IPv6::uncompress($elements[0]); 
     983                $bitmask = $elements[1]; 
     984 
     985            } else { 
     986 
     987                include_once 'PEAR.php'; 
     988 
     989                return PEAR::raiseError(NET_IPV6_NO_NETMASK_MSG, 
     990                                        NET_IPV6_NO_NETMASK); 
     991            } 
     992        } else { 
     993 
     994            $ip      = Net_IPv6::uncompress($ipToParse); 
     995            $bitmask = $bits; 
     996 
     997        } 
     998 
     999        $binNetmask = str_repeat('1', $bitmask). 
     1000                      str_repeat('0', 128 - $bitmask); 
     1001        $maxNetmask = str_repeat('1', 128); 
     1002        $netmask    = Net_IPv6::_bin2Ip($binNetmask); 
     1003 
     1004        $startAddress = Net_IPv6::_bin2Ip(Net_IPv6::_ip2Bin($ip) 
     1005                                          & $binNetmask); 
     1006        $endAddress   = Net_IPv6::_bin2Ip(Net_IPv6::_ip2Bin($ip) 
     1007                                          | ($binNetmask ^ $maxNetmask)); 
     1008 
     1009        return array('start' => $startAddress, 'end' => $endAddress); 
     1010    } 
     1011 
     1012    // }}} 
     1013 
     1014    // {{{ _ip2Bin() 
     1015 
     1016    /** 
     1017     * Converts an IPv6 address from Hex into Binary representation. 
     1018     * 
     1019     * @param String $ip the IP to convert (a:b:c:d:e:f:g:h),  
     1020     *                   compressed IPs are allowed 
     1021     * 
     1022     * @return String the binary representation 
     1023     * @access private 
     1024     @ @since 1.1.0 
     1025     */ 
     1026    function _ip2Bin($ip)  
     1027    { 
     1028        $binstr = ''; 
     1029 
     1030        $ip = Net_IPv6::removeNetmaskSpec($ip); 
     1031        $ip = Net_IPv6::Uncompress($ip); 
     1032 
     1033        $parts = explode(':', $ip); 
     1034 
     1035        foreach ( $parts as $v ) { 
     1036 
     1037            $str     = base_convert($v, 16, 2); 
     1038            $binstr .= str_pad($str, 16, '0', STR_PAD_LEFT); 
     1039 
     1040        } 
     1041 
     1042        return $binstr; 
     1043    } 
     1044 
     1045    // }}} 
     1046    // {{{ _bin2Ip() 
     1047 
     1048    /** 
     1049     * Converts an IPv6 address from Binary into Hex representation. 
     1050     * 
     1051     * @param String $bin the IP address as binary 
     1052     * 
     1053     * @return String the uncompressed Hex representation 
     1054     * @access private 
     1055     @ @since 1.1.0 
     1056     */ 
     1057    function _bin2Ip($bin) 
     1058    { 
     1059        $ip = ""; 
     1060 
     1061        if (strlen($bin) < 128) { 
     1062 
     1063            $bin = str_pad($bin, 128, '0', STR_PAD_LEFT); 
     1064 
     1065        } 
     1066 
     1067        $parts = str_split($bin, "16"); 
     1068 
     1069        foreach ( $parts as $v ) { 
     1070 
     1071            $str = base_convert($v, 2, 16); 
     1072            $ip .= $str.":"; 
     1073 
     1074        } 
     1075 
     1076        $ip = substr($ip, 0, -1); 
     1077 
     1078        return $ip; 
     1079    } 
     1080 
     1081    // }}} 
     1082} 
     1083// }}} 
     1084 
     1085/* 
     1086 * Local variables: 
     1087 * tab-width: 4 
     1088 * c-basic-offset: 4 
     1089 * c-hanging-comment-ender-p: nil 
     1090 * End: 
     1091 */ 
     1092 
     1093?> 

Sites map