Skip to content

Instantly share code, notes, and snippets.

@wangshijun
Created September 11, 2012 06:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wangshijun/3696328 to your computer and use it in GitHub Desktop.
Save wangshijun/3696328 to your computer and use it in GitHub Desktop.
php: get client location city based on ip address
<?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