Created
September 11, 2012 06:04
-
-
Save wangshijun/3696328 to your computer and use it in GitHub Desktop.
php: get client location city based on ip address
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* 根据用户IP获取用户所在城市 | |
* @param string $userip IP | |
* @return string Location | |
* @todo Implement this service in an OOP way, and Silington Pattern | |
*/ | |
function get_client_location($userip) { | |
//IP数据库路径 | |
$dat_path = 'qqwry.dat'; | |
$useripAddr1 = ""; | |
//打开IP数据库 | |
if (!$fd = @fopen($dat_path, 'rb')){ | |
return 'IP data file not exists or access denied'; | |
} | |
//explode函数分解IP地址,运算得出整数形结果 | |
$userip = explode('.', $userip); | |
$useripNum = $userip[0] * 16777216 + $userip[1] * 65536 + $userip[2] * 256 + $userip[3]; | |
//获取IP地址索引开始和结束位置 | |
$DataBegin = fread($fd, 4); | |
$DataEnd = fread($fd, 4); | |
$useripbegin = implode('', unpack('L', $DataBegin)); | |
if ($useripbegin < 0) $useripbegin += pow(2, 32); | |
$useripend = implode('', unpack('L', $DataEnd)); | |
if ($useripend < 0) $useripend += pow(2, 32); | |
$useripAllNum = ($useripend - $useripbegin) / 7 + 1; | |
$BeginNum = 0; | |
$EndNum = $useripAllNum; | |
$userip1num = $BeginNum; | |
$userip2num = $EndNum; | |
//使用二分查找法从索引记录中搜索匹配的IP地址记录 | |
while($userip1num>$useripNum || $userip2num<$useripNum) { | |
$Middle= intval(($EndNum + $BeginNum) / 2); | |
//偏移指针到索引位置读取4个字节 | |
fseek($fd, $useripbegin + 7 * $Middle); | |
$useripData1 = fread($fd, 4); | |
if (strlen($useripData1) < 4) { | |
fclose($fd); | |
return 'File Error'; | |
} | |
//提取出来的数据转换成长整形,如果数据是负数则加上2的32次幂 | |
$userip1num = implode('', unpack('L', $useripData1)); | |
if ($userip1num < 0) { | |
$userip1num += pow(2, 32); | |
} | |
//提取的长整型数大于我们IP地址则修改结束位置进行下一次循环 | |
if ($userip1num > $useripNum) { | |
$EndNum = $Middle; | |
continue; | |
} | |
//取完上一个索引后取下一个索引 | |
$DataSeek = fread($fd, 3); | |
if (strlen($DataSeek) < 3) { | |
fclose($fd); | |
return 'File Error'; | |
} | |
$DataSeek = implode('', unpack('L', $DataSeek.chr(0))); | |
fseek($fd, $DataSeek); | |
$useripData2 = fread($fd, 4); | |
if (strlen($useripData2) < 4) { | |
fclose($fd); | |
return 'File Error'; | |
} | |
$userip2num = implode('', unpack('L', $useripData2)); | |
if ($userip2num < 0) $userip2num += pow(2, 32); | |
//找不到IP地址对应城市 | |
if ($userip2num < $useripNum) { | |
if ($Middle == $BeginNum) { | |
fclose($fd); | |
return 'No Data'; | |
} | |
$BeginNum = $Middle; | |
} | |
} | |
$useripFlag = fread($fd, 1); | |
if ($useripFlag == chr(1)) { | |
$useripSeek = fread($fd, 3); | |
if (strlen($useripSeek) < 3) { | |
fclose($fd); | |
return 'System Error'; | |
} | |
$useripSeek = implode('', unpack('L', $useripSeek.chr(0))); | |
fseek($fd, $useripSeek); | |
$useripFlag = fread($fd, 1); | |
} | |
if ($useripFlag == chr(2)) { | |
$AddrSeek = fread($fd, 3); | |
if (strlen($AddrSeek) < 3) { | |
fclose($fd); | |
return 'System Error'; | |
} | |
$useripFlag = fread($fd, 1); | |
if ($useripFlag == chr(2)) { | |
$AddrSeek2 = fread($fd, 3); | |
if (strlen($AddrSeek2) < 3) { | |
fclose($fd); | |
return 'System Error'; | |
} | |
$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0))); | |
fseek($fd, $AddrSeek2); | |
} else { | |
fseek($fd, -1, SEEK_CUR); | |
} | |
$AddrSeek = implode('', unpack('L', $AddrSeek.chr(0))); | |
fseek($fd, $AddrSeek); | |
while(($char = fread($fd, 1)) != chr(0)) { | |
$useripAddr1 .= $char; | |
} | |
} else { | |
fseek($fd, -1, SEEK_CUR); | |
while(($char = fread($fd, 1)) != chr(0)) | |
$useripAddr1 .= $char; | |
$useripFlag = fread($fd, 1); | |
if ($useripFlag == chr(2)) { | |
$AddrSeek2 = fread($fd, 3); | |
if (strlen($AddrSeek2) < 3) { | |
fclose($fd); | |
return 'System Error'; | |
} | |
$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0))); | |
fseek($fd, $AddrSeek2); | |
} else { | |
fseek($fd, -1, SEEK_CUR); | |
} | |
} | |
fclose($fd); | |
return $useripAddr1; | |
} | |
/** | |
* PHP获取当前用户IP地址 | |
* @return string IP | |
*/ | |
function get_client_ip() { | |
$client_ip = null; | |
if (isset($_SERVER["HTTP_VIA"])) { | |
$client_ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; | |
} else { | |
$client_ip = $_SERVER["REMOTE_ADDR"]; | |
} | |
return $client_ip; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment