设为首页收藏本站

就爱编程论坛

 找回密码
 注册

人人连接登陆

无需注册,直接登录

用新浪微博连接

一步搞定

QQ登录

只需一步,快速开始

查看: 425|回复: 1
打印 上一主题 下一主题

PHP读取纯真IP数据库 [复制链接]

Rank: 9Rank: 9Rank: 9

  • TA的每日心情
    无聊
    2025-5-27 03:37:20
  • 签到天数: 366 天

    [LV.9]以坛为家II

    论坛先锋 学习至圣 荣誉成员 论坛元老 活跃之星 终极领袖

    我玩的应用:

    跳转到指定楼层
    楼主
    发表于 2011-4-24 06:59:24 |只看该作者 |倒序浏览
    整个系统是用 Ajax+php做的,
    phperz.com
    包里只有二个文件,一个getip.php 是获得客户端ip,及查询ip详情的类。你也可以将此类提出来集成到你的系统里,源码里有详细的注释, phperz~com
    ip.php是前台页面

    <?php
    header("content-type:text/html;charset=GB2312");

    //*
    //文件头 [第一条索引的偏移量 (4byte)] + [最后一条索引的偏移地址 (4byte)]     8字节
    //记录区 [结束ip (4byte)] + [地区1] + [地区2]                                                             4字节+不定长 php程序员之家
    //索引区 [开始ip (4byte)] + [指向记录区的偏移地址 (3byte)]                                7字节
    //注意:使用之前请去网上下载纯真IP数据库,并改名为 "CoralWry.dat" 放到当前目录下即可.
    //by 查询吧 www.query8.com
    //*
    class ipLocation {
    var $fp;
    var $firstip; //第一条ip索引的偏移地址
    var $lastip;   //最后一条ip索引的偏移地址
    var $totalip; //总ip数
    //*
    //构造函数,初始化一些变量
    //$datfile 的值为纯真IP数据库的名子,可自行修改.
    //*
    function ipLocation($datfile = "CoralWry.dat"){
    $this->fp=fopen($datfile,'rb');   //二制方式打开
    $this->firstip = $this->get4b(); //第一条ip索引的绝对偏移地址
    $this->lastip = $this->get4b(); //最后一条ip索引的绝对偏移地址
    $this->totalip =($this->lastip - $this->firstip)/7 ; //ip总数 索引区是定长的7个字节,在此要除以7,

    phperz.com


    register_shutdown_function(array($this,"closefp")); //为了兼容php5以下版本,本类没有用析构函数,自动关闭ip库.
    }
    //*
    //关闭ip库
    //*
    function closefp(){
    fclose($this->fp);
    }
    //*
    //读取4个字节并将解压成long的长模式
    //*
    function get4b(){
    $str=unpack("V",fread($this->fp,4));
    return $str[1];
    }
    //*
    //读取重定向了的偏移地址
    //*
    function getoffset(){
    $str=unpack("V",fread($this->fp,3).chr(0));
    return $str[1];
    }
    //*
    //读取ip的详细地址信息
    //*
    function getstr(){
    $split=fread($this->fp,1);
    while (ord($split)!=0) {
        $str .=$split;
    $split=fread($this->fp,1);
    }
    return $str;
    }
    //*
    //将ip通过ip2long转成ipv4的互联网地址,再将他压缩成big-endian字节序
    //用来和索引区内的ip地址做比较
    //*
    function iptoint($ip){
    return pack("N",intval(ip2long($ip))); phperz.com

    }
    //*
    //获取客户端ip地址
    //注意:如果你想要把ip记录到服务器上,请在写库时先检查一下ip的数据是否安全.
    //*
    function getIP() {
            if (getenv('HTTP_CLIENT_IP')) {
         $ip = getenv('HTTP_CLIENT_IP');
       }
       elseif (getenv('HTTP_X_FORWARDED_FOR')) { //获取客户端用代理服务器访问时的真实ip 地址
         $ip = getenv('HTTP_X_FORWARDED_FOR');
       }
       elseif (getenv('HTTP_X_FORWARDED')) {
         $ip = getenv('HTTP_X_FORWARDED');
       }
       elseif (getenv('HTTP_FORWARDED_FOR')) {
         $ip = getenv('HTTP_FORWARDED_FOR');
       }
       elseif (getenv('HTTP_FORWARDED')) {
         $ip = getenv('HTTP_FORWARDED');
       }
       else {
         $ip = $_SERVER['REMOTE_ADDR'];
       }
       return $ip; www.phperz.com
    }
    //*
    //获取地址信息
    //*
    function readaddress(){
    $now_offset=ftell($this->fp); //得到当前的指针位址
    $flag=$this->getflag();
    switch (ord($flag)){
             case 0:
           $address="";
       break;
       case 1:
       case 2:
           fseek($this->fp,$this->getoffset());
        $address=$this->getstr();
       break;
       default:
           fseek($this->fp,$now_offset);
           $address=$this->getstr();
       break;
    }
    return $address;
    }
    //*
    //获取标志1或2
    //用来确定地址是否重定向了.
    //*
    function getflag(){
    return fread($this->fp,1);
    }
    //*
    //用二分查找法在索引区内搜索ip
    //* php程序员站

    function searchip($ip){
    $ip=gethostbyname($ip);     //将域名转成ip
    $ip_offset["ip"]=$ip;
    $ip=$this->iptoint($ip);    //将ip转换成长整型
    $firstip=0;                 //搜索的上边界
    $lastip=$this->totalip;     //搜索的下边界
    $ipoffset=$this->lastip;    //初始化为最后一条ip地址的偏移地址
    while ($firstip <= $lastip){
        $i=floor(($firstip + $lastip) / 2);          //计算近似中间记录 floor函数记算给定浮点数小的最大整数,说白了就是四舍五也舍
    fseek($this->fp,$this->firstip + $i * 7);    //定位指针到中间记录
    $startip=strrev(fread($this->fp,4));         //读取当前索引区内的开始ip地址,并将其little-endian的字节序转换成big-endian的字节序 php程序员站
    if ($ip < $startip) {
        $lastip=$i - 1;
    }
    else {
        fseek($this->fp,$this->getoffset());
        $endip=strrev(fread($this->fp,4));
        if ($ip > $endip){
           $firstip=$i + 1;
        }
        else {
           $ip_offset["offset"]=$this->firstip + $i * 7;
           break;
        }
    }
    }
    return $ip_offset;
    }
    //*
    //获取ip地址详细信息
    //*
    function getaddress($ip){
    $ip_offset=$this->searchip($ip); //获取ip 在索引区内的绝对编移地址
    $ipoffset=$ip_offset["offset"];
    $address["ip"]=$ip_offset["ip"];
    fseek($this->fp,$ipoffset);      //定位到索引区
    $address["startip"]=long2ip($this->get4b()); //索引区内的开始ip 地址 www.phperz.com
    $address_offset=$this->getoffset();            //获取索引区内ip在ip记录区内的偏移地址
    fseek($this->fp,$address_offset);            //定位到记录区内
    $address["endip"]=long2ip($this->get4b());   //记录区内的结束ip 地址
    $flag=$this->getflag();                      //读取标志字节
    switch (ord($flag)) {
             case 1: //地区1地区2都重定向
       $address_offset=$this->getoffset();   //读取重定向地址
       fseek($this->fp,$address_offset);     //定位指针到重定向的地址
       $flag=$this->getflag();               //读取标志字节 php程序员之家
       switch (ord($flag)) {
              case 2: //地区1又一次重定向,
         fseek($this->fp,$this->getoffset());
         $address["area1"]=$this->getstr();
         fseek($this->fp,$address_offset+4);      //跳4个字节
         $address["area2"]=$this->readaddress(); //地区2有可能重定向,有可能没有
         break;
         default: //地区1,地区2都没有重定向
         fseek($this->fp,$address_offset);        //定位指针到重定向的地址
         $address["area1"]=$this->getstr();
         $address["area2"]=$this->readaddress();
         break;
       }
       break;
       case 2: //地区1重定向 地区2没有重定向 php程序员站
       $address1_offset=$this->getoffset();   //读取重定向地址
       fseek($this->fp,$address1_offset);
       $address["area1"]=$this->getstr();
       fseek($this->fp,$address_offset+8);
       $address["area2"]=$this->readaddress();
       break;
       default: //地区1地区2都没有重定向
       fseek($this->fp,$address_offset+4);
       $address["area1"]=$this->getstr();
       $address["area2"]=$this->readaddress();
       break;
    }
    //*过滤一些无用数据
    if (strpos($address["area1"],"CZ88.NET")!=false){
          $address["area1"]="未知";
    }
    if (strpos($address["area2"],"CZ88.NET")!=false){
          $address["area2"]=" "; php程序员之家

    }
    return $address;
    }

    }
    //*ipLocation class end
    $action=$_GET["action"];
    $ip_url=$_GET["ip_url"];
    if ($action=="getip"){
       $myobj=new ipLocation();
       $ip=$myobj->getIP();
       $address=$myobj->getaddress($ip);
       $myobj=NULL;
       $str="<span class='orange'>".$ip."</span>&nbsp;&nbsp;来自:".$address["area1"]." ".$address["area2"];
       echo $str;
    }
    if ($action=="queryip"){
    $myobj=new ipLocation();
    $address=$myobj->getaddress($ip_url);
    $myobj=NULL;
    $str="您查询的IP是:<span class='orange'>".$address["ip"]."</span> 来自:".$address["area1"]." ".$address["area2"];
    echo $str;
    }
    ?>




    来自: http://hi.baidu.com/dujt/blog/item/c51bb2b1752158530923029a.html
    分享到: QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    分享分享0 收藏收藏0 支持支持0 反对反对0 分享到人人 转发到微博
    [img=http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=fRUcHhYWGAQ9GxIFEBwUEVMeEhA]http://rescdn.qqmail.com/zh_CN/htmledition/images/function/qm_open/ico_mailme_02.png[/img]

    使用道具 举报

    Rank: 9Rank: 9Rank: 9

  • TA的每日心情
    无聊
    2025-5-27 03:37:20
  • 签到天数: 366 天

    [LV.9]以坛为家II

    论坛先锋 学习至圣 荣誉成员 论坛元老 活跃之星 终极领袖

    沙发
    发表于 2011-4-24 07:00:01 |只看该作者
    <?php
    function convertip($ip) {
            if(!preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip))
    { //检查IP地址
                    return '没有找到对应地址或IP输入错误';
            }

            $dat_path = 'QQWry.Dat'; //这里输入IP数据库的文件位置你只需设置这个路径dat格式QQ纯真IP数据库)
            if($fd = @fopen($dat_path, 'rb')) { //打开IP数据文件
                    //分解IP进行运算,得出整形数
                    $ip = explode('.', $ip);
                    $ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
                    //获取IP数据索引开始和结束位置
                    $DataBegin = fread($fd, 4);
                    $DataEnd = fread($fd, 4);
                    $ipbegin = implode('', unpack('L', $DataBegin));
                    if($ipbegin < 0) $ipbegin += pow(2, 32);
                    $ipend = implode('', unpack('L', $DataEnd));
                    if($ipend < 0) $ipend += pow(2, 32);
                    $ipAllNum = ($ipend - $ipbegin) / 7 + 1;
                    $BeginNum = 0;
                    $EndNum = $ipAllNum;
                    //使用二分查找法从索引记录中搜索匹配的IP记录
                   
    while($ip1num > $ipNum || $ip2num < $ipNum) {
                            $Middle= intval(($EndNum + $BeginNum) / 2);
                            //偏移指针到索引位置读取4个字节
                            fseek($fd, $ipbegin + 7 * $Middle);
                            $ipData1 = fread($fd, 4);
                            if(strlen($ipData1) < 4) {
                                    fclose($fd);
                                    return '- System Error';
                            }

                            //提取出来的数据转换成长整形,如果数据是负数则加上2的32次幂
                            $ip1num = implode('', unpack('L', $ipData1));
                            if($ip1num < 0) $ip1num += pow(2, 32);
                            //提取的长整型数大于我们IP地址则修改结束位置进行下一次循环
                           if($ip1num > $ipNum) {
                                    $EndNum = $Middle;
                                    continue;
                            }

                            //取完上一个索引后取下一个索引
                            $DataSeek = fread($fd, 3);
                           if(strlen($DataSeek) < 3) {
                                    fclose($fd);
                                    return '- System Error';
                            }

                            $DataSeek = implode('', unpack('L', $DataSeek.chr(0)));
                            fseek($fd, $DataSeek);
                            $ipData2 = fread($fd, 4);
                            if(strlen($ipData2) < 4) {
                                    fclose($fd);
                                    return '- System Error';
                            }

                            $ip2num = implode('', unpack('L', $ipData2));
                            if($ip2num < 0) $ip2num += pow(2, 32);
                            //没找到提示未知
                            if($ip2num < $ipNum) {
                                    if($Middle == $BeginNum) {
                                            fclose($fd);
                                            return '- Unknown';
                                    }
                                    $BeginNum = $Middle;
                            }

                    }
                    //下面的代码还没读明白,有兴趣的慢慢读
                    $ipFlag = fread($fd, 1);
                    if($ipFlag == chr(1)) {
                            $ipSeek = fread($fd, 3);
                            if(strlen($ipSeek) < 3) {
                                    fclose($fd);
                                    return '- System Error';
                            }
                            $ipSeek = implode('', unpack('L', $ipSeek.chr(0)));
                            fseek($fd, $ipSeek);
                            $ipFlag = fread($fd, 1);
                    }

                    if($ipFlag == chr(2)) {
                            $AddrSeek = fread($fd, 3);
                            if(strlen($AddrSeek) < 3) {
                                    fclose($fd);
                                    return '- System Error';
                            }
                            $ipFlag = fread($fd, 1);
                            if($ipFlag == chr(2)) {
                                    $AddrSeek2 = fread($fd, 3);
                                    if(strlen($AddrSeek2) < 3) {
                                            fclose($fd);
                                            return '- System Error';
                                    }
                                    $AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
                                    fseek($fd, $AddrSeek2);
                            } else {
                                    fseek($fd, -1, SEEK_CUR);
                            }
                            while(($char = fread($fd, 1)) != chr(0))
                                    $ipAddr2 .= $char;
                            $AddrSeek = implode('', unpack('L', $AddrSeek.chr(0)));
                            fseek($fd, $AddrSeek);
                            while(($char = fread($fd, 1)) != chr(0))
                                    $ipAddr1 .= $char;
                    } else {
                            fseek($fd, -1, SEEK_CUR);
                            while(($char = fread($fd, 1)) != chr(0))
                                    $ipAddr1 .= $char;
                            $ipFlag = fread($fd, 1);
                            if($ipFlag == chr(2)) {
                                    $AddrSeek2 = fread($fd, 3);
                                    if(strlen($AddrSeek2) < 3) {
                                            fclose($fd);
                                            return '- System Error';
                                    }
                                    $AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
                                    fseek($fd, $AddrSeek2);
                            } else {
                                    fseek($fd, -1, SEEK_CUR);
                            }
                            while(($char = fread($fd, 1)) != chr(0))
                                    $ipAddr2 .= $char;
                    }
                    fclose($fd);
                    if(preg_match('/http/i', $ipAddr2)) {
                            $ipAddr2 = '';
                    }
                    $ipaddr = "$ipAddr1 $ipAddr2";
                    $ipaddr = preg_replace('/CZ88\.NET/is', '', $ipaddr);
                    $ipaddr = preg_replace('/^\s*/is', '', $ipaddr);
                    $ipaddr = preg_replace('/\s*$/is', '', $ipaddr);
                    if(preg_match('/http/i', $ipaddr) || $ipaddr == '') {
                            $ipaddr = '- Unknown';
                    }
                    return '- '.$ipaddr;
            } else {
                    $datadir = DISCUZ_ROOT.'./ipdata/';
                    $ip_detail = explode('.', $ip);
                    if(file_exists($datadir.$ip_detail[0].'.txt')) {
                            $ip_fdata = @fopen($datadir.$ip_detail[0].'.txt', 'r');
                    } else {
                            if(!($ip_fdata = @fopen($datadir.'0.txt', 'r'))) {
                                    return '- Invalid IP data file';
                            }
                    }
                    for($i = 0; $i <= 3; $i++) {
                            $ip_detail[$i] = sprintf('%03d', $ip_detail[$i]);
                    }
                    $ip = join('.', $ip_detail);
                    do {
                            $ip_data = fgets($ip_fdata, 200);
                            $ip_data_detail = explode('|', $ip_data);
                            if($ip >= $ip_data_detail[0] && $ip <= $ip_data_detail[1]) {
                                    fclose($ip_fdata);
                                    return '- '.$ip_data_detail[2].$ip_data_detail[3];
                            }
                    } while(!feof($ip_fdata));
                    fclose($ip_fdata);
                    return '- UNKNOWN';
            }
    }
    ?>
    <?php echo convertip('202.194.110.113'); ?>

    [img=http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=fRUcHhYWGAQ9GxIFEBwUEVMeEhA]http://rescdn.qqmail.com/zh_CN/htmledition/images/function/qm_open/ico_mailme_02.png[/img]

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册 人人连接登陆

    晴云孤魂's Blog|就爱编程搜帖|手机版|Archiver|就爱编程论坛     

    GMT+8, 2025-7-1 23:41 , Processed in 0.107078 second(s), 30 queries .

    Powered by Discuz! X2

    © 2001-2011 Comsenz Inc.

    回顶部