Location: PHPKode > projects > PHPMyServer > lite/includes/class.ipcalc.php4.php
<?
/**
 * IP Calculation Class
 *
 * @author Benjamin Zeiss <hide@address.com>
 * @version 0.55
 * @package ipcalc
 *
 * $Id: class.ipcalc.php,v 1.3 2002/09/18 21:12:33 bzeiss Exp $
 *
 * Description:
 * This class helps php applications with ip calculation methods. It may
 * be most interesting for applications that should act differently depending
 * on in which subnet the computer is part of. 
 *
 * Example:
 *
 * You have a kickass news script running in your company intranet. In this
 * company there are different teams. Now, you want to put different news into the 
 * system for each team. These news articles should be displayed only to the according
 * team members and not the other teams.
 * Usually this kind of access control in done with a user/password authentication
 * or apache password protection. In some cases however, it may be smart to implement
 * such functionaly directly into the script to have greater control over everything
 * and to to make things easier when security is not much of an issue (ip's can be
 * faked of course).
 *
 * The script can of course also be used to make the access control more tight as well !
 * You may, for example, want users with username's/password's to access some script
 * parts, but only when they are member of a certrain subnet.
 *
 * To sum it up: there are many places where this class could be used to enhance 
 * comfort and/or security in intranet aware php applications.
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 */

class IPCalc { 

    // ====================================================================================
    // Private Variable Definitions
    // ====================================================================================
    var $_networkaddress; // integer array with 4 elements
    var $_subnetmask; // integer array with 4 elements
    var $_error; // array: 1st element boolean flag ('flag'), 2nd element errorstring ('string')
    var $_debug; // true or false
    
    /**
     ** Constructor
     **/
    function IPCalc() {
        $this->_debug = 0;
        $this->_error[0] = $this->_error['flag'] = false;
    }

    // ====================================================================================
    // Public functions
    // ====================================================================================

    /**
     * Network Address modifier
     *
     * @param string network ip address
     * @returns true if successful, false if unsuccessful
     */
    function setNetworkAddress($ip) {
        if (($this->_networkaddress = $this->_destringifyIP($ip)) == false)
            return false;

        return true;
    }

    /**
     * Subnetmask modifier
     *
     * @param string subnetmask. accepts either dotted or numeric mask
     * @returns true if successful, false if unsuccessful
     */
    function setSubnetmask($ip) {
        if (($this->_subnetmask = $this->_destringifyIP($ip,false)) == false) {
        // ip is not in dotted form, try numeric
            if (($ip >=0) && ($ip <= 32)) {
                $i=0;
                $bit=0;
                $n=0;
                $this->_subnetmask[0]="";
                $this->_subnetmask[1]="";
                $this->_subnetmask[2]="";
                $this->_subnetmask[3]="";
                while ($i < $ip) { // convert to binary ip array
                    $this->_subnetmask[$n].="1";
                    $i++;
                    $bit = $i % 8;
                    if ($bit == 0) {
                        $n++;
                    }
                }               
                // convert binary parts to decimal parts
                $this->_subnetmask[0]=bindec($this->_subnetmask[0]);
                $this->_subnetmask[1]=bindec($this->_subnetmask[1]);
                $this->_subnetmask[2]=bindec($this->_subnetmask[2]);
                $this->_subnetmask[3]=bindec($this->_subnetmask[3]);
                return true;
            }

            return false;           
        }
            
        return true;
    }
    
    /**
     * gets the current network address as string
     *
     * @returns ip address as string
     */
    function getNetworkAddress() {
        return $this->_stringifyIP($this->_networkaddress);
    }

    /**
     * gets the current subnet as string
     *
     * @returns subnet as string
     */
    function getSubnetmask() {
        return $this->_stringifyIP($this->_subnetmask);
    }

    /**
     * get first host in subnet
     *
     * @returns ip address of the first host in the subnet, false on error
     */
    function getFirstHost() {
        if (!isset($this->_networkaddress) || !isset($this->_subnetmask)) {
            $this->_setError(true,"Network not properly set");
            $this->_outputError();
            return false;
        }
        
        $ip_address = $this->_destringifyIP($this->getNetworkAddress());
        $ip_address[3]+=1;
        return $this->_stringifyIP($ip_address);
    }

