<? php tutorial
/ **
* @ date 2010.12.21
* @ author Wang Gang
* @ email 373882774@qq.com
* @ qq 373882774
* @ blog http://hi.baidu.com/sa123abc/home
Note: The header of the file [first index offset (4byte)] + [last index index offset (4byte)] octet [end ip (4byte)] + [area1] + [area 2] 4 bytes + indefinite long index area [Start ip (4byte)] + [Offset address to recording area (3byte)] 7 bytes
* /
class iplocation {
var $ fp;
var $ firstip; / / First ip index offset address
var $ lastip; / / last ip index offset address
var $ totalip; / / total number of ip
/ *
| ------------------------------------------------- ---------------------------
| Constructor, initialize some variables
| ------------------------------------------------- ---------------------------
|
* /
function iplocation ($ datfile = "qqwry.dat") {
$ this-> fp = fopen ($ datfile, 'rb') or die ("qqwry.dat does not exist, go to the web at <a href = 'http: //www.heqee.com/apps tutorial / download / iplocationapi. rar '> download pure ip database </a>,' qqwry.dat 'into the current directory "); / / open two systems
$ this-> firstip = $ this-> get4b (); / / first ip index absolute offset address
$ this-> lastip = $ this-> get4b (); // The absolute offset of the last ip index
$ this-> totalip = ($ this-> lastip - $ this-> firstip) / 7; / / ip total index area is a fixed length of 7 bytes, divided by 7,
register_shutdown_function (array ($ this, "closefp")); // In order to be compatible with php5 the following version, this class does not use the destructor, automatically shut down the ip library.
}
/ *
| ------------------------------------------------- ---------------------------
Close the ip library
| ------------------------------------------------- ---------------------------
|
* /
function closefp () {
fclose ($ this-> fp);
}
/ *
| ------------------------------------------------- ---------------------------
Read long 4 bytes and decompress long
| ------------------------------------------------- ---------------------------
|
* /
function get4b () {
$ str = unpack ("v", fread ($ this-> fp, 4));
return $ str [1];
}
/ *
| ------------------------------------------------- ---------------------------
Read the redirected offset address
| ------------------------------------------------- ---------------------------
|
* /
function getoffset () {
$ str = unpack ("v", fread ($ this-> fp, 3) .chr (0));
return $ str [1];
}
/ *
| ------------------------------------------------- ---------------------------
| Read ip address details
| ------------------------------------------------- ---------------------------
|
* /
function getstr () {
$ split = fread ($ this-> fp, 1);
while (ord ($ split)! = 0) {
$ str. = $ split;
$ split = fread ($ this-> fp, 1);
}
return $ str;
}
/ *
| ------------------------------------------------- ---------------------------
| Ip iplong into ipv4 ip address, and then he compressed into big-endian byte order, and used to compare the index ip address area
| ------------------------------------------------- ---------------------------
|
* /
function iptoint ($ ip) {
return pack ("n", intval (ip2long ($ ip)));
}
/ *
| ------------------------------------------------- ---------------------------
Get address information
| ------------------------------------------------- ---------------------------
|
* /
function readaddress () {
$ now_offset = ftell ($ this-> fp); // Get the current pointer address
$ flag = $ this-> getflag ();
switch (ord ($ flag)) {
case 0:
$ address = "";
break;
case 1:
case 2:
fseek ($ this-> fp, $ this-> getoffset ());
$ address = $ this-> getstr ();
break;
default:
fseek ($ this-> fp, $ now_offset);
$ address = $ this-> getstr ();
break;
}
return $ address;
}
/ *
| ------------------------------------------------- ---------------------------
Obtain flag 1 or 2 to determine if the address is redirected
| ------------------------------------------------- ---------------------------
|
* /
function getflag () {
return fread ($ this-> fp, 1);
}
/ *
| ------------------------------------------------- ---------------------------
Search for index ip in binary search method
| ------------------------------------------------- ---------------------------
|
* /
function searchip ($ ip) {
$ ip = gethostbyname ($ ip); // change the domain name to ip
$ ip_offset ["ip"] = $ ip;
$ ip = $ this-> iptoint ($ ip); // Convert ip to a long integer
$ firstip = 0; // Search the upper bound
$ lastip = $ this-> totalip; // Search the lower bound
$ ipoffset = $ this-> lastip; / / initialize the offset address of the last ip address
while ($ firstip <= $ lastip) {
$ i = floor (($ firstip + $ lastip) / 2); / / Calculate the approximate middle of the floor function Calculate the maximum integer given a small floating-point numbers, to put it bluntly,
fseek ($ this-> fp, $ this-> firstip + $ i * 7); // Locate the pointer to the middle record
$ startip = strrev (fread ($ this-> fp, 4)); // read the start ip address in the current index area and convert its little-endian byte order into big-endian byte order
if ($ ip <$ startip) {
$ lastip = $ i - 1;
}
else {
fseek ($ this-> fp, $ this-> getoffset ());
$ endip = strrev (fread ($ this-> fp, 4));
if ($ ip> $ endip) {
$ firstip = $ i + 1;
}
else {
$ ip_offset ["offset"] = $ this-> firstip + $ i * 7;
break;
}
}
}
return $ ip_offset;
}
/ *
| ------------------------------------------------- ---------------------------
| Get ip address details
| ------------------------------------------------- ---------------------------
|
* /
function getaddress ($ ip) {
$ ip_offset = $ this-> searchip ($ ip); / / Get ip in the index area of the absolute offset address
$ ipoffset = $ ip_offset ["offset"];
$ address ["ip"] = $ ip_offset ["ip"];
fseek ($ this-> fp, $ ipoffset); // Navigate to the index area
$ address ["startip"] = long2ip ($ this-> get4b ()); // start ip address in the index area
$ address_offset = $ this-> getoffset (); / / Get ip index in the ip record area offset address
fseek ($ this-> fp, $ address_offset); // Target to record area
$ address ["endip"] = long2ip ($ this-> get4b ()); // The ending ip address in the recording area
$ flag = $ this-> getflag (); // read the flag byte
switch (ord ($ flag)) {
case 1: // Region 1 Region 2 is redirected
$ address_offset = $ this-> getoffset (); // read the redirect address
fseek ($ this-> fp, $ address_offset); // locate the pointer to the redirected address
$ flag = $ this-> getflag (); // read the flag byte
switch (ord ($ flag)) {
case 2: // area 1 redirected again,
fseek ($ this-> fp, $ this-> getoffset ());
$ address ["area1"] = $ this-> getstr ();
fseek ($ this-> fp, $ address_offset + 4); // jump 4 bytes
$ address ["area2"] = $ this-> readaddress (); / / Area 2 may be redirected, there may not be
break;
default: // Region 1, Region 2 are not redirected
fseek ($ this-> fp, $ address_offset); // locate the pointer to the redirected address
$ address ["area1"] = $ this-> getstr ();
$ address ["area2"] = $ this-> readaddress ();
break;
}
break;
case 2: // Area 1 Redirect Area 2 No redirects
$ address1_offset = $ this-> getoffset (); // read the redirect address
fseek ($ this-> fp, $ address1_offset);
$ address ["area1"] = $ this-> getstr ();
fseek ($ this-> fp, $ address_offset + 8);
$ address ["area2"] = $ this-> readaddress ();
break;
default: // Region 1 Region 2 are not redirected
fseek ($ this-> fp, $ address_offset + 4);
$ address ["area1"] = $ this-> getstr ();
$ address ["area2"] = $ this-> readaddress ();
break;
}
// * filter some useless data
if (strpos ($ address ["area1"], "cz88.net")! = false) {
$ address ["area1"] = "unknown";
}
if (strpos ($ address ["area2"], "cz88.net")! = false) {
$ address ["area2"] = "";
}
return $ address;
}
}
/ * Usage is as follows: * /
$ ip = new iplocation ("qqwry.dat");
$ address = $ ip-> getaddress ("221.231.102.100");
//$address=$ip->getaddress(www.jzread.com);
echo '<pre>';
print_r ($ address);
?>