ip2region小问题修复发

By money at 2022-01-20 • 0人收藏 • 310人看过

https://suiang.cn/  发现一个ip2region库,一直用得非常愉快,直到在windowsServer2016中运行,ip2region.db置于中文目录下,会报错,无法读取文件,只需要将程序置于英文目录就简单解决,但是我这贱人的小矫情控制不住(win10没问题,其它系统没测)

/*
https://gitee.com/lionsoul/ip2region
*/ 

import wsock
import fsys.file;

namespace inet; 

class ip2region{
    ctor( path ){
        path := "~\lib\inet\ip2region\.res\ip2region.db"
		this.file, err = ..fsys.file(path, "rb")
		if(!this.file){
			 return null,err; 
		}
		
        this.headerLen = 0;
    	this.HeaderSip = {};
    	this.HeaderPtr = {};
    	//open the db file
    	this.firstIndex = 0;
    	this.lastIndex  = 0;
    	this.totalBlocks= 0;
    	this.dbBinStr   = null;
        ..table.add_gc(this,"close"); 
    }; 
    memory_search = function(ip) {
    	if ( !this.dbBinStr ) {
        	//alloc the buffer size
        	this.file.seek("set")
        	this.dbBinStr = ..raw.buffer(this.file.readAll());
        	
        	var index = ..raw.convert(this.dbBinStr, {INT beginIndex; INT endIndex})
	
        	this.firstIndex = index.beginIndex;
        	this.lastIndex  = index.endIndex;
        	this.totalBlocks   = (this.lastIndex-this.firstIndex)/INDEX_BLOCK_LENGTH + 1;
    	}
    	
    	var left = 0; 
    	var right = this.totalBlocks; 
    	var dptr = 0;
    	
    	while ( left <= right ) {
        	var middle = (left + right) >> 1;  //二分法
        	var offset = this.firstIndex + middle * INDEX_BLOCK_LENGTH;
			
        	sip = ..raw.convert(this.dbBinStr, {INT ip}, offset).ip
        	if ( ip < sip ) {
            	right = middle - 1;
        	} else {
            	eip = ..raw.convert(this.dbBinStr, {INT ip}, offset+4).ip
            	if ( ip > eip ) {
                	left = middle + 1;
            	} else {
                	dptr = ..raw.convert(this.dbBinStr, {INT ip}, offset + 8).ip
                	break;
            	}
        	}
    	}
		
    	if ( dptr == 0 ) return;
    	var dataLen = ((dptr >> 24) & 0xFF);
    	var dataptr = (dptr & 0x00FFFFFF);
    	var city_id = ..raw.convert(this.dbBinStr, {INT id}, dataptr).id;
    	return {
    		city_id = city_id;
    		region = ..string.slice(this.dbBinStr, dataptr+4+1, dataptr+dataLen)
    	}; 
	}
	btree_search = function(ip){
    	var  (i, idx)
    	var (l, m, h, p, sptr, eptr, indexBlockLen, dataLen, dataptr)
    	var (sip, eip, idxptr, dptr);
	
    	if ( !this.headerLen ) {
    	    var buf = ..raw.buffer(TOTAL_HEADER_LENGTH);
    	    this.file.seek("set",8)
    	    this.file.readBuffer(buf);
    	    
    	    var idx = 0;
    	    for(i=1; TOTAL_HEADER_LENGTH; 8){
    	        idx++;
    	    	var head = ..raw.convert(buf, {int sip;int idxptr}, i-1);
    	    	
    	    	if(!head.idxptr){
            		break
            	}
    	    	this.HeaderSip[idx] = head.sip;
            	this.HeaderPtr[idx] = head.idxptr;
    	    }
    	    
        	this.headerLen = idx;
    	}
	
    	//search the header block to define the index block
    	var (l = 0; h = this.headerLen; sptr = 0; eptr = 0;)
    	while ( l <= h ) {
        	m = ((l + h) >> 1);
        	//perfetc matched, just return it
        	if ( ip == this.HeaderSip[m] ) {
            	if ( m > 0 ) {
                	sptr = this.HeaderPtr[m-1];
                	eptr = this.HeaderPtr[m  ];
            	} else {
                	sptr = this.HeaderPtr[m ];
                	eptr = this.HeaderPtr[m+1];
            	}
	
            	break;
        	}
	
        	//less then the middle value
        	if ( ip < this.HeaderSip[m] ) {
            	if ( m == 0 ) {
                	sptr = this.HeaderPtr[m  ];
                	eptr = this.HeaderPtr[m+1];
                	break;
            	} else if ( ip > this.HeaderSip[m-1] ) {
                	sptr = this.HeaderPtr[m-1];
                	eptr = this.HeaderPtr[m  ];
                	break;
            	}
            	h = m - 1;
        	} else {
            	if ( m == this.headerLen - 1 ) {
                	sptr = this.HeaderPtr[m-1];
                	eptr = this.HeaderPtr[m  ];
                	break;
            	} else if ( ip <= this.HeaderSip[m+1] ) {
                	sptr = this.HeaderPtr[m  ];
                	eptr = this.HeaderPtr[m+1];
                	break;
            	}
            	l = m + 1;
        	}
    	}
	
    	//not matched just stop it
    	if ( sptr == 0 ) return ;
	
    	var indexBlockLen = eptr - sptr;
    	this.file.seek("set", sptr);
    	var buf = ..raw.buffer(indexBlockLen + INDEX_BLOCK_LENGTH)
    	if(!this.file.readBuffer(buf)){
    		return ; 
    	} 
    	
	
    	var (dptr = 0; l = 0; h = indexBlockLen / INDEX_BLOCK_LENGTH;)
    	while ( l <= h ) {
        	m = ((l + h) >> 1);
        	p = m * INDEX_BLOCK_LENGTH;
        	sip = ..raw.convert(buf, {int sip}, p)
        	sip = sip.sip
        	if ( ip < sip ) {
            	h = m - 1;
        	} else {
            	eip = ..raw.convert(buf, {int eip}, p+4)
            	eip = eip.eip
            	if ( ip > eip ) {
                	l = m + 1;
            	} else {
                	dptr = ..raw.convert(buf, {int dptr}, p+8)
                	dptr = dptr.dptr
                	break;
            	}
        	}
    	}
	
    	if ( dptr == 0 ) return 0;
	
    	dataLen = ((dptr >> 24) & 0xFF);
    	dataptr = (dptr & 0x00FFFFFF);
	
		this.file.seek("set", dataptr)
		
		var city_id = this.file.read({INT id}).id;
    	return {
    		city_id = city_id;
    		region = this.file.read(dataLen-4);
    	}; 
	}
	
    close = function(){
        if(this.file){
        	this.file.close();
        	this.file=null
        }
    }; 
    string2ip = function (str){
		return  ..wsock.htonl(..wsock.inet_addr(str))     
    };
    getIpInfo = function(ip, mode = "btree") {
        var search = this[[mode+"_search"]]
        if(type(search)!==type.function){
        	return;
        }
        if (!owner.isValidIp(ip)) return;

        var ipInfo = IpInfo()
        ip = this.string2ip(ip)
        var data = search(ip)
        if (data) {
            var arr = split(data.region, "|")
            if (# arr = 5) {
                ipInfo.CityId = data.city_id
                ipInfo.Country = arr[1]
                ipInfo.Region = arr[2]
                ipInfo.Province = arr[3]
                ipInfo.City = arr[4]
                ipInfo.ISP = arr[5]
            }
        }
        return ipInfo
    };
    isValidIp = function(s) {
        return match(s, "\d+\.\d+\.\d+\.\d+") ? true : false
    };
}

namespace ip2region{
	INDEX_BLOCK_LENGTH=12;
	TOTAL_HEADER_LENGTH=8192;
	
	match = ..string.match;
	concat = ..string.concat;
	split = ..string.split;
	
    class IpInfo {
        CityId=0;
        Country="";
        Region="";
        Province="";
        City="";
        ISP="";
        @_meta;
    }
    
    IpInfo._meta = {
        _tostring = function() {
            return concat(owner.Country, owner.Province, owner.City, " ", owner.ISP)
        }
    }
    
    import web.rest.client;
    var http = web.rest.client();
    getIp = function() {
        return http.api("https://www.taobao.com/help/getip.php", "GET", "\d+\.\d+\.\d+\.\d+")();
    }
}


/**intellisense()
inet.ip2region = ip2region数据库
inet.ip2region() = 创建IP数据库连接\n!inet_ip2region.
!inet_ip2region.getIpInfo( = 查询IP归属性
!inet_ip2region.getIpInfo(.("IP地址") = 返回IP归属地
!inet_ip2region.close() = 关闭数据库连接
end intellisense**/


1 个回复 | 最后更新于 2022-01-20
2022-01-20   #1

矫情,哈哈

登录后方可回帖

登 录
信息栏
公告:
个人博客
专注分享
谢谢合作!

本站域名:HtmLayout.Cn
aardio可以快速开发上位机,本站主要记录了学习过程中遇到的问题和解决办法及aardio代码分享

这里主要专注于aardio学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.

Aardio 官方站:Aardio官方
Aardio最新功能:Aardio官方更新日志
本 站 主 站:Stm32cube中文网
Sciter中文在线文档Sciter在线学习文档
空间赞助:才仁机械
打赏本站
Loading...