QQWry.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <?php
  2. namespace App\Utils;
  3. /*
  4. * @author joyphper
  5. */
  6. class QQWry
  7. {
  8. private $fp;
  9. private $firstip;
  10. private $lastip;
  11. private $totalip;
  12. public function __construct()
  13. {
  14. $filename = BASE_PATH."/storage/qqwry.dat";
  15. $this->fp = 0;
  16. if (($this->fp = fopen($filename, 'rb')) !== false) {
  17. $this->firstip = $this->getlong();
  18. $this->lastip = $this->getlong();
  19. $this->totalip = ($this->lastip - $this->firstip) / 7;
  20. register_shutdown_function(array(&$this, '__destruct'));
  21. }
  22. }
  23. public function __destruct()
  24. {
  25. if ($this->fp) {
  26. fclose($this->fp);
  27. }
  28. $this->fp = 0;
  29. }
  30. private function getlong()
  31. {
  32. $result = unpack('Vlong', fread($this->fp, 4));
  33. return $result['long'];
  34. }
  35. private function getlong3()
  36. {
  37. $result = unpack('Vlong', fread($this->fp, 3).chr(0));
  38. return $result['long'];
  39. }
  40. private function packip($ip)
  41. {
  42. return pack('N', intval(ip2long($ip)));
  43. }
  44. private function getstring($data = "")
  45. {
  46. $char = fread($this->fp, 1);
  47. while (ord($char) > 0) {
  48. $data .= $char;
  49. $char = fread($this->fp, 1);
  50. }
  51. return $data;
  52. }
  53. private function getarea()
  54. {
  55. $byte = fread($this->fp, 1);
  56. switch (ord($byte)) {
  57. case 0:
  58. $area = "";
  59. break;
  60. case 1:
  61. case 2:
  62. fseek($this->fp, $this->getlong3());
  63. $area = $this->getstring();
  64. break;
  65. default:
  66. $area = $this->getstring($byte);
  67. break;
  68. }
  69. return $area;
  70. }
  71. public function getlocation($ip)
  72. {
  73. if (!$this->fp) {
  74. return null;
  75. }
  76. $location['ip'] = gethostbyname($ip);
  77. $ip = $this->packip($location['ip']);
  78. $l = 0;
  79. $u = $this->totalip;
  80. $findip = $this->lastip;
  81. while ($l <= $u) {
  82. $i = floor(($l + $u) / 2);
  83. fseek($this->fp, $this->firstip + $i * 7);
  84. $beginip = strrev(fread($this->fp, 4));
  85. if ($ip < $beginip) {
  86. $u = $i - 1;
  87. } else {
  88. fseek($this->fp, $this->getlong3());
  89. $endip = strrev(fread($this->fp, 4));
  90. if ($ip > $endip) {
  91. $l = $i + 1;
  92. } else {
  93. $findip = $this->firstip + $i * 7;
  94. break;
  95. }
  96. }
  97. }
  98. fseek($this->fp, $findip);
  99. $location['beginip'] = long2ip($this->getlong());
  100. $offset = $this->getlong3();
  101. fseek($this->fp, $offset);
  102. $location['endip'] = long2ip($this->getlong());
  103. $byte = fread($this->fp, 1);
  104. switch (ord($byte)) {
  105. case 1:
  106. $countryOffset = $this->getlong3();
  107. fseek($this->fp, $countryOffset);
  108. $byte = fread($this->fp, 1);
  109. switch (ord($byte)) {
  110. case 2:
  111. fseek($this->fp, $this->getlong3());
  112. $location['country'] = $this->getstring();
  113. fseek($this->fp, $countryOffset + 4);
  114. $location['area'] = $this->getarea();
  115. break;
  116. default:
  117. $location['country'] = $this->getstring($byte);
  118. $location['area'] = $this->getarea();
  119. break;
  120. }
  121. break;
  122. case 2:
  123. fseek($this->fp, $this->getlong3());
  124. $location['country'] = $this->getstring();
  125. fseek($this->fp, $offset + 8);
  126. $location['area'] = $this->getarea();
  127. break;
  128. default:
  129. $location['country'] = $this->getstring($byte);
  130. $location['area'] = $this->getarea();
  131. break;
  132. }
  133. if ($location['country'] == " CZ88.NET") {
  134. $location['country'] = "未知";
  135. }
  136. if ($location['area'] == " CZ88.NET") {
  137. $location['area'] = "";
  138. }
  139. return $location;
  140. }
  141. }