Ip.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. <?php
  2. /*
  3. 全球 IPv4 地址归属地数据库(17MON.CN 版)
  4. 高春辉(pAUL gAO) <gaochunhui@gmail.com>
  5. Build 20141009 版权所有 17MON.CN
  6. (C) 2006 - 2014 保留所有权利
  7. 请注意及时更新 IP 数据库版本
  8. 数据问题请加 QQ 群: 346280296
  9. Code for PHP 5.3+ only
  10. */
  11. class Ip
  12. {
  13. private static $ip = NULL;
  14. private static $fp = NULL;
  15. private static $offset = NULL;
  16. private static $index = NULL;
  17. private static $cached = array();
  18. public static function find($ip)
  19. {
  20. if (empty($ip) === TRUE)
  21. {
  22. // 始终返回数组,避免调用方 implode() 时报 Invalid arguments
  23. return array('N/A');
  24. }
  25. $nip = gethostbyname($ip);
  26. $ipdot = explode('.', $nip);
  27. if ($ipdot[0] < 0 || $ipdot[0] > 255 || count($ipdot) !== 4)
  28. {
  29. return array('N/A');
  30. }
  31. if (isset(self::$cached[$nip]) === TRUE)
  32. {
  33. return self::$cached[$nip];
  34. }
  35. if (self::$fp === NULL)
  36. {
  37. self::init();
  38. }
  39. $nip2 = pack('N', ip2long($nip));
  40. $tmp_offset = (int)$ipdot[0] * 4;
  41. $start = unpack('Vlen', self::$index[$tmp_offset] . self::$index[$tmp_offset + 1] . self::$index[$tmp_offset + 2] . self::$index[$tmp_offset + 3]);
  42. $index_offset = $index_length = NULL;
  43. $max_comp_len = self::$offset['len'] - 1024 - 4;
  44. for ($start = $start['len'] * 8 + 1024; $start < $max_comp_len; $start += 8)
  45. {
  46. if (self::$index[$start] . self::$index[$start + 1] . self::$index[$start + 2] . self::$index[$start + 3] >= $nip2)
  47. {
  48. $index_offset = unpack('Vlen', self::$index[$start + 4] . self::$index[$start + 5] . self::$index[$start + 6] . "\x0");
  49. $index_length = unpack('Clen', self::$index[$start + 7]);
  50. break;
  51. }
  52. }
  53. if ($index_offset === NULL)
  54. {
  55. return array('N/A');
  56. }
  57. fseek(self::$fp, self::$offset['len'] + $index_offset['len'] - 1024);
  58. self::$cached[$nip] = explode("\t", fread(self::$fp, $index_length['len']));
  59. return self::$cached[$nip];
  60. }
  61. private static function init()
  62. {
  63. if (self::$fp === NULL)
  64. {
  65. self::$ip = new self();
  66. self::$fp = fopen(__DIR__ . '/ip/17monipdb.dat', 'rb');
  67. if (self::$fp === FALSE)
  68. {
  69. throw new Exception('Invalid 17monipdb.dat file!');
  70. }
  71. self::$offset = unpack('Nlen', fread(self::$fp, 4));
  72. if (self::$offset['len'] < 4)
  73. {
  74. throw new Exception('Invalid 17monipdb.dat file!');
  75. }
  76. self::$index = fread(self::$fp, self::$offset['len'] - 4);
  77. }
  78. }
  79. public function __destruct()
  80. {
  81. if (self::$fp !== NULL)
  82. {
  83. fclose(self::$fp);
  84. }
  85. }
  86. }
  87. ?>