Provide an IP geolocation query class again

Source: Internet
Author: User
Tags fread unpack
IP geolocation Query class
  1. /**
  2. File name: IpLocation.class.php
  3. * IP Geo-Location query class (Master file I'm uploading it.) I upload a test file, and there is a QQWry.Dat this can be downloaded to the pure IP library because there are more than 6M so here do not upload it up.
  4. *
  5. * @author Ma Bingyao
  6. * @version 1.5
  7. * @copyright 2005 coolcode.cn
  8. */
  9. Class Iplocation {
  10. /**
  11. * QQWry.Dat file pointer
  12. * @var Resource
  13. */
  14. var $fp;
  15. /**
  16. * The offset address of the first IP record
  17. * @var int
  18. */
  19. var $firstip;
  20. /**
  21. * Offset address of last IP record
  22. * @var int
  23. */
  24. var $lastip;
  25. /**
  26. * Total number of IP records (not including version information Records)
  27. * @var int
  28. */
  29. var $totalip;
  30. /**
  31. * constructor to open the QQWry.Dat file and initialize the information in the class
  32. * @param string $filename
  33. * @return Iplocation
  34. */
  35. function __construct ($filename = "QQWry.Dat") {
  36. $this->FP = 0;
  37. if ($this->FP = @fopen ($filename, ' RB ')!== false) {
  38. $this->firstip = $this->getlong ();
  39. $this->lastip = $this->getlong ();
  40. $this->totalip = ($this->lastip-$this->firstip)/7;
  41. Register the destructor so that it executes at the end of the program execution
  42. Register_shutdown_function (Array (& $this, ' __construct '));
  43. }
  44. }
  45. /**
  46. * Returns the number of read long integers
  47. * @access Private
  48. * @return int
  49. */
  50. function Getlong () {
  51. Converts the Read Little-endian encoded 4 bytes to a long integer number
  52. $result = Unpack (' Vlong ', fread ($this->FP, 4));
  53. return $result [' Long '];
  54. }
  55. /**
  56. * Returns the number of 3-byte long integers read
  57. *
  58. * @access Private
  59. * @return int
  60. */
  61. function Getlong3 () {
  62. Converts the Read Little-endian encoded 3 bytes to a long integer number
  63. $result = Unpack (' Vlong ', fread ($this->FP, 3). chr (0));
  64. return $result [' Long '];
  65. }
  66. /**
  67. * Returns the IP address that can be compared after compression
  68. *
  69. * @access Private
  70. * @param string $ip
  71. * @return String
  72. */
  73. function Packip ($IP) {
  74. Converts the IP address to a long integer and returns false if the IP address is incorrect in PHP5.
  75. At this point intval converts the flase to an integer-1, which is then compressed into Big-endian encoded string
  76. Return pack (' N ', Intval (Ip2long ($IP)));
  77. }
  78. /**
  79. * Returns the Read string
  80. *
  81. * @access Private
  82. * @param string $data
  83. * @return String
  84. */
  85. function GetString ($data = "") {
  86. $char = Fread ($this->fp, 1);
  87. while (Ord ($char) > 0) {//string is saved in C format and ends in
  88. $data. = $char; Connect prompt the read word after the given string
  89. $char = Fread ($this->fp, 1);
  90. }
  91. return $data;
  92. }
  93. /**
  94. * Return Area information
  95. *
  96. * @access Private
  97. * @return String
  98. */
  99. function Getarea () {
  100. $byte = Fread ($this->fp, 1); Flag byte
  101. Switch (ord ($byte)) {
  102. Case 0://No area information
  103. $area = "";
  104. Break
  105. Case 1:
  106. Case 2://Flag byte 1 or 2 indicating that the zone information is redirected
  107. Fseek ($this->fp, $this->getlong3 ());
  108. $area = $this->getstring ();
  109. Break
  110. Default://Otherwise, indicates that the zone information has not been redirected
  111. $area = $this->getstring ($byte);
  112. Break
  113. }
  114. return $area;
  115. }
  116. /**
  117. * Return the region information according to the IP address or domain name given
  118. * @access Public
  119. * @param string $ip
  120. * @return Array
  121. */
  122. function GetLocation ($IP) {
  123. if (! $this->FP) return null; If the data file is not opened correctly, return empty
  124. $location [' ip '] = gethostbyname ($IP); Convert the entered domain name to an IP address
  125. $ip = $this->packip ($location [' IP ']); Convert the IP address you entered into a comparable IP address
  126. Illegal IP address will be converted to 255.255.255.255
  127. Search by split
  128. $l = 0; The bottom boundary of the search
  129. $u = $this->totalip; Top boundary of search
  130. $findip = $this->lastip; Returns the last IP record (version information for QQWry.Dat) if it is not found
  131. while ($l <= $u) {//when the upper boundary is less than the lower boundary, the lookup fails
  132. $i = Floor (($l + $u)/2); Calculate approximate intermediate records
  133. Fseek ($this->fp, $this->firstip + $i * 7);
  134. $beginip = Strrev (fread ($this->FP, 4)); Gets the start IP address of the intermediate record
  135. The purpose of the Strrev function here is to convert the Little-endian's compressed IP address into a Big-endian format.
  136. To be used for comparison, the same later.
  137. if ($ip < $beginip) {//user's IP is smaller than the intermediate record's start IP address
  138. $u = $i-1; Modify the top boundary of the search to the intermediate record minus one
  139. } else {
  140. Fseek ($this->fp, $this->getlong3 ());
  141. $endip = Strrev (fread ($this->FP, 4)); Gets the end IP address of the intermediate record
  142. if ($ip > $endip) {//user's IP is greater than the end IP address of the intermediate record
  143. $l = $i + 1; Modify the bottom boundary of the search to an intermediate record plus a
  144. } else {//The IP of the user is within the IP range of the intermediate record
  145. $findip = $this->firstip + $i * 7;
  146. Break Indicates that the result is found and exits the loop
  147. }
  148. }
  149. }
  150. Get the IP geolocation information that was found
  151. Fseek ($this->fp, $findip);
  152. $location [' beginip '] = Long2ip ($this->getlong ()); Start address of the range where the user IP is located
  153. $offset = $this->getlong3 ();
  154. Fseek ($this->fp, $offset);
  155. $location [' endip '] = Long2ip ($this->getlong ()); End address of the range where the user IP is located
  156. $byte = Fread ($this->fp, 1); Flag byte
  157. Switch (ord ($byte)) {
  158. Case 1://Flag byte 1, indicating that national and regional information is being redirected at the same time
  159. $countryOffset = $this->getlong3 (); REDIRECT Address
  160. Fseek ($this->fp, $countryOffset);
  161. $byte = Fread ($this->fp, 1); Flag byte
  162. Switch (ord ($byte)) {
  163. Case 2://Flag Byte is 2, indicating that the country information is redirected again
  164. Fseek ($this->fp, $this->getlong3 ());
  165. $location [' country '] = $this->getstring ();
  166. Fseek ($this->fp, $countryOffset + 4);
  167. $location [' area '] = $this->getarea ();
  168. Break
  169. Default://Otherwise, indicates that the country information has not been redirected
  170. $location [' country '] = $this->getstring ($byte);
  171. $location [' area '] = $this->getarea ();
  172. Break
  173. }
  174. Break
  175. Case 2://Flag Byte is 2, indicating that the country information is redirected
  176. Fseek ($this->fp, $this->getlong3 ());
  177. $location [' country '] = $this->getstring ();
  178. Fseek ($this->fp, $offset + 8);
  179. $location [' area '] = $this->getarea ();
  180. Break
  181. Default://Otherwise, indicates that the country information has not been redirected
  182. $location [' country '] = $this->getstring ($byte);
  183. $location [' area '] = $this->getarea ();
  184. Break
  185. }
  186. if ($location [' country '] = = "Cz88.net") {//CZ88. NET means no valid information
  187. $location [' country '] = "Unknown";
  188. }
  189. if ($location [' area '] = = "Cz88.net") {
  190. $location [' area '] = "";
  191. }
  192. return $location;
  193. }
  194. /**
  195. * destructor to automatically close open files after the page execution ends.
  196. *
  197. */
  198. function __desctruct () {
  199. if ($this->fp) {
  200. Fclose ($this->FP);
  201. }
  202. $this->FP = 0;
  203. }
  204. }
  205. ?>
