mirror of https://github.com/dnomd343/echoIP
Dnomd343
4 years ago
3 changed files with 108 additions and 1 deletions
@ -0,0 +1,96 @@ |
|||
<?php |
|||
|
|||
// 数据来源:IPIP免费数据库 ipipfree.ipdb |
|||
// 初始化类:new IPDB($fileName) |
|||
// 请求方式:getDistrict($ip) |
|||
// 返回格式: |
|||
// { |
|||
// '0': 国家 |
|||
// '1': 省、直辖市 |
|||
// '2': 市 |
|||
// } |
|||
// 注:仅国内省市数据 |
|||
// |
|||
// 请求版本:getVersion() |
|||
// 返回格式:YYYYMMDD |
|||
|
|||
class IPDB { |
|||
private $fp; // 文件指针 |
|||
private $meta; // 元数据信息 |
|||
private $nodeCount; |
|||
private $nodeOffset; |
|||
|
|||
public function __construct($fileName) { // 构造函数 |
|||
$this->fp = fopen($fileName, 'rb'); |
|||
$metaSize = unpack('N', fread($this->fp, 4))[1]; // 获取元数据长度 |
|||
$this->meta = json_decode(fread($this->fp, $metaSize), 1); // 读取元数据信息 |
|||
$this->nodeCount = $this->meta['node_count']; |
|||
$this->nodeOffset = 4 + $metaSize; |
|||
} |
|||
|
|||
public function __destruct() { // 析构函数 |
|||
if ($this->fp) { |
|||
fclose($this->fp); |
|||
} |
|||
} |
|||
|
|||
public function getVersion() { // 获取版本信息 |
|||
return date("Ymd", $this->meta['build']); |
|||
} |
|||
|
|||
public function getDistrict($ip) { // 获取地区信息 |
|||
$node = $this->getNode($ip); |
|||
if ($node <= 0) { |
|||
return NULL; |
|||
} |
|||
return explode("\t", $this->getData($node)); |
|||
} |
|||
|
|||
private function getNode($ip) { // 获取节点编号 |
|||
$node = 0; |
|||
$binary = inet_pton($ip); |
|||
for ($i = 0; $i < 96 && $node < $this->nodeCount; $i++) { |
|||
if ($i >= 80) { |
|||
$node = $this->readNode($node, 1); |
|||
} else { |
|||
$node = $this->readNode($node, 0); |
|||
} |
|||
if ($node > $this->nodeCount) { |
|||
return 0; |
|||
} |
|||
} |
|||
for ($i = 0; $i < 32; $i++) { |
|||
if ($node >= $this->nodeCount) { |
|||
break; |
|||
} |
|||
$node = $this->readNode($node, 1 & ((0xFF & ord($binary[$i >> 3])) >> 7 - ($i % 8))); |
|||
} |
|||
if ($node <= $this->nodeCount) { |
|||
return NULL; |
|||
} |
|||
return $node; |
|||
} |
|||
|
|||
private function readNode($node, $index) { |
|||
return unpack('N', $this->read($node * 8 + $index * 4, 4))[1]; |
|||
} |
|||
|
|||
private function getData($node) { // 根据节点编号获取信息 |
|||
$offset = $node + $this->nodeCount * 7; |
|||
$bytes = $this->read($offset, 2); |
|||
$size = unpack('N', str_pad($bytes, 4, "\x00", STR_PAD_LEFT))[1]; |
|||
$offset += 2; |
|||
return $this->read($offset, $size); |
|||
} |
|||
|
|||
private function read($offset, $length) { // 从指定位置读取指定长度 |
|||
if ($length <= 0) { |
|||
return NULL; |
|||
} |
|||
if (fseek($this->fp, $offset + $this->nodeOffset) === 0) { |
|||
return fread($this->fp, $length); |
|||
} |
|||
} |
|||
} |
|||
|
|||
?> |
Binary file not shown.
Loading…
Reference in new issue