Файл: vkolhoze.com/geo/ipgeobase.php
Строк: 74
<?php
/*
    Class for working with ipgeobase.ru geo database.
    Copyright (C) 2013, Vladislav Ross
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
    This library 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
    Lesser General Public License for more details.
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    E-mail: vladislav.ross@gmail.com
    URL: https://github.com/rossvs/ipgeobase.php
    
*/
/*
 * @class IPGeoBase
 * @brief Класс для работы с текстовыми базами ipgeobase.ru
 * @see example.php
 *
 * Определяет страну, регион и город по IP для России и Украины
 */
class IPGeoBase 
{
    private $fhandleCIDR, $fhandleCities, $fSizeCIDR, $fsizeCities;
    /*
     * @brief Конструктор
     *
     * @param CIDRFile файл базы диапазонов IP (cidr_optim.txt)
     * @param CitiesFile файл базы городов (cities.txt)
     */
    function __construct($CIDRFile = false, $CitiesFile = false)
    {
        if(!$CIDRFile)
        {
            $CIDRFile = dirname(__FILE__) . '/cidr_optim.txt';            
        }
        if(!$CitiesFile)
        {
            $CitiesFile = dirname(__FILE__) . '/cities.txt';            
        }
        $this->fhandleCIDR = fopen($CIDRFile, 'r') or die("Cannot open $CIDRFile");
        $this->fhandleCities = fopen($CitiesFile, 'r') or die("Cannot open $CitiesFile");
        $this->fSizeCIDR = filesize($CIDRFile);
        $this->fsizeCities = filesize($CitiesFile);
    }
    /*
     * @brief Получение информации о городе по индексу
     * @param idx индекс города
     * @return массив или false, если не найдено
     */
    private function getCityByIdx($idx)
    {
        rewind($this->fhandleCities);
        while(!feof($this->fhandleCities))
        {
            $str = fgets($this->fhandleCities);
            $arRecord = explode("t", trim($str));
            if($arRecord[0] == $idx)
            {
                return array(    'city' => $arRecord[1],
                                'region' => $arRecord[2],
                                'district' => $arRecord[3],
                                'lat' => $arRecord[4],
                                'lng' => $arRecord[5]);
            }
        }
        return false;
    }
    /*
     * @brief Получение гео-информации по IP
     * @param ip IPv4-адрес
     * @return массив или false, если не найдено
     */
    function getRecord($ip)
    {
        $ip = sprintf('%u', ip2long($ip));
        
        rewind($this->fhandleCIDR);
        $rad = floor($this->fSizeCIDR / 2);
        $pos = $rad;
        while(fseek($this->fhandleCIDR, $pos, SEEK_SET) != -1)            
        {
            if($rad) 
            {
                $str = fgets($this->fhandleCIDR);                
            }
            else
            {
                rewind($this->fhandleCIDR);
            }
            
            $str = fgets($this->fhandleCIDR);
            
            if(!$str)
            {
                return false;
            }
            
            $arRecord = explode("t", trim($str));
            $rad = floor($rad / 2);
            if(!$rad && ($ip < $arRecord[0] || $ip > $arRecord[1]))
            {
                return false;
            }
            
            if($ip < $arRecord[0])
            {
                $pos -= $rad;
            }
            elseif($ip > $arRecord[1])
            {
                $pos += $rad;
            }
            else
            {
                $result = array('range' => $arRecord[2], 'cc' => $arRecord[3]);
                                            
                if($arRecord[4] != '-' && $cityResult = $this->getCityByIdx($arRecord[4]))
                {
                    $result += $cityResult;
                }
                
                return $result;
            }
        }
        return false;        
    }
}