Files
web-discuz/source/class/ip/ip_v6wry.php
2025-06-27 21:04:18 +08:00

123 lines
3.0 KiB
PHP
Executable File

<?php
if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
class ip_v6wry_init_exception extends Exception {}
class ip_v6wry {
private static $instance = null;
public $ipdb,$firstIndex,$indexCount,$offlen;
public function __construct() {
$ipdatafile = constant("DISCUZ_ROOT").'./data/ipdata/ipv6wry.dat';
$this->ipdb = fopen($ipdatafile,'rb');
if (!$this->ipdb) {
throw new ip_v6wry_init_exception();
}
$this->firstIndex = unpack('V',$this->reader(16,8))[1];
$this->indexCount = unpack('V',$this->reader(8,8))[1];
$this->offlen = ord($this->reader(6,1));
}
public function __destruct() {
if($this->ipdb) {
@fclose($this->ipdb);
}
}
public static function getInstance() {
if (!self::$instance) {
try {
self::$instance = new ip_v6wry();
} catch (Exception $e) {
return null;
}
}
return self::$instance;
}
public function getstring($offset) {
fseek($this->ipdb,$offset);
$flag = 1;
$return = '';
while($flag) {
$i = fread($this->ipdb,1);
if($i === "\0") {
$flag = 0;
} else {
$return .= $i;
}
}
return $return;
}
public function getareaaddr($offset) {
$byte = ord($this->reader($offset,1));
if($byte == 1 || $byte == 2) {
$p = unpack('V',str_pad($this->reader($offset + 1,$this->offlen),4,"\0"))[1];
return $this->getareaaddr($p);
} else {
return $this->getstring($offset);
}
}
public function getaddr($offset) {
$byte = ord($this->reader($offset,1));
if($byte == 1) {
return $this->getaddr(unpack('V',str_pad($this->reader($offset + 1,$this->offlen),4,"\0"))[1]);
} else {
$carea = $this->getareaaddr($offset);
if($byte == 2) {
$offset += 1 + $this->offlen;
} else {
$offset += strlen($carea) + 1;
}
$aarea = $this->getareaaddr($offset);
return [$carea,$aarea];
}
}
public function ipcomp($ip1,$ip2) {
$ip1a = unpack('v',substr($ip1,-2))[1];
$ip2a = unpack('v',substr($ip2,-2))[1];
if($ip1a == $ip2a) {
if(strlen($ip1)<=2) {
return 0;
} else {
return $this->ipcomp(substr($ip1,0,-2),substr($ip2,0,-2));
}
} elseif($ip1a > $ip2a) {
return 1;
} else {
return -1;
}
}
public function reader($offset,$length) {
fseek($this->ipdb,$offset);
return fread($this->ipdb,$length);
}
public function finder($ip,$l,$r) {
if($r-$l<=1) {
return $l;
}
$m = intval(($l + $r)/2);
$o = $this->firstIndex + $m * (8 + $this->offlen);
$new_ip = $this->reader($o,8);
if($this->ipcomp($new_ip,$ip)>0) {
return $this->finder($ip,$l,$m);
} else {
return $this->finder($ip,$m,$r);
}
}
public function getipaddr($ip) {
$ipbinary = inet_pton($ip);
if($ipbinary == false) {
return '- Unknown';
}
$iprev = strrev($ipbinary);
$i = $this->finder($iprev,0,$this->indexCount);
$o = $this->firstIndex + $i * (8 + $this->offlen);
$output = $this->getaddr(unpack('L',str_pad($this->reader($o + 8,$this->offlen),4,"\0"))[1]);
return $output;
}
public function convert($ip) {
return '- '.diconv(implode(' ',$this->getipaddr($ip)),'utf-8');
}
}
?>