Location: PHPKode > projects > CNStats > cnstats/geo/geobaza/php/Geobaza.php
<?php

if ( !function_exists("json_decode") ) {
    function json_decode($text) {
	eval("\$var=".preg_replace('/(\"[^\"]+\"):/', "$1=>", preg_replace('/\}|\]/', ")", preg_replace('/\[|\{/', "array(", $text))).";");
	return $var;
    }
}

if ( !function_exists("json_encode") ) {
    function json_encode($var) {
	if ( is_array($var) && count($var) && (array_keys($var)!==range(0,sizeof($var)-1)) ) {
	    $res = array();
	    foreach ( array_keys($var) as $key )
		$res[] = "\"$key\":".json_encode($var{$key});
	    return "{".join(",",$res)."}";
	}
	if ( is_array($var) ) {
	    $res = array();
	    foreach ( array_keys($var) as $key )
		$res[] = json_encode($var{$key});
	    return "[".join(",",$res)."]";
	}
	if ( is_string($var) ) {
	    return "\"".addslashes($var)."\"";
	}
	if ( is_numeric($var) ) {
	    return $var;
	}
	return "";
    }
}


class Geobaza {
    function __construct($filepath=self::FILENAME_BINARY_TREE) {
	$this->is_valid = false;
	$this->error_message = "";
	$this->fp_binary_tree = fopen($filepath, 'r');
	if ( !$this->fp_binary_tree ) {
	    $this->error_message = "Can't open binary tree file \"".$filepath."\"";
	    return false;
	}
	$data = fread($this->fp_binary_tree, 7);
	if ( $data != "GEOBAZA" ) {
	    $this->error_message = "Invalid datafile signature";
	    return false;
	}
	$data = fread($this->fp_binary_tree, 2);
	$unp = unpack('nlen', $data);
	$data = fread($this->fp_binary_tree, $unp['len']);
	$this->headers = json_decode($data, true);

	$this->level_size = array();
	for(;;) {
	    $data = fread($this->fp_binary_tree, 1);
	    $unp = unpack('Cdata', $data);
	    $hi = ($unp['data']>>4) & 0x0f;
	    $lo = $unp['data'] & 0x0f;
	    $this->level_size[] = $hi;
	    if ( $hi == 0 )
		break;
	    $this->level_size[] = $lo;
	    if ( $lo == 0 )
		break;
	}
	$this->start_offset = ftell($this->fp_binary_tree);
	$this->is_valid = true;
    }


    function __destruct() {
	fclose($this->fp_binary_tree);
    }
    

    function lookup($ip) {
	if ( !$this->is_valid )
	    return false;
	    
	$ipint = ip2long($ip);
	$shift = 32;
	$offset = $this->start_offset;
	$result = array();
    
	for($l=0; $l<sizeof($this->level_size); $l++) {
	    $shift -= $this->level_size[$l];
	    $index = (($ipint>>$shift)) & ((1<<$this->level_size[$l])-1);
	    $tell = $offset+$index*4;
	    fseek($this->fp_binary_tree, $tell, 0);
	    $data = fread($this->fp_binary_tree, 4);
	    $unp = unpack('Ndata',$data);
	    $offset = $unp['data'] & 0xffffffff;
	    if ( $offset & 0x80000000 ) {
		while ( $offset ) {
		    $tell = $offset & 0x7fffffff;
		    fseek($this->fp_binary_tree, $tell, 0);
		    $data = fread($this->fp_binary_tree, 2);
		    $unp = unpack('nlen', $data);
		    $length = $unp['len'] & 0xffff;
		    if ( !$length )
			return "";
		    $info = fread($this->fp_binary_tree, $length);
		    $unpacked_data = json_decode($info, true);
		    if ( isset($unpacked_data['special']) ) {
			return $unpacked_data;
		    }
		    $result[] = $unpacked_data;
		    $data = fread($this->fp_binary_tree, 4);
		    $unp = unpack('Nparent', $data);
		    $offset = $unp['parent'];
		}
		break;
	    }
	}
	return array('items'=>$result);
    }
    
    
    const FILENAME_BINARY_TREE = "geobaza.dat";
    
    private $is_valid;
    function is_valid() {
	return $this->is_valid;
    }
    
    private $error_message;
    function get_error() {
	return $this->error_message;
    }
    
    private $headers;
    function get_headers() {
	return $this->headers;
    }
    
    private $level_size;
    private $start_offset;
    
    private $fp_binary_tree;
    private $dbh;
    
}



?>
Return current item: CNStats