Location: PHPKode > scripts > IP Address Subnet Sniffer > ip-address-subnet-sniffer/IPAddressSubnetSniffer.php
<?php
class IPAddressSubnetSniffer {
    /*****************************************************************
     * Author:  Jeff Silverman
     * Date:    28-OCT-2005
     * Version: 0.1
     * Copyright © 2005, The Johns Hopkins University, All rights reserved.
     * To Do: 
     *       Need to let the "okay ip addresses" be set after class
     *       instantiation
     *
     * Description:
     * This class determines whether a given IP address is in a given
     * list of subnets.  The idea is to use this determination to allow/deny
     * access to a PHP script based on IP address. Because of the way a
     * particular web environment that I was using was set up, I was
     * unable to use a .htaccess file for this task.  I could not
     * find a built-in PHP function or functions to do this task, so this class
     * was built.
     * For example, to emulate the following .htaccess file:
     *
     * ".htaccess"
     *************
     *   order allow,deny
     *   allow from 123.45.6.7
     *   allow from 012.34.5.
     *   deny from all
     *************
     *
     * You would do the following using this class:
     * 1) create a list (array) of "okay" subnets:
     * $okay = array("123.45.6.7", "12.34.5");
     *
     * 2) Then instantiate the class:
     * $ipsniff = new IPAddressSubnetSniffer( $okay );
     *
     * 3) Then test an IP address to see if it is "okay" (meaning, i
     * the same subnet):
     *
     * $ip = "123.45.6.9";
     * if ( $ipsniff->ip_is_allowed( $ip ) ){
     *     echo "It's fine";
     * }
     * Real World example -- to test a user's IP address to allow/deny
     access you can do something like this at the start of a particular
     page:

       <?php
       $okay = array("123.45.6.7", "12.34.5");
       $ipsniff = new IPAddressSubnetSniffer( $okay );
       if ( ! $ipsniff->ip_is_allowed( $_SERVER['REMOTE_ADDR'] ) ){
           echo "You are not allowed access to this page";
           exit;
       }
       ?>

     *****************************************************************/
    var $allowed_subnets;
    function IPAddressSubnetSniffer ($allowed_subnets) {
        // "allowed_subnets" defaults to ALL allowed subnets
        $this->allowed_subnets = $allowed_subnets ? $allowed_subnets : array(0);
        $this->setup_binary_subnet_list();
    }

    function setup_binary_subnet_list(){
        foreach ( $this->allowed_subnets as $sn ){
            unset($ip_octets);
            unset($mask_octets);
            if ( ! preg_match("/\//", $sn) ){
                // assume mask is "natural", create value for mask
                $ip_octets = split("\.", $sn);
                $ip_octets = array_pad($ip_octets, 4, 0);
                foreach ( $ip_octets as $o ){
                    if ($o != 0){
                        $mask_octets[] = 255;
                    } else {
                        $mask_octets[] = 0;
                    }
                }
            } else {
                // Do masking according to notation
                list($ip, $mask) = split("/", $sn);
                $ip_octets = split("\.", $ip);
                if ( preg_match("/^\d\d*$/", $mask) ){
                    for ( $m = 0; $m < $mask; $m++){
                    $mask_octets .= "1";
                    }
                    $mask_octets = str_pad($mask_octets, 32, '0');
                    $mask_octets = preg_replace("/(\d{8})/", "$1.", $mask_octets);
                    $mask_octets = preg_replace("/\.$/", "", $mask_octets);
                    $mask_octets = split("\.", $mask_octets);
                    foreach ( $mask_octets as $k => $v){
                        $mask_octets[$k] = bindec($v);
                    }
                } else {
                    $mask_octets = split("\.", $mask);
                }
            }
            unset($bin_sn);
            unset($masks);
            for ( $o = 0; $o < count($ip_octets); $o++ ){
                $bin_sn[] = $this->get_bin($ip_octets[$o] & $mask_octets[$o]);
                $masks[] = $this->get_bin($mask_octets[$o]);
            }
            $subnets[] = join(".", $bin_sn);
            $mask_list[] = join(".", $masks);
        }
        $this->binary_subnet_ips = $subnets;
        $this->binary_subnet_masks = array_unique($mask_list);
        return true;
    }

    function get_bin($number){
        return str_pad(decbin($number),8,'0',STR_PAD_LEFT);
        return decbin($number);
    }

    function ip2bin( $ip ){
        $ip_octets = split("\.", $ip);
        unset($bin_sn);
        for ( $o = 0; $o < count($ip_octets); $o++ ){
            $bin_sn[] = $this->get_bin($ip_octets[$o]);
        }
        return join(".", $bin_sn);
    }

    function bin2ip( $ip ){
        $ip_octets = split("\.", $ip);
        unset($bin_sn);
        for ( $o = 0; $o < count($ip_octets); $o++ ){
            $bin_sn[] = bindec($ip_octets[$o]);
        }
        return join(".", $bin_sn);
    }

    function apply_mask( $ip, $mask ){
        $ip_octets = split("\.", $ip);
        $mask_octets = split("\.", $mask);
        unset($bin_sn);
        for ( $o = 0; $o < count($ip_octets); $o++ ){
            $bin_sn[] = $this->get_bin(intval($ip_octets[$o]) & intval($mask_octets[$o]));
        }
        $subnet = join(".", $bin_sn);
        return $subnet;
    }

    function ip_is_allowed( $ip ){
        foreach ( $this->binary_subnet_masks as $mask ){
            $subnet = $this->apply_mask( $ip, $this->bin2ip($mask) );
            $out[] = $subnet;
        }
        // Need to walk through all the possible subnets that the given IP
        // could be a part of.  Just use "in_array()"
        foreach ( $out as $net ){
            if ( in_array( $net, $this->binary_subnet_ips ) ) return true;
        }
        return false;
    }
}
Return current item: IP Address Subnet Sniffer