php查询IP地理位置(dat数据库)

ipdata类源码

<?php

define('__QQWRY__', dirname(__FILE__) . "/qqwry.dat");
class ipdata {
    var $StartIP = 0;
    var $EndIP = 0;
    var $Country = '';
    var $Local = '';

    var $CountryFlag = 0; // 标识 Country位置
    // 0x01,随后3字节为Country偏移,没有Local
    // 0x02,随后3字节为Country偏移,接着是Local
    // 其他,Country,Local,Local有类似的压缩。可能多重引用。

    var $fp;

    var $FirstStartIp = 0;
    var $LastStartIp = 0;
    var $EndIpOff = 0;

    function getStartIp($RecNo) {
        $offset = $this->FirstStartIp + $RecNo * 7;
        @fseek($this->fp, $offset, SEEK_SET);
        $buf = fread($this->fp, 7);
        $this->EndIpOff = ord($buf[4]) + (ord($buf[5]) * 256) + (ord($buf[6]) * 256 * 256);
        $this->StartIp = ord($buf[0]) + (ord($buf[1]) * 256) + (ord($buf[2]) * 256 * 256) + (ord($buf[3]) * 256 * 256 * 256);
        return $this->StartIp;
    }

    function getEndIp() {
        @fseek($this->fp, $this->EndIpOff, SEEK_SET);
        $buf = fread($this->fp, 5);
        $this->EndIp = ord($buf[0]) + (ord($buf[1]) * 256) + (ord($buf[2]) * 256 * 256) + (ord($buf[3]) * 256 * 256 * 256);
        $this->CountryFlag = ord($buf[4]);
        return $this->EndIp;
    }

    function getCountry() {
        switch ($this->CountryFlag) {
            case 1:
            case 2:
                $this->Country = $this->getFlagStr($this->EndIpOff + 4);
                $this->Local = (1 == $this->CountryFlag) ? '' : $this->getFlagStr($this->EndIpOff + 8);
                break;
            default:
                $this->Country = $this->getFlagStr($this->EndIpOff + 4);
                $this->Local = $this->getFlagStr(ftell($this->fp));
        }
    }

    function getFlagStr($offset) {
        $flag = 0;

        while (1) {
            @fseek($this->fp, $offset, SEEK_SET);
            $flag = ord(fgetc($this->fp));

            if ($flag == 1 || $flag == 2) {
                $buf = fread($this->fp, 3);

                if ($flag == 2) {
                    $this->CountryFlag = 2;
                    $this->EndIpOff = $offset - 4;
                }

                $offset = ord($buf[0]) + (ord($buf[1]) * 256) + (ord($buf[2]) * 256 * 256);
            } else {
                break;
            }

        }

        if ($offset < 12) {
            return '';
        }

        @fseek($this->fp, $offset, SEEK_SET);

        return $this->getStr();
    }

    function getStr() {
        $str = '';

        while (1) {
            $c = fgetc($this->fp);

            if (ord($c[0]) == 0) {
                break;
            }

            $str .= $c;
        }

        return iconv('gbk', 'utf-8', $str);
    }

    function geop($dotip = '') {
        if (!$dotip) {
            return;
        }

        if (preg_match("/^(127)/", $dotip)) {
            $this->Country = '本地网络';
            return;
        } else if (preg_match("/^(192)/", $dotip)) {
            $this->Country = '局域网';
            return;
        }

        $nRet;
        $ip = $this->IpToInt($dotip);
        $this->fp = fopen(__QQWRY__, "rb");

        if ($this->fp == NULL) {
            $szLocal = "OpenFileError";
            return 1;
        }

        @fseek($this->fp, 0, SEEK_SET);
        $buf = fread($this->fp, 8);
        $this->FirstStartIp = ord($buf[0]) + (ord($buf[1]) * 256) + (ord($buf[2]) * 256 * 256) + (ord($buf[3]) * 256 * 256 * 256);
        $this->LastStartIp = ord($buf[4]) + (ord($buf[5]) * 256) + (ord($buf[6]) * 256 * 256) + (ord($buf[7]) * 256 * 256 * 256);

        $RecordCount = floor(($this->LastStartIp - $this->FirstStartIp) / 7);

        if ($RecordCount <= 1) {
            $this->Country = "FileDataError";
            fclose($this->fp);
            return 2;
        }

        $RangB = 0;
        $RangE = $RecordCount;

        // Match ...
        while ($RangB < $RangE - 1) {
            $RecNo = floor(($RangB + $RangE) / 2);
            $this->getStartIp($RecNo);

            if ($ip == $this->StartIp) {
                $RangB = $RecNo;
                break;
            }

            if ($ip > $this->StartIp) {
                $RangB = $RecNo;
            } else {
                $RangE = $RecNo;
            }

        }

        $this->getStartIp($RangB);
        $this->getEndIp();

        if (($this->StartIp <= $ip) && ($this->EndIp >= $ip)) {
            $this->getCountry();
        } else {
            $this->Country = '未知';
            $this->Local = '';
        }

        fclose($this->fp);
    }

    function IpToInt($Ip) {
        $array = explode('.', $Ip);
        $Int = ($array[0] * 256 * 256 * 256) + ($array[1] * 256 * 256) + ($array[2] * 256) + $array[3];

        return $Int;
    }
}

使用

<?php

require "./util/ipdata/ipdata.class.php";

$ip = '220.177.9.69';
$ipdata = new ipdata();
$ipdata->geop($ip);
echo $ipdata->Country.$ipdata->Local;

运行结果




文/hopevow(简书作者)
原文链接:http://www.jianshu.com/p/b7709779e210
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值