ip2region小问题修复发
By
money
at 2022-01-20 • 0人收藏 • 974人看过
在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
登录后方可回帖
矫情,哈哈