| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 | <?php /** * ip_area.class.php 根据ip地址获取ip所在地区的类 * * @copyright			(C) 2005-2010 PHPCMS * @license				http://www.phpcms.cn/license/ * @lastmodify			2010-6-7 */class ip_area {	public $fp = NULL;		//定义文件指针	public $func;			//处理的方法	private $offset;			private $index;		/** 	 * 构造函数 	 *  	 */	public function __construct() {		if(@file_exists(PC_PATH.DIRECTORY_SEPARATOR.'libs'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'ipdata'.DIRECTORY_SEPARATOR.'mini.Dat')) {			$this->func = 'data_mini';			$this->fp = @fopen(PC_PATH.DIRECTORY_SEPARATOR.'libs'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'ipdata'.DIRECTORY_SEPARATOR.'mini.Dat', 'rb');			$this->offset = unpack('Nlen', fread($this->fp, 4));			$this->index  = fread($this->fp, $this->offset['len'] - 4);		} elseif(@file_exists(PC_PATH.DIRECTORY_SEPARATOR.'libs'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'ipdata'.DIRECTORY_SEPARATOR.'QQWry.Dat')) {			$this->func = 'data_full';			$this->fp = @fopen(PC_PATH.DIRECTORY_SEPARATOR.'libs'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'ipdata'.DIRECTORY_SEPARATOR.'QQWry.Dat', 'rb');		} elseif(@file_exists(PC_PATH.DIRECTORY_SEPARATOR.'libs'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'ipdata'.DIRECTORY_SEPARATOR.'qqwry.dat')) {			$this->func = 'data_full';			$this->fp = @fopen(PC_PATH.DIRECTORY_SEPARATOR.'libs'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'ipdata'.DIRECTORY_SEPARATOR.'qqwry.dat', 'rb');		}	}	/** 	 * 取得地区名 	 * @param  string $ip IP地址 	 * @ return string/null 	 */	public function get($ip) {		$return = '';		if(preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {			$iparray = explode('.', $ip);			if($iparray[0] == 10 || $iparray[0] == 127 || ($iparray[0] == 192 && $iparray[1] == 168) || ($iparray[0] == 172 && ($iparray[1] >= 16 && $iparray[1] <= 31))) {				$return = 'LAN';			} elseif($iparray[0] > 255 || $iparray[1] > 255 || $iparray[2] > 255 || $iparray[3] > 255) {				$return = 'Invalid IP Address';			} else {				$return = $this->func ? $this->{$this->func}($ip) : '';				if(strpos($return, ' ') !== false) $return = substr($return, 0, strpos($return,' '));			}			if(strtolower(pc_base::load_config('system', 'charset')) == 'utf-8') $return = iconv('gbk', 'utf-8', $return);		}		return $return;	}		/**	* 通过外部接口方式获取详细地址信息	* @return $localinfo province 省份 city城市  sp网络 提供商  pinyin拼音	*/	public function getcitybyapi($ip) {		$api_url = $localinfo = '';		$xml = pc_base::load_sys_class('xml');		pc_base::load_sys_func('iconv');		$api_url = 'http://ipquery.sdo.com/getipinfo.php?ip='.$ip;		$data = $xml->xml_unserialize(@file_get_contents($api_url));		if (CHARSET == 'gbk') {			$data = !empty($data) ? array_iconv($data, 'utf-8', 'gbk') : array();		}				if($data['ip']['result']) {			$localinfo['province'] = $data['ip']['country'];			$localinfo['city'] = $data['ip']['city'];			$localinfo['sp'] = $data['ip']['sp'];					//$name = strtolower(CHARSET) == 'gbk' ? $localinfo['city'] : iconv(CHARSET,'gbk',$localinfo['city']);			$name = str_replace(L('city'),'',$localinfo['city']);			$letters = gbk_to_pinyin($name);				$localinfo['pinyin'] =strtolower(implode('', $letters));				}				return $localinfo;			}		/**	*获取城市名称	*/	public function getcity($ip) {		$localinfo = '';		$address = $this->get($ip);		if(strpos($address,L('province'))!== false && strpos($address,L('city'))!== false){			$address = explode(L('province'), $address);			$address=$address[1];		}		$address = str_replace(L('city'),'',$address);		$localinfo['city']= trim($address);		$name = CHARSET == 'gbk' ? $localinfo['city'] : iconv('utf-8','gbk',$localinfo['city']);		$name = str_replace(L('city'),'',$name);		$letters = gbk_to_pinyin($name);			$localinfo['pinyin'] =strtolower(implode('', $letters));		return $localinfo;	}	/** 	 * 使用mini.Dat ip数据包获取地区 	 * @param  string $ip IP地址 	 * @ return string/null 	 */	private function data_mini($ip) {		$ipdot = explode('.', $ip);		$ipdot[0] = (int)$ipdot[0];		$ipdot[1] = (int)$ipdot[1];		$ip    = pack('N', ip2long($ip));		$length = $this->offset['len'] - 1028;		$start  = unpack('Vlen', $this->index[$ipdot[0] * 4] . $this->index[$ipdot[0] * 4 + 1] . $this->index[$ipdot[0] * 4 + 2] . $this->index[$ipdot[0] * 4 + 3]);		for($start = $start['len'] * 8 + 1024; $start < $length; $start += 8) {			if($this->index{$start} . $this->index{$start + 1} . $this->index{$start + 2} . $this->index{$start + 3} >= $ip) {				$this->index_offset = unpack('Vlen', $this->index{$start + 4} . $this->index{$start + 5} . $this->index{$start + 6} . "\x0");				$this->index_length = unpack('Clen', $this->index{$start + 7});				break;			}		}		fseek($this->fp, $this->offset['len'] + $this->index_offset['len'] - 1024);		if($this->index_length['len']) {			return str_replace('- ', '', fread($this->fp, $this->index_length['len']));		} else {			return 'Unknown';		}	}		/** 	 * 使用QQWry.Dat ip数据包获取地区 	 * @param  string $ip IP地址 	 * @ return string/null 	 */	private function data_full($ip) {		rewind($this->fp);		$ip = explode('.', $ip);		$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];		if(!($DataBegin = fread($this->fp, 4)) || !($DataEnd = fread($this->fp, 4)) ) return;		@$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 = $ip2num = $ip1num = 0;		$ipAddr1 = $ipAddr2 = '';		$EndNum = $ipAllNum;		while($ip1num > $ipNum || $ip2num < $ipNum) {			$Middle= intval(($EndNum + $BeginNum) / 2);			fseek($this->fp, $ipbegin + 7 * $Middle);			$ipData1 = fread($this->fp, 4);			if(strlen($ipData1) < 4) {				fclose($this->fp);				return 'System Error';			}			$ip1num = implode('', unpack('L', $ipData1));			if($ip1num < 0) $ip1num += pow(2, 32);			if($ip1num > $ipNum) {				$EndNum = $Middle;				continue;			}			$DataSeek = fread($this->fp, 3);			if(strlen($DataSeek) < 3) {				fclose($this->fp);				return 'System Error';			}			$DataSeek = implode('', unpack('L', $DataSeek.chr(0)));			fseek($this->fp, $DataSeek);			$ipData2 = fread($this->fp, 4);			if(strlen($ipData2) < 4) {				fclose($this->fp);				return 'System Error';			}			$ip2num = implode('', unpack('L', $ipData2));			if($ip2num < 0) $ip2num += pow(2, 32);			if($ip2num < $ipNum) {				if($Middle == $BeginNum) {					fclose($this->fp);					return 'Unknown';				}				$BeginNum = $Middle;			}		}		$ipFlag = fread($this->fp, 1);		if($ipFlag == chr(1)) {			$ipSeek = fread($this->fp, 3);			if(strlen($ipSeek) < 3) {				fclose($this->fp);				return 'System Error';			}			$ipSeek = implode('', unpack('L', $ipSeek.chr(0)));			fseek($this->fp, $ipSeek);			$ipFlag = fread($this->fp, 1);		}		if($ipFlag == chr(2)) {			$AddrSeek = fread($this->fp, 3);			if(strlen($AddrSeek) < 3) {				fclose($this->fp);				return 'System Error';			}			$ipFlag = fread($this->fp, 1);			if($ipFlag == chr(2)) {				$AddrSeek2 = fread($this->fp, 3);				if(strlen($AddrSeek2) < 3) {					fclose($this->fp);					return 'System Error';				}				$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));				fseek($this->fp, $AddrSeek2);			} else {				fseek($this->fp, -1, SEEK_CUR);			}			while(($char = fread($this->fp, 1)) != chr(0))			$ipAddr2 .= $char;			$AddrSeek = implode('', unpack('L', $AddrSeek.chr(0)));			fseek($this->fp, $AddrSeek);			while(($char = fread($this->fp, 1)) != chr(0))			$ipAddr1 .= $char;		} else {			fseek($this->fp, -1, SEEK_CUR);			while(($char = fread($this->fp, 1)) != chr(0))			$ipAddr1 .= $char;			$ipFlag = fread($this->fp, 1);			if($ipFlag == chr(2)) {				$AddrSeek2 = fread($this->fp, 3);				if(strlen($AddrSeek2) < 3) {					fclose($this->fp);					return 'System Error';				}				$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));				fseek($this->fp, $AddrSeek2);			} else {				fseek($this->fp, -1, SEEK_CUR);			}			while(($char = fread($this->fp, 1)) != chr(0))			$ipAddr2 .= $char;		}		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;	}	private function close() {		@fclose($this->fp);	}}?>
 |