    /**
     * get last host in subnet
     *
     * @returns ip address of the last host in the subnet, false on error
     */
    function getLastHost() {
        if (!isset($this->_networkaddress) || !isset($this->_subnetmask)) {
            $this->_setError(true,"Network not properly set");
            $this->_outputError();
            return false;
        }

        $ip_address = $this->_destringifyIP($this->getBroadcast());
        $ip_address[3]-=1;
        return $this->_stringifyIP($ip_address);
    }

    /**
     * get broadcast address in subnet
     *
     * @returns the subnet's broadcast address, false on error
     */
    function getBroadcast() {
        if (!isset($this->_networkaddress) || !isset($this->_subnetmask)) {
            $this->_setError(true,"Network not properly set");
            $this->_outputError();
            return false;
        }

        $inverse_subnet = $this->_invertIP($this->_subnetmask);
        $broadcast[0] = intval($this->_networkaddress[0]) | intval($inverse_subnet[0]);
        $broadcast[1] = intval($this->_networkaddress[1]) | intval($inverse_subnet[1]);
        $broadcast[2] = intval($this->_networkaddress[2]) | intval($inverse_subnet[2]);
        $broadcast[3] = intval($this->_networkaddress[3]) | intval($inverse_subnet[3]);

        return $this->_stringifyIP($broadcast);
    }

    /**
     * checks whether a given IP Address is within the subnet
     * which has been set before
     *
     * @param string ip address to check
     * @returns true if ip is within the subnet, false otherwise
     */
    function isIPInSubnet($ip) {
        if (!isset($this->_networkaddress) || !isset($this->_subnetmask)) {
            $this->_setError(true,"Network not properly set");
            $this->_outputError();
            return false;
        }

        $network = $this->calculateNetworkAddress($ip,$this->getSubnetmask());
        if (strcmp($network,$this->getNetworkAddress()) == 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * gets all possible ip addresses within the set subnet in one array
     *
     * @returns array with all possible ip addresses, false on error
     */
    function getPossibleIPAddresses() {
        if (!isset($this->_networkaddress) || !isset($this->_subnetmask)) {
            $this->_setError(true,"Network not properly set");
            $this->_outputError();
            return false;
        }
        
        $current_host = $this->getFirstHost();
        $last_host = $this->getLastHost();
        $i=0;

        while (strcmp($current_host,$this->getNextIP($last_host)) != 0) {
            $results[$i++]=$current_host;
            $current_host=$this->getNextIP($current_host);
        }
        
        return $results;
    }

    /**
     * takes an ip address as argument and returns the next one after
     * incrementation
     *
     * @param string ip address
     * @returns next ip (string), false on overflow
     */
    function getNextIP($ip) {
        $current = $this->_destringifyIP($ip);
        $ip = (intval($current[0]) << 24) + (intval($current[1]) << 16) + 
              (intval($current[2]) << 8) + intval($current[3]) + 1;

        $current[0]= (intval($ip) & (255 << 24)) >> 24;
        $current[1]= (intval($ip) & (255 << 16)) >> 16;
        $current[2]= (intval($ip) & (255 << 8)) >> 8;
        $current[3]= (intval($ip) & 255);

        return $this->_stringifyIP($current);
    }


    /**
     * calculates the network address from given ip and subnetmask
     *
     * @param string ip address
     * @param string subnetmask
     * @returns the network address as string, false on error
     */
    function calculateNetworkAddress($ip,$subnetmask) {
        if ( !($this->_isIP($ip)) ) {
            $this->_setError(true,"'".$ip."' is not an IP Address !");
            $this->_outputError();
            return false;
        } 
        if ( !($this->_isIP($subnetmask)) ) {
            $this->_setError(true,"'".$ip."' is not an IP Address !");
            $this->_outputError();
            return false;
        } 
        $ip_address = $this->_destringifyIP($ip);
        $sn_mask = $this->_destringifyIP($subnetmask);
        
        if (($ip_address || $sn_mask) == false) {
            return false;
        }
        
        $network_address[0] = intval($ip_address[0]) & intval($sn_mask[0]);
        $network_address[1] = intval($ip_address[1]) & intval($sn_mask[1]);
        $network_address[2] = intval($ip_address[2]) & intval($sn_mask[2]);
        $network_address[3] = intval($ip_address[3]) & intval($sn_mask[3]);

        return $this->_stringifyIP($network_address);
    }

    /**
     * get IP in dotted binary form
     *
     * @param string ip to display in dotted binary form
     * @returns ip address in binary numbers
     */
    function getDottedBinary($ip) {
        $ip_address = $this->_destringifyIP($ip);
        $ip_address[0] = $this->_fillBinaryZeros(decbin($ip_address[0]));
        $ip_address[1] = $this->_fillBinaryZeros(decbin($ip_address[1]));
        $ip_address[2] = $this->_fillBinaryZeros(decbin($ip_address[2]));
        $ip_address[3] = $this->_fillBinaryZeros(decbin($ip_address[3]));

        return $this->_stringifyIP($ip_address);
    }

    /**
     * sets the debug level
     *
     * @param boolean debug level
     */
    function setDebug($state) {
        $this->_debug = $state;
    }


    // ====================================================================================
    // Private functions
   // ====================================================================================

    /**
     * calculates the inverse of a given ip address (array).
     * ip address must be valid.
     *
     * @param array ip address to invert
     * @returns inverse ip address
     */
    function _invertIP($ip) {
        $inverse[0] = intval($ip[0]) ^ intval(255);
        $inverse[1] = intval($ip[1]) ^ intval(255);
        $inverse[2] = intval($ip[2]) ^ intval(255);
        $inverse[3] = intval($ip[3]) ^ intval(255);

        return $inverse;
    }
    
    /**
     * checks a string if it is a ip address
     *
     * @param string ip address to check for validity
     * @returns true if ip, false if not
     */
    function _isIP($ip) {
        if (!preg_match("/^([\d]{1,3})\.([\d]{1,3})\.([\d]{1,3})\.([\d]{1,3})$/",$ip)) {
            return false;
        }
        $ip_array = explode(".",$ip);
        reset ($ip_array);
        while (list ($key, $val) = each ($ip_array)) {
            if (!$this->_isByte($val)) {
                return false;
            }
        }
        if (!(count($ip_array) == 4)) {
            return false;
        } 

        return true;
    }

    /**
     * checks whether the value of a number is within the Byte range
     *
     * @param int number to check
     * @returns true if byte, false if not a byte
     */
    function _isByte($number) {
        if (($number >= 0) && ($number <= 255) ) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * prints a string if the debug flag is set
     *
     * @param string message to print
     */
    function _printDebug($string) {
        if ($this->_debug) {
            printf($string);
        }
    }

    /**
     * converts an ip address to a dotted string
     *
     * @param array ip array to stringify
     * @returns ip string, false if ip is not valid
     */
    function _stringifyIP($ip) {
        return sprintf("%s.%s.%s.%s",
            $ip[0],$ip[1],$ip[2],$ip[3]);
    }

    /**
     * converts an ip address string to the internal 
     * ip array structure.
     *
     * @param string ip array to destringify (string to array)
     * @param boolean prints error message if true (optional)
     * @returns ip string if successful, false if ip not valid
     */
    function _destringifyIP($ip,$set_error=true) {
        if ( !($this->_isIP($ip)) ) {
            if ($set_error == true) {
                $this->_setError(true,"'".$ip."' is not an IP Address !");
                $this->_outputError();
            }
            return false;
        }
        return explode(".",$ip);
    }


    /**
     * sets the class error state
     *
     * @param boolean true if error, false if not
     * @param string errorstring (optional)
     */
    function _setError($flag,$str="") {
        $this->_error[0] = $this->_error['flag'] = $flag;
        $this->_error[1] = $this->_error['string'] = "[Class IPCalc] ".$str;
    }

    /**
     * outputs the error string if debug is set
     */
    function _outputError() {
        $this->_printDebug($this->_error['string']);
    }

    /**
     * takes a byte-size binary number as argument
     * and returns the same number, but filled with
     * zeros adjusted to the size of a byte
     *
     * @param byte binary number
     * @returns zero filled binary number
     */
    function _fillBinaryZeros($number) {
        $zeros = "";
        for ($i=0; $i < 8-strlen($number); $i++) {
            $zeros.="0";
        }
        $number = sprintf("%s%s",$zeros,$number);
        return $number;
    }
    
}

?>
Return current item: PHPMyServer