Sindbad~EG File Manager
<?php
defined( '_JEXEC' ) or die( 'Restricted access' );
#namespace dilps\helper;
/*------------------------------------------------------------------------------
** File: IPv6Net.class.php
** Description: PHP class for an IPv6 subnet.
** Version: 0.1
** Author: Juergen Enge
** Email: juergen dot enge at hfg dot edu
** Homepage: http://www.hfg.edu
**------------------------------------------------------------------------------
** COPYRIGHT (c) 2011 Juergen Enge
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; version 2 of the License.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**------------------------------------------------------------------------------
* Demo Code
*
* echo "<pre>\n";
*
* $net = '2001:7C0:403:C000::1/64'; // works also: 192.168.1.1/24 or ::192.168.1.1/120
* $test = '2001:7C0:403:C000:12::2';
*
* $net = new IPV6Net( $net );
*
* echo "Subnet: {$net}<br />\n";
*
* echo 'Network: '.$net->getNetwork( true )."<br />\n";
* echo 'Broadcast: '.$net->getBroadcast( true )."<br />\n";
* echo "contains( $test ) = ".($net->contains( $test ))."<br />\n";;
* echo "</pre>\n";
*/
#use dilps;
/*!
* \brief Represents an IPv6 subnet
* the IPv6Net class is used to describe a subnet based on an ip-address and a netmask.
*/
class IPv6Net
{
private $net_addr; //!< a binary representation of the network
private $net_addr_long; //!< a 128bit integer of ipv6 addr
private $net_mask; //!< a binary representation of the network mask
private $net_mask_long; //!< a 128bit integer of ipv6 network mask
private $net_mask_bits; //!< an integer with the number of bits set in the network mask
private $net_broadcast; //!< a binary representation of the network broadcast
private $net_broadcast_long; //!< a 128bit integer of ipv6 network broadcast
private $ipv4; //!< a boolean indicating whether it is an IPv4 address
private $valid; //!< a boolean indicating whether the ip address is valid
/*!
* \brief checks for ipv4 address
* \param[in] $addr a string with an ip address
* \return true, if $addr is an ipv4 address
*/
public static function isIPv4( $addr )
{
return preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $addr );
}
/*!
* \brief Converts a packed internet address to a gmp resource
* \param[in] $in_addr a packed internet addr
* \return a gmp resource
*/
private static function inet_ntogmp( $addr )
{
// 16*8 == 128
$gmp = gmp_init( 0 );
for( $bits = 0; $bits < 16; $bits++ )
{
$byte = ord( $addr[15-$bits] );
for( $b = 0; $b < 8; $b++ )
{
gmp_setbit( $gmp, $bits*8+$b, $byte & (1<<$b) );
}
}
// echo inet_ntop( $addr ).' -> '.gmp_strval( $gmp, 16 )."<br />\n";
return $gmp;
}
/*!
* \brief Converts a gmp resource to an expanded internet address
* \param[in] $gmp a gmp resource
* \return an expanded internet address
*/
private static function inet_gmptofull( $gmp )
{
$str = gmp_strval( $gmp, 16 );
for( $i = strlen( $str ); $i < 32; $i++ )
{
$str = '0'.$str;
}
$ret = '';
for( $i = 0; $i < 8; $i++ )
{
$ret .= substr( $str, $i*4, 4 ).':';
}
return substr( $ret, 0, -1 );
}
/*!
* \brief Converts a gmp resource to a packed internet address
* \param[in] $gmp a gmp resource
* \return a packed internet address
*/
private static function inet_gmpton( $gmp )
{
// 16*8 == 128
$addr = '';
for( $bits = 0; $bits < 16; $bits++ )
{
$byte = 0;
for( $b = 0; $b < 8; $b++ )
{
if( gmp_testbit( $gmp, (15-$bits)*8+$b ))
{
$byte |= 1<<$b;
}
}
$addr .= chr( $byte );
}
// echo gmp_strval( $gmp, 16 ).' -> '.inet_ntop( $addr )."<br />\n";
return $addr;
}
/*!
* \brief Converts a internet address to an expanded IPv6 address
* \param[in] $addr a string with an internet address
* \return an expanded internet address
*/
public static function inet_ptofull( $addr )
{
if( self::isIPv4($addr)) { $addr = '::'.$addr; }
$net_addr = @inet_pton($addr);
if( $net_addr == false )
{
throw new Exception( "invalid ip address {$addr}" );
}
$net_addr_long = self::inet_ntogmp( $net_addr );
return self::inet_gmptofull($net_addr_long);
}
/*!
* constructor
* \param[in] $addr a string with an ip address
* \throws Exception if address is invalid
*/
public function __construct( $addr )
{
$this->valid = false;
// check for netmask
$cx = strpos($addr, '/');
if( $cx )
{
$mask = trim(substr($addr, $cx+1));
$addr = trim( substr($addr, 0, $cx));
}
else
{
$mask = null;
}
$this->ipv4 = $this->isIPv4( $addr );
if( $this->ipv4 )
{
$addr = '::'.$addr;
if( $mask != null )
{
if( $this->isIPv4( $mask ))
{
$mask = '::'.$mask;
}
}
}
if( $mask == null )
{
$mask = 128;
}
$this->setIPv6($addr, $mask);
}
public function __toString()
{
if( !$this->net_addr ) return '::0/128';
return inet_ntop( $this->net_addr ).'/'.$this->net_mask_bits;
}
/*!
* \brief get the network as ipv6
* \param[in] $full a boolean indicating whether the resultung ipv6 address is expanded
* \return a string with an ipv6 address
*/
public function getNetwork( $full = false )
{
if( !$this->valid ) { return null; }
if( !$full )
{
return inet_ntop( $this->net_addr );
}
else
{
return $this->inet_gmptofull( $this->net_addr_long );
}
}
/*!
* \brief get the network as ipv4 integer
* \return an integer with the ipv4 address
*/
public function getNetworkIPv4()
{
if( !$this->valid ) { return null; }
if( gmp_cmp( '4294967295', $this->net_addr_long ) > 0 )
{
return gmp_strval( $this->net_addr_long );
}
else
{
return '4294967295';
}
}
/*!
* \brief get the broadcast as ipv4 integer
* \return an integer with the ipv4 address
*/
public function getBroadcastIPv4()
{
if( !$this->valid ) { return null; }
if( gmp_cmp( '4294967295', $this->net_broadcast_long ) > 0 )
{
return gmp_strval( $this->net_broadcast_long );
}
else
{
return '4294967295';
}
}
/*!
* \brief get the broadcast as ipv6
* \param[in] $full a boolean indicating whether the resultung ipv6 address is expanded
* \return a string with an ipv6 address
*/
public function getBroadcast( $full = false )
{
if( !$this->valid ) { return null; }
if( !$full )
{
return inet_ntop( $this->net_broadcast );
}
else
{
return $this->inet_gmptofull( $this->net_broadcast_long );
}
}
/*!
* \brief checks whether address is ipv4
* \return a boolean value indicating whether the subnet is ipv4
*/
public function ipv4()
{
return $this->ipv4;
}
/*!
* \brief checks whether address is valid
* \return a boolean value indicating whether address is valid
*/
public function valid()
{
return $this->valid;
}
/*!
* \brief calculates size of the subnet
* \return an integer with the number of adresses within the subnetz
*/
public function size()
{
if( !$this->valid ) { return 0; }
return gmp_intval( gmp_add( $this->net_broadcast_long, gmp_neg( $this->net_addr_long )));
}
/*!
* \brief tests whether the ipv6 address is part of the network
* \param[in] $ip a string with the ipv4/v6 address to be checked
* \return a boolean indicating whether the address is part of the network
*/
public function contains( $ip )
{
if( !$this->valid ) return false;
if( $this->isIPv4( $ip ))
{
$ip = '::'.$ip;
}
$addr = @inet_pton( $ip );
if( $addr === false ) return false;
$gmp = $this->inet_ntogmp( $addr );
return( gmp_cmp( $this->net_addr_long, $gmp ) <= 0 && gmp_cmp( $gmp, $this->net_broadcast_long ) <= 0 );
}
/*!
* \brief set internal subnet data (ipv6 only)
* \param[in] $addr a string with the ip address
* \param[in] $mask a string with the network mask (bits or complete mask)
*/
private function setIPv6( $addr, $mask )
{
$this->net_addr = @inet_pton($addr);
if( $this->net_addr == false )
{
throw new Exception( "invalid ip address {$addr}" );
}
$this->valid = true;
$this->net_addr_long = $this->inet_ntogmp( $this->net_addr );
//$this->inet_gmpton( $this->net_addr_long );
// set the netmask
if( preg_match( '/^[0-9]+$/', $mask ))
{
$this->net_mask_bits = intval( $mask );
if( $this->ipv4 && $this->net_mask_bits != 0 ){
$this->net_mask_bits += 96;
}
$this->net_mask_long = gmp_mul( gmp_sub( gmp_pow( 2, $this->net_mask_bits ), 1 ), gmp_pow( 2, 128-$this->net_mask_bits ));
// echo gmp_strval( $this->net_mask_long, 2 )."<br />\n";
$this->net_mask = $this->inet_gmpton($this->net_mask_long);
}
else
{
$this->net_mask = inet_pton($mask);
$this->net_mask_long = $this->inet_ntogmp($this->netmask);
$this->net_mask_bits = gmp_scan0( $this->net_mask_long, 0 );
}
// normalize it...
$this->net_addr_long = gmp_and( $this->net_addr_long, $this->net_mask_long );
$this->net_addr = $this->inet_gmpton( $this->net_addr_long );
$this->net_broadcast_long = gmp_or( $this->net_addr_long, gmp_sub( gmp_pow( 2, 128-$this->net_mask_bits ), 1 ));
$this->net_broadcast = $this->inet_gmpton($this->net_broadcast_long );
}
/**
* \brief subnet this network into smaller networks (thanks to Martin Baum)
*
* \param[in] $iNetMaskBits an integer with the number of bits to
* \param[in] $iMaxValues an integer with the max number of subnets to return. Default: 1024
* \param[in] $iStartAt an integer with the offset to start from (0=first subnet, 1=second subnet, ...)
*
* \example $net = new IPv6Net("2a00:2000:1::/48"); var_dump($net->subNetTo(56));
* will subnet a /48 into 256 /56 networks
*
* \return Array containing human redable representation of subnets
*/
public function subNetTo($iNetMaskBits, $iMaxValues=1024, $iStartAt=0) {
$aRet = array();
$iNetmaskDiff = $iNetMaskBits - $this->net_mask_bits;
$rStep = gmp_pow(2, 128-$iNetMaskBits);
$rCurr = gmp_add($this->net_addr_long, gmp_mul($iStartAt, $rStep));
for ($i=0;$i<$iMaxValues; $i++) {
if ( gmp_cmp($rCurr, $this->net_broadcast_long) > 0) break;
$aRet[] = inet_ntop($this->inet_gmpton($rCurr))."/$iNetMaskBits";
$rCurr = gmp_add($rCurr, $rStep);
}
return $aRet;
}
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists