file/cwhois.php

<?php
define
("E_FCW_WRONG_DATA_FILENAME"1);
define("E_FCW_WRONG_XML_FILENAME"2);
define("E_FCW_WRONG_DATA_FILE"11);
define("E_FCW_WRONG_XML_FILE"12);
define("E_FCW_WRONG_ADDR_FORMAT"21);
define("E_FCW_WRONG_ADDR"31);
define("E_FCW_WRONG_ADDR_LONG"32);
define("FCW_DATAROW_LENGTH"10);

class 
CFileCWhois
{
    var 
$dataFileName "";
    var 
$dataFile NULL;
    var 
$xmlFileName "";
    var 
$xmlFile NULL;

    var 
$error NULL;
    var 
$errReports NULL;
    var 
$parser NULL;

    var 
$pow8;
    var 
$pow16;
    var 
$pow24;

    function 
_setError($errCode$method$line$file$additionalInfo "")
    {
        
$this->error->clean();
        
$text "Error #".$errCode." in ".get_class($this)."::".$method.", file ".$file."\n".$additionalInfo."\n";
        
$text.= print_r($thistrue);
        
$this->error->setError($errCode$this->errReports[$errCode], $text);
    }

    function 
getLastErrorCode()
    {
        return 
$this->error->getCode();
    }

    function 
getLastError()
    {
        return 
$this->error->getString();
    }

    function 
getLastErrorText()
    {
        return 
$this->error->getDebugText();
    }

    function 
_search($addr$start = -1$end = -1)
    {
        global 
$iterCnt;
        if (
$start 0) {
            
$start 0;
            
$end = (int)(filesize($this->dataFileName) / FCW_DATAROW_LENGTH);
        }
        if (
$start == $end) {
            return 
$this->_getIdByNum($start);
        }
        if ((
$end $start) == 1) {
            
fseek($this->dataFile$start FCW_DATAROW_LENGTHSEEK_SET);
            
$str fread($this->dataFile10);
            if ((
$addr >= (((ord($str[0])*256+ord($str[1]))*256+ord($str[2]))*256+ord($str[3]))) && ($addr <= (((ord($str[4])*256+ord($str[5]))*256+ord($str[6]))*256+ord($str[7])))) {
                return 
$this->_getIdByNum($start);
            }
            
fseek($this->dataFile$end FCW_DATAROW_LENGTHSEEK_SET);
            
$str fread($this->dataFile10);
            if ((
$addr >= (((ord($str[0])*256+ord($str[1]))*256+ord($str[2]))*256+ord($str[3]))) && ($addr <= (((ord($str[4])*256+ord($str[5]))*256+ord($str[6]))*256+ord($str[7])))) {
                return 
$this->_getIdByNum($end);
            }
            return 
0;
        }
        
$num = (int)(($start $end) / 2);
        
fseek($this->dataFile$num FCW_DATAROW_LENGTHSEEK_SET);
        
$str fread($this->dataFile10);
        if (
$addr < (((ord($str[0])*256+ord($str[1]))*256+ord($str[2]))*256+ord($str[3]))) {
            return 
$this->_search($addr$start$num);
        }
        if (
$addr > (((ord($str[4])*256+ord($str[5]))*256+ord($str[6]))*256+ord($str[7]))) {
            return 
$this->_search($addr$num$end);
        }
        return 
$this->_getIdByNum($num);
    }

    function 
_getIdByNum($num)
    {
        
fseek($this->dataFile$num FCW_DATAROW_LENGTH 8SEEK_SET);
        
$str fread($this->dataFile2);
        return (
ord($str[1])*256+ord($str[0]));
    }

    function 
_getCountryById($id)
    {
        
    }

    function 
CFileCWhois()
    {
        
$this->parser = & new CFileCWhoisXmlParser();
        
$this->error = & new CFileCWhoisError();
        
$errorReports = Array();
        include(
dirname(__FILE__)."/config.php");
        
$this->errReports $errorReports;

        
$this->pow8 pow(2,8);
        
$this->pow16 $this->pow8 $this->pow8;
        
$this->pow24 $this->pow16 $this->pow8;
    }

    function 
connect($dataFileName$xmlFileName)
    {
        if (!empty(
$this->dataFile) || !empty($this->xmlFile)) {
            
$this->disconnect();
        }
        
$this->dataFileName $dataFileName;
        
$this->xmlFileName $xmlFileName;
        if (!
is_file($this->dataFileName)) {
            
$this->_setError(E_FCW_WRONG_DATA_FILENAME__FUNCTION____LINE____FILE__);
            return 
false;
        }
        if (!
is_file($this->xmlFileName)) {
            
$this->_setError(E_FCW_WRONG_XML_FILENAME__FUNCTION____LINE____FILE__);
            return 
false;
        }
        
$this->dataFile fopen($this->dataFileName"rb");
        if (!
$this->dataFile) {
            
$this->_setError(E_FCW_WRONG_DATA_FILE__FUNCTION____LINE____FILE__);
            return 
false;
        }
        
$this->xmlFile fopen($this->xmlFileName"rb");
        if (!
$this->xmlFile) {
            
$this->_setError(E_FCW_WRONG_XML_FILE__FUNCTION____LINE____FILE__);
            return 
false;
        }
        
$this->parser->parse($this->xmlFile);
        return 
true;
    }
    
    function 
disconnect()
    {
        
fclose($this->dataFile);
        
fclose($this->xmlFile);
    }

    function 
getCountryByAddr($addr)
    {
        if (
is_array($addr)) {
            
$resArr = array();
            foreach (
$addr as $val) {
                
$resArr[] = $this->getCountryByAddr($val);
            }
            return 
$resArr;
        }
        if (!
is_string($addr)) {
            
$this->_setError(E_FCW_WRONG_ADDR_FORMAT__FUNCTION____LINE____FILE__);
            return 
false;
        }
        
$addr trim($addr);
        if (!
preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/'$addr)) {
            
$host getHostByName($addr);
            if (
$host == $addr) {
                
$this->_setError(E_FCW_WRONG_ADDR__FUNCTION____LINE____FILE__);
                return 
false;
            }
            
$addr $host;
        }
        
$addr sprintf("%u"ip2long($addr));
        if (
$addr 0) {
            
$this->_setError(E_FCW_WRONG_ADDR_LONG__FUNCTION____LINE____FILE__);
            return 
false;
        }
        
$id $this->_search($addr);
        return array(
$this->parser->getCode($id), $this->parser->getName($id));
    }
    function 
getNameByAddr($addr)
    {
        if (
is_array($addr)) {
            
$resArr = array();
            foreach (
$addr as $val) {
                
$resArr[] = $this->getCountryByAddr($val);
            }
            return 
$resArr;
        }
        if (!
is_string($addr)) {
            
$this->_setError(E_FCW_WRONG_ADDR_FORMAT__FUNCTION____LINE____FILE__);
            return 
false;
        }
        
$addr trim($addr);
        if (!
preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/'$addr)) {
            
$host getHostByName($addr);
            if (
$host == $addr) {
                
$this->_setError(E_FCW_WRONG_ADDR__FUNCTION____LINE____FILE__);
                return 
false;
            }
            
$addr $host;
        }
        
$addr sprintf("%u"ip2long($addr));
        if (
$addr 0) {
            
$this->_setError(E_FCW_WRONG_ADDR_LONG__FUNCTION____LINE____FILE__);
            return 
false;
        }
        
$id $this->_search($addr);
        return 
$this->parser->getName($id);
    }
    function 
getCodeByAddr($addr)
    {
        if (
is_array($addr)) {
            
$resArr = array();
            foreach (
$addr as $val) {
                
$resArr[] = $this->getCountryByAddr($val);
            }
            return 
$resArr;
        }
        if (!
is_string($addr)) {
            
$this->_setError(E_FCW_WRONG_ADDR_FORMAT__FUNCTION____LINE____FILE__);
            return 
false;
        }
        
$addr trim($addr);
        if (!
preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/'$addr)) {
            
$host getHostByName($addr);
            if (
$host == $addr) {
                
$this->_setError(E_FCW_WRONG_ADDR__FUNCTION____LINE____FILE__);
                return 
false;
            }
            
$addr $host;
        }
        
$addr sprintf("%u"ip2long($addr));
        if (
$addr 0) {
            
$this->_setError(E_FCW_WRONG_ADDR_LONG__FUNCTION____LINE____FILE__);
            return 
false;
        }
        
$id $this->_search($addr);
        return 
$this->parser->getCode($id);
    }
}
class 
CFileCWhoisXmlParser
{
    var 
$codes;
    var 
$countries;
    var 
$curId 0;

    function 
CFileCWhoisXmlParser()
    {
        
$codes = array();
        
$countries = array();
    }

    function 
startElement($parser$name$attrs)
    {
        if (
"COUNTRY" == $name) {
            
$this->curId $attrs["ID"];
            
$this->codes[$this->curId] = $attrs["CODE"];
        }
    }

    function 
endElement($parser$name)
    {
        if (
"COUNTRY" == $name) {
            
$this->curId 0;
        }
    }

    function 
charData($parser$data)
    {
        
$this->countries[$this->curId] = $data;
    }

    function 
parse($fp)
    {
        
$xml_parser xml_parser_create();
        
xml_parser_set_option($xml_parserXML_OPTION_CASE_FOLDINGtrue);
        
xml_set_element_handler($xml_parser, array(&$this,"startElement"), array(&$this,"endElement"));
        
xml_set_character_data_handler($xml_parser, array(&$this,"charData"));
        while (
$data fread($fp4096)) {
            if (!
xml_parse($xml_parser$datafeof($fp))) {
                die(
sprintf("XML error: %s at line %d",                  xml_error_string(xml_get_error_code($xml_parser)),                  xml_get_current_line_number($xml_parser)));
            }
        }
        
xml_parser_free($xml_parser);
    }
    function 
getCode($id)
    {
        if (!
array_key_exists($id$this->codes)) {
            return 
'';
        }
        return 
$this->codes[$id];
    }
    function 
getName($id)
    {
        if (!
array_key_exists($id$this->countries)) {
            return 
'Unknown';
        }
        return 
$this->countries[$id];
    }
}
class 
CFileCWhoisError
{
    var 
$errCode 0;
    var 
$errStr "";
    var 
$errDebugText "";

    function 
setError($code$str$text)
    {
        
$this->errCode $code;
        
$this->errStr $str;
        
$this->errDebugText $text;
    }

    function 
clean()
    {
        
$this->errCode 0;
        
$this->errStr "";
        
$this->errDebugText "";
    }

    function 
getCode()
    {
        return 
$this->errCode;
    }
    function 
getString()
    {
        return 
$this->errStr;
    }
    function 
getDebugText()
    {
        return 
$this->errDebugText;
    }
}
?>

file/config.php

<?php
$errorReports
[E_FCW_WRONG_DATA_FILENAME] = "Non existing data file";
$errorReports[E_FCW_WRONG_XML_FILENAME] = "Non existing xml file";
$errorReports[E_FCW_WRONG_DATA_FILE] = "Can't open data file";
$errorReports[E_FCW_WRONG_XML_FILE] = "Can't open xml file";
$errorReports[E_FCW_WRONG_ADDR_FORMAT] = "Wrong address format";
$errorReports[E_FCW_WRONG_ADDR] = "Wrong address";
$errorReports[E_FCW_WRONG_ADDR_LONG] = "Can't convert ip to long";
?>