首页文章相册图片搜索RSS 2.0

在drupal中使用纯真QQ IP库显示访问者地理位置

发表于 2008-08-4-09:17:54 编辑

drupal系统日志中会记录每一次访问的来源、访问者、访问页面以及访问者IP,但ip是一串数字,虽然网上到处有ip查询,但都不如直接转换成物理位置再输出来得方便。纯真IP库是个好东西,更新很快,许多程序(如DZ)都使用它。我在drupal的统计系统里也用纯真IP来转换输出访问者物理位置。查询代码几乎全部使用的dz 6.x中的,所以在其它php程序中使用纯真IP的话,也可以直接用这两个函数。
效果图:Drupal流量统计模块:tools.module
使用方法如下:

<?php
echo _tools_getip('220.181.6.6');
//输出结果:北京市电信百度公司
?>

函数代码:
<?php
function _tools_getip($ip) {

   
$t = '';

    if(
preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {

       
$iparray = explode('.', $ip);

        if(
$iparray[0] == 10 || $iparray[0] == 127 || ($iparray[0] == 192 && $iparray[1] == 168) || ($iparray[0] == 172 && ($iparray[1] >= 16 && $iparray[1] <= 31))) {
           
$t = '本机地址';
        } elseif(
$iparray[0] > 255 || $iparray[1] > 255 || $iparray[2] > 255 || $iparray[3] > 255) {
           
$t = '- Invalid IP Address';
        } else {
           
$t = _tools_dataip($ip, './QQWry.Dat');//QQWry.Dat的路径
       
}
    }else{
       
$t = 'IP地址不合法。';
    }

    return
$t;

}
function
_tools_dataip($ip, $ipdatafile) {

    if(!
$fd = @fopen($ipdatafile, 'rb')) {
        return
'- Invalid IP data file';
    }

   
$ip = explode('.', $ip);
   
$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];

    if(!(
$DataBegin = fread($fd, 4)) || !($DataEnd = fread($fd, 4)) ) return;
    @
$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 = $ip2num = $ip1num = 0;
   
$ipAddr1 = $ipAddr2 = '';
   
$EndNum = $ipAllNum;

    while(
$ip1num > $ipNum || $ip2num < $ipNum) {
       
$Middle= intval(($EndNum + $BeginNum) / 2);

       
fseek($fd, $ipbegin + 7 * $Middle);
       
$ipData1 = fread($fd, 4);
        if(
strlen($ipData1) < 4) {
           
fclose($fd);
            return
'- System Error';
        }
       
$ip1num = implode('', unpack('L', $ipData1));
        if(
$ip1num < 0) $ip1num += pow(2, 32);

        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
mb_convert_encoding($ipaddr,"utf-8","gb2312");//QQWry.Dat是gbk编码,如果程序是utf8,就得转码。

}
?>

不错,把它加到counter模块里面去了,不过是直接去dz

不错,把它加到counter模块里面去了,不过是直接去dz复制的代码,只要了convertip_tiny,convertip_full觉得没有必要。ip库路径问题弄了很久,后来用drupal_get_path解决了。

极速资讯

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img> <span> <h1> <h2> <h3> <h4>
  • Lines and paragraphs break automatically.
  • You can use BBCode tags in the text. URLs will automatically be converted to links.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.

More information about formatting options

同步内容