Copy Code
    1. Require_once (' IpLocation.class.php ');
    2. $ip = ' 127.0.0.1 ';
    3. $idADDR =new iplocation ();
    4. Print_r ($idADDR->getlocation ($IP));
    5. ?>
Copy Code
  1. /**
  2. * IP geolocation Query class
  3. *
  4. * @author Ma Bingyao
  5. * @version 1.5
  6. * @copyright 2005 coolcode.cn
  7. */
  8. Class Iplocation {
  9. /**
  10. * QQWry.Dat file pointer
  11. * @var Resource
  12. */
  13. var $fp;
  14. /**
  15. * The offset address of the first IP record
  16. * @var int
  17. */
  18. var $firstip;
  19. /**
  20. * Offset address of last IP record
  21. * @var int
  22. */
  23. var $lastip;
  24. /**
  25. * Total number of IP records (not including version information Records)
  26. * @var int
  27. */
  28. var $totalip;
  29. /**
  30. * constructor to open the QQWry.Dat file and initialize the information in the class
  31. * @param string $filename
  32. * @return Iplocation
  33. */
  34. function __construct ($filename = "QQWry.Dat") {
  35. $this->FP = 0;
  36. if ($this->FP = @fopen ($filename, ' RB ')!== false) {
  37. $this->firstip = $this->getlong ();
  38. $this->lastip = $this->getlong ();
  39. $this->totalip = ($this->lastip-$this->firstip)/7;
  40. Register the destructor so that it executes at the end of the program execution
  41. Register_shutdown_function (Array (& $this, ' __construct '));
  42. }
  43. }
  44. /**
  45. * Returns the number of read long integers
  46. * @access Private
  47. * @return int
  48. */
  49. function Getlong () {
  50. Converts the Read Little-endian encoded 4 bytes to a long integer number
  51. $result = Unpack (' Vlong ', fread ($this->FP, 4));
  52. return $result [' Long '];
  53. }
  54. /**
  55. * Returns the number of 3-byte long integers read
  56. *
  57. * @access Private
  58. * @return int
  59. */
  60. function Getlong3 () {
  61. Converts the Read Little-endian encoded 3 bytes to a long integer number
  62. $result = Unpack (' Vlong ', fread ($this->FP, 3). chr (0));
  63. return $result [' Long '];
  64. }
  65. /**
  66. * Returns the IP address that can be compared after compression
  67. *
  68. * @access Private
  69. * @param string $ip
  70. * @return String
  71. */
  72. function Packip ($IP) {
  73. Converts the IP address to a long integer and returns false if the IP address is incorrect in PHP5.
  74. At this point intval converts the flase to an integer-1, which is then compressed into Big-endian encoded string
  75. Return pack (' N ', Intval (Ip2long ($IP)));
  76. }
  77. /**
  78. * Returns the Read string
  79. *
  80. * @access Private
  81. * @param string $data
  82. * @return String
  83. */
  84. function GetString ($data = "") {
  85. $char = Fread ($this->fp, 1);
  86. while (Ord ($char) > 0) {//string is saved in C format and ends in
  87. $data. = $char; Connect prompt the read word after the given string
  88. $char = Fread ($this->fp, 1);
  89. }
  90. return $data;
  91. }
  92. /**
  93. * Return Area information
  94. *
  95. * @access Private
  96. * @return String
  97. */
  98. function Getarea () {
  99. $byte = Fread ($this->fp, 1); Flag byte
  100. Switch (ord ($byte)) {
  101. Case 0://No area information
  102. $area = "";
  103. Break
  104. Case 1:
  105. Case 2://Flag byte 1 or 2 indicating that the zone information is redirected
  106. Fseek ($this->fp, $this->getlong3 ());
  107. $area = $this->getstring ();
  108. Break
  109. Default://Otherwise, indicates that the zone information has not been redirected
  110. $area = $this->getstring ($byte);
  111. Break
  112. }
  113. return $area;
  114. }
  115. /**
  116. * Return the region information according to the IP address or domain name given
  117. * @access Public
  118. * @param string $ip
  119. * @return Array
  120. */
  121. function GetLocation ($IP) {
  122. if (! $this->FP) return null; If the data file is not opened correctly, return empty
  123. $location [' ip '] = gethostbyname ($IP); Convert the entered domain name to an IP address
  124. $ip = $this->packip ($location [' IP ']); Convert the IP address you entered into a comparable IP address
  125. Illegal IP address will be converted to 255.255.255.255
  126. Search by split
  127. $l = 0; The bottom boundary of the search
  128. $u = $this->totalip; Top boundary of search
  129. $findip = $this->lastip; Returns the last IP record (version information for QQWry.Dat) if it is not found
  130. while ($l <= $u) {//when the upper boundary is less than the lower boundary, the lookup fails
  131. $i = Floor (($l + $u)/2); Calculate approximate intermediate records
  132. Fseek ($this->fp, $this->firstip + $i * 7);
  133. $beginip = Strrev (fread ($this->FP, 4)); Gets the start IP address of the intermediate record
  134. The purpose of the Strrev function here is to convert the Little-endian's compressed IP address into a Big-endian format.
  135. To be used for comparison, the same later.
  136. if ($ip < $beginip) {//user's IP is smaller than the intermediate record's start IP address
  137. $u = $i-1; Modify the top boundary of the search to the intermediate record minus one
  138. } else {
  139. Fseek ($this->fp, $this->getlong3 ());
  140. $endip = Strrev (fread ($this->FP, 4)); Gets the end IP address of the intermediate record
  141. if ($ip > $endip) {//user's IP is greater than the end IP address of the intermediate record
  142. $l = $i + 1; Modify the bottom boundary of the search to an intermediate record plus a
  143. } else {//The IP of the user is within the IP range of the intermediate record
  144. $findip = $this->firstip + $i * 7;
  145. Break Indicates that the result is found and exits the loop
  146. }
  147. }
  148. }
  149. Get the IP geolocation information that was found
  150. Fseek ($this->fp, $findip);
  151. $location [' beginip '] = Long2ip ($this->getlong ()); Start address of the range where the user IP is located
  152. $offset = $this->getlong3 ();
  153. Fseek ($this->fp, $offset);
  154. $location [' endip '] = Long2ip ($this->getlong ()); End address of the range where the user IP is located
  155. $byte = Fread ($this->fp, 1); Flag byte
  156. Switch (ord ($byte)) {
  157. Case 1://Flag byte 1, indicating that national and regional information is being redirected at the same time
  158. $countryOffset = $this->getlong3 (); REDIRECT Address
  159. Fseek ($this->fp, $countryOffset);
  160. $byte = Fread ($this->fp, 1); Flag byte
  161. Switch (ord ($byte)) {
  162. Case 2://Flag Byte is 2, indicating that the country information is redirected again
  163. Fseek ($this->fp, $this->getlong3 ());
  164. $location [' country '] = $this->getstring ();
  165. Fseek ($this->fp, $countryOffset + 4);
  166. $location [' area '] = $this->getarea ();
  167. Break
  168. Default://Otherwise, indicates that the country information has not been redirected
  169. $location [' country '] = $this->getstring ($byte);
  170. $location [' area '] = $this->getarea ();
  171. Break
  172. }
  173. Break
  174. Case 2://Flag Byte is 2, indicating that the country information is redirected
  175. Fseek ($this->fp, $this->getlong3 ());
  176. $location [' country '] = $this->getstring ();
  177. Fseek ($this->fp, $offset + 8);
  178. $location [' area '] = $this->getarea ();
  179. Break
  180. Default://Otherwise, indicates that the country information has not been redirected
  181. $location [' country '] = $this->getstring ($byte);
  182. $location [' area '] = $this->getarea ();
  183. Break
  184. }
  185. if ($location [' country '] = = "Cz88.net") {//CZ88. NET means no valid information
  186. $location [' country '] = "Unknown";
  187. }
  188. if ($location [' area '] = = "Cz88.net") {
  189. $location [' area '] = "";
  190. }
  191. return $location;
  192. }
  193. /**
  194. * destructor to automatically close open files after the page execution ends.
  195. *
  196. */
  197. function __desctruct () {
  198. if ($this->fp) {
  199. Fclose ($this->FP);
  200. }
  201. $this->FP = 0;
  202. }
  203. }
  204. ?>
Copy Code
  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.