IP.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <?php
  2. namespace Qii\Library;
  3. /**
  4. * Class ip
  5. *
  6. * @package Library
  7. */
  8. class IP
  9. {
  10. var $StartIP = 0;
  11. var $EndIP = 0;
  12. var $Country = '';
  13. var $Local = '';
  14. var $CountryFlag = 0; // 标识 Country位置
  15. // 0x01,随后3字节为Country偏移,没有Local
  16. // 0x02,随后3字节为Country偏移,接着是Local
  17. // 其他,Country,Local,Local有类似的压缩。可能多重引用。
  18. var $fp;
  19. var $FirstStartIp = 0;
  20. var $LastStartIp = 0;
  21. var $EndIpOff = 0;
  22. /**
  23. * 获取访问者的ip地址
  24. *
  25. * @return mixed
  26. */
  27. public function getIP()
  28. {
  29. if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
  30. $ip = $_SERVER['HTTP_CLIENT_IP'];
  31. } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  32. $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
  33. } else {
  34. $ip = $_SERVER['REMOTE_ADDR'];
  35. }
  36. return $ip;
  37. }
  38. public function getStartIp($RecNo)
  39. {
  40. $offset = $this->FirstStartIp + $RecNo * 7;
  41. @fseek($this->fp, $offset, SEEK_SET);
  42. $buf = fread($this->fp, 7);
  43. $this->EndIpOff = ord($buf[4]) + (ord($buf[5]) * 256) + (ord($buf[6]) * 256 * 256);
  44. $this->StartIp = ord($buf[0]) + (ord($buf[1]) * 256) + (ord($buf[2]) * 256 * 256) + (ord($buf[3]) * 256 * 256 * 256);
  45. return $this->StartIp;
  46. }
  47. public function getEndIp()
  48. {
  49. @fseek($this->fp, $this->EndIpOff, SEEK_SET);
  50. $buf = fread($this->fp, 5);
  51. $this->EndIp = ord($buf[0]) + (ord($buf[1]) * 256) + (ord($buf[2]) * 256 * 256) + (ord($buf[3]) * 256 * 256 * 256);
  52. $this->CountryFlag = ord($buf[4]);
  53. return $this->EndIp;
  54. }
  55. public function getCountry()
  56. {
  57. switch ($this->CountryFlag) {
  58. case 1:
  59. case 2:
  60. $this->Country = $this->getFlagStr($this->EndIpOff + 4);
  61. $this->Local = (1 == $this->CountryFlag) ? '' : $this->getFlagStr($this->EndIpOff + 8);
  62. break;
  63. default:
  64. $this->Country = $this->getFlagStr($this->EndIpOff + 4);
  65. $this->Local = $this->getFlagStr(ftell($this->fp));
  66. }
  67. }
  68. public function getFlagStr($offset)
  69. {
  70. $flag = 0;
  71. while (1) {
  72. @fseek($this->fp, $offset, SEEK_SET);
  73. $flag = ord(fgetc($this->fp));
  74. if ($flag == 1 || $flag == 2) {
  75. $buf = fread($this->fp, 3);
  76. if ($flag == 2) {
  77. $this->CountryFlag = 2;
  78. $this->EndIpOff = $offset - 4;
  79. }
  80. $offset = ord($buf[0]) + (ord($buf[1]) * 256) + (ord($buf[2]) * 256 * 256);
  81. } else
  82. break;
  83. }
  84. if ($offset < 12) return '';
  85. @fseek($this->fp, $offset, SEEK_SET);
  86. return $this->getStr();
  87. }
  88. public function getStr()
  89. {
  90. $str = '';
  91. while (1) {
  92. $c = fgetc($this->fp);
  93. if (ord($c[0]) == 0) break;
  94. $str .= $c;
  95. }
  96. return $str;
  97. }
  98. public function QQwry($dotip = '')
  99. {
  100. if (!$dotip) return;
  101. if (ereg("^(127)", $dotip)) {
  102. $this->Country = '本地网络';
  103. return;
  104. } else if (ereg("^(192)", $dotip)) {
  105. $this->Country = '局域网';
  106. return;
  107. }
  108. $ip = $this->IpToInt($dotip);
  109. $this->fp = fopen(__QQWRY__, "rb");
  110. if ($this->fp == NULL) {
  111. $szLocal = "OpenFileError";
  112. return 1;
  113. }
  114. @fseek($this->fp, 0, SEEK_SET);
  115. $buf = fread($this->fp, 8);
  116. $this->FirstStartIp = ord($buf[0]) + (ord($buf[1]) * 256) + (ord($buf[2]) * 256 * 256) + (ord($buf[3]) * 256 * 256 * 256);
  117. $this->LastStartIp = ord($buf[4]) + (ord($buf[5]) * 256) + (ord($buf[6]) * 256 * 256) + (ord($buf[7]) * 256 * 256 * 256);
  118. $RecordCount = floor(($this->LastStartIp - $this->FirstStartIp) / 7);
  119. if ($RecordCount <= 1) {
  120. $this->Country = "FileDataError";
  121. fclose($this->fp);
  122. return 2;
  123. }
  124. $RangB = 0;
  125. $RangE = $RecordCount;
  126. // Match ...
  127. while ($RangB < $RangE - 1) {
  128. $RecNo = floor(($RangB + $RangE) / 2);
  129. $this->getStartIp($RecNo);
  130. if ($ip == $this->StartIp) {
  131. $RangB = $RecNo;
  132. break;
  133. }
  134. if ($ip > $this->StartIp) $RangB = $RecNo;
  135. else $RangE = $RecNo;
  136. }
  137. $this->getStartIp($RangB);
  138. $this->getEndIp();
  139. if (($this->StartIp <= $ip) && ($this->EndIp >= $ip)) {
  140. $this->getCountry();
  141. } else {
  142. $this->Country = '未知';
  143. $this->Local = '';
  144. }
  145. fclose($this->fp);
  146. }
  147. public function IpToInt($Ip)
  148. {
  149. $array = explode('.', $Ip, 4);
  150. $Int = ($array[0] * 256 * 256 * 256) + ($array[1] * 256 * 256) + ($array[2] * 256) + $array[3];
  151. return $Int;
  152. }
  153. /**
  154. * 将ip转换成整形
  155. *
  156. * @param string $ip
  157. * @return string
  158. */
  159. public function ip2Long($ip = null)
  160. {
  161. if (!$ip) $ip = $this->getIP();
  162. return sprintf("%u", ip2long($ip));
  163. }
  164. /**
  165. * 将长整形的数转换成ip地址
  166. *
  167. * @param $longIP
  168. * @return string
  169. */
  170. public function long2Ip($longIP)
  171. {
  172. if(!$longIP || intval($longIP) == 0) return 'Unknow';
  173. $ip1 = ($longIP >> 24) & 0xff; // 跟0xff做与运算的目的是取低8位
  174. $ip2 = ($longIP >> 16) & 0xff;
  175. $ip3 = ($longIP >> 8) & 0xff;
  176. $ip4 = $longIP & 0xff;
  177. return $ip1 . '.' . $ip2 . '.' . $ip3 . '.' . $ip4;
  178. }
  179. }