PHP读取纯真IP数据库的函数

2024-02-29 18:32

本文主要是介绍PHP读取纯真IP数据库的函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Discuz  5.0 不在使用自己的IP数据,而是使用纯真IP的数据格式, 存取纯真IP数据库稍微有点麻烦,它的存储格式比较特殊也很有趣,具体的格式分析参考下面两个链接,其他语言实现参考文章末的链接。

《纯真IP数据库格式详解》
链接一:http://blog.csdn.Net/heiyeshuwu/archive/2006/05/12/725675.aspx
链接二:http://lumaqq.Linuxsir.org/article/qqwry_format_detail.html

纯真IP数据库官网:http://www.cz88.Net/ip/
纯真IP数据库下载:http://update.cz88.Net/soft/qqwry.rar

 

以下函数conrvertip()位于 Discuz!5_GBK/upload/include/misc.func.Php 路径中,有兴趣可以具体去阅读分析。(下面代码我做了简单的修改,更便于阅读,核心没有修改)

 

<?
// ===================================
//
// 功能:IP地址获取真实地址函数
// 参数:$ip - IP地址
// 作者:[Discuz!] (C) Comsenz Inc.
//
//===================================

function  convertip( $ip ) {
    
// IP数据文件路径
     $dat_path   =   ' QQWry.Dat ' ;

    
// 检查IP地址
     if ( ! preg_match ( " /^d{1,3}.d{1,3}.d{1,3}.d{1,3}$/ " ,   $ip )) {
        
return   ' IP Address Error ' ;
    }
    
// 打开IP数据文件
     if ( ! $fd   =  @ fopen ( $dat_path ,   ' rb ' )){
        
return   ' IP date file not exists or access denied ' ;
    }

    
// 分解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 ;
}


// ========================
//
//  调用举例(速度很快)
//
//========================


echo  convertip( ' 219.238.235.10 ' );
// 输出: 北京市 电信通

echo  convertip( ' 23.56.82.12 ' );
// 输出:IANA

echo  convertip( ' 250.69.52.0 ' );
// 输出:IANA保留地址

echo  convertip( ' 238.69.52.0 ' );
// 输出:IANA保留地址 用于多点传送

echo  convertip( ' 192.168.0.1 ' );
// 输出:局域网 对方和您在同一内部网

echo  convertip( ' 255.255.255.255 ' );
// 输出:纯真网络 2006年11月20日IP数据

?>



附:(相应其他实现程序)

Php)" href="http://www.coolcode.cn/?p=16" rel=bookmark>利用 QQWry.Dat 实现 IP 地址高效检索(Php)(作者: andot)

数据库(QQWry.Dat)查询 C源码" href="http://www.douzi.org/wp/index.Php/articles/71" rel=bookmark>纯真IP数据库(QQWry.Dat)查询 C源码 (作者:Windix)

 

这篇关于PHP读取纯真IP数据库的函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/759667

相关文章

Python如何实现读取csv文件时忽略文件的编码格式

《Python如何实现读取csv文件时忽略文件的编码格式》我们再日常读取csv文件的时候经常会发现csv文件的格式有多种,所以这篇文章为大家介绍了Python如何实现读取csv文件时忽略文件的编码格式... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍我们再日常读取csv文件的时候经常

MySQL 日期时间格式化函数 DATE_FORMAT() 的使用示例详解

《MySQL日期时间格式化函数DATE_FORMAT()的使用示例详解》`DATE_FORMAT()`是MySQL中用于格式化日期时间的函数,本文详细介绍了其语法、格式化字符串的含义以及常见日期... 目录一、DATE_FORMAT()语法二、格式化字符串详解三、常见日期时间格式组合四、业务场景五、总结一、

SpringBoot使用Jasypt对YML文件配置内容加密的方法(数据库密码加密)

《SpringBoot使用Jasypt对YML文件配置内容加密的方法(数据库密码加密)》本文介绍了如何在SpringBoot项目中使用Jasypt对application.yml文件中的敏感信息(如数... 目录SpringBoot使用Jasypt对YML文件配置内容进行加密(例:数据库密码加密)前言一、J

golang panic 函数用法示例详解

《golangpanic函数用法示例详解》在Go语言中,panic用于触发不可恢复的错误,终止函数执行并逐层向上触发defer,最终若未被recover捕获,程序会崩溃,recover用于在def... 目录1. panic 的作用2. 基本用法3. recover 的使用规则4. 错误处理建议5. 常见错

Nginx实现动态封禁IP的步骤指南

《Nginx实现动态封禁IP的步骤指南》在日常的生产环境中,网站可能会遭遇恶意请求、DDoS攻击或其他有害的访问行为,为了应对这些情况,动态封禁IP是一项十分重要的安全策略,本篇博客将介绍如何通过NG... 目录1、简述2、实现方式3、使用 fail2ban 动态封禁3.1 安装 fail2ban3.2 配

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

C#中读取XML文件的四种常用方法

《C#中读取XML文件的四种常用方法》Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具,下面我们就来看看C#中读取XML文件的方法都有哪些吧... 目录XML简介格式C#读取XML文件方法使用XmlDocument使用XmlTextReader/XmlTextWr

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

Ubuntu固定虚拟机ip地址的方法教程

《Ubuntu固定虚拟机ip地址的方法教程》本文详细介绍了如何在Ubuntu虚拟机中固定IP地址,包括检查和编辑`/etc/apt/sources.list`文件、更新网络配置文件以及使用Networ... 1、由于虚拟机网络是桥接,所以ip地址会不停地变化,接下来我们就讲述ip如何固定 2、如果apt安

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详