This article illustrates the method of PHP querying IP location. Share to everyone for your reference.
The implementation methods are as follows:
Copy Code code as follows:
<?php
/**
*@ Date 2010.12.21
Note: file header [offset of first index (4byte)] + [offset address of last index (4byte)] 8 bytes
Record area [end IP (4byte)] + [Region 1] + [Region 2] 4 bytes + indefinite length
Index area [Start IP (4byte)] + [offset address to record area (3byte)] 7 bytes
*/
Class iplocation{
var $fp;
var $firstip; Offset address of the first IP index
var $lastip; Offset address of the last IP index
var $totalip; Total IP number
/*
|----------------------------------------------------------------------------
| constructor to initialize some variables
|----------------------------------------------------------------------------
|
*/
function iplocation ($datfile = "Qqwry.dat") {
$this->fp=fopen ($datfile, ' RB ') or Die ("Qqwry.dat does not exist, please go online <a href= ' http://www.jb51.net/softs/10529.html ' > Download the pure IP database </a>, ' Qqwry.dat ' to the current directory; Two Way Open
$this->firstip = $this->get4b (); Absolute offset address of the first IP index
$this->lastip = $this->get4b (); Absolute offset address of the last IP index
$this->totalip = ($this->lastip-$this->firstip)/7; The IP total index area is a fixed length of 7 bytes, which is divided by 7,
Register_shutdown_function (Array ($this, "CLOSEFP")); In order to be compatible with the following versions, this class does not automatically close the IP library with destructors PHP5.
}
/*
|----------------------------------------------------------------------------
| Close IP Library
|----------------------------------------------------------------------------
|
*/
function Closefp () {
Fclose ($this->FP);
}
/*
|----------------------------------------------------------------------------
| Long mode of reading 4 bytes and decompressing into 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's detailed address information
|----------------------------------------------------------------------------
|
*/
function Getstr () {
$split =fread ($this->fp,1);
while (Ord ($split)!=0) {
$str. = $split;
$split =fread ($this->fp,1);
}
return $str;
}
/*
|----------------------------------------------------------------------------
| Transfer IP via Ip2long to IPv4 's Internet address, and then compress it into Big-endian byte order to compare with the IP address in the index 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;
}
/*
|----------------------------------------------------------------------------
| Get flag 1 or 2 to determine if the address is redirected
|----------------------------------------------------------------------------
|
*/
function Getflag () {
Return fread ($this->fp,1);
}
/*
|----------------------------------------------------------------------------
| Searching IP in index area with the method of two-point search
|----------------------------------------------------------------------------
|
*/
function Searchip ($IP) {
$ip =gethostbyname ($IP); Turn domain name into IP
$ip _offset["IP"]= $ip;
$ip = $this->iptoint ($IP); Convert IP to grow integral type
$firstip = 0; Top bounds for Search
$lastip = $this->totalip; Search the bottom boundary
$ipoffset = $this->lastip; Offset address initialized to the last IP address
while ($firstip <= $lastip) {
$i =floor (($firstip + $lastip)/2); Calculating approximate intermediate record floor function to calculate a given floating-point number of the largest integer small, plainly is the four homes five
Fseek ($this->fp, $this->firstip + $i * 7); Position pointer to intermediate record
$startip =strrev (fread ($this->fp,4)); Reads the start IP address in the current index area and converts its Little-endian byte order into a 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); Gets the absolute IP address in the index area
$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 index area
$address _offset= $this->getoffset (); Gets the offset address of IP within the IP record area within the index area
Fseek ($this->fp, $address _offset); Locate in the record area
$address ["EndIP"]=long2ip ($this->get4b ()); End IP address in the record area
$flag = $this->getflag (); Read Flag bytes
Switch (ord ($flag)) {
Case 1://area 1 area 2 All redirected
$address _offset= $this->getoffset (); Read REDIRECT Address
Fseek ($this->fp, $address _offset); Locate the pointer to the redirected address
$flag = $this->getflag (); Read Flag bytes
Switch (ord ($flag)) {
Case 2://area 1 redirect 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 There may be redirects, there may not be
Break
Default://Region 1, Region 2 No redirect
Fseek ($this->fp, $address _offset); Locate the pointer to the redirected address
$address ["area1"]= $this->getstr ();
$address ["Area2"]= $this->readaddress ();
Break
}
Break
Case 2://Region 1 redirected area 2 No redirect
$address 1_offset= $this->getoffset (); Read REDIRECT Address
Fseek ($this->fp, $address 1_offset);
$address ["area1"]= $this->getstr ();
Fseek ($this->fp, $address _offset+8);
$address ["Area2"]= $this->readaddress ();
Break
Default://Region 1 Area 2 No redirect
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 ("61.129.51.27");
$address = $ip->getaddress (www.jb51.net);
Echo ' <pre> ';
Print_r ($address);
?>
I hope this article will help you with your PHP program design.