|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00036 require_once 'PEAR/Exception.php'; 00037 00136 class Net_GeoIP 00137 { 00141 const ERR_INVALID_IP = 218624992; // crc32('Net_GeoIP::ERR_INVALID_IP') 00142 00146 const ERR_DB_FORMAT = 866184008; // crc32('Net_GeoIP::ERR_DB_FORMAT') 00147 00148 public static $COUNTRY_CODES = array( 00149 "", "AP", "EU", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", 00150 "AR", "AS", "AT", "AU", "AW", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", 00151 "BI", "BJ", "BM", "BN", "BO", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", 00152 "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU", 00153 "CV", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", 00154 "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "FX", "GA", "GB", 00155 "GD", "GE", "GF", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", 00156 "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IN", 00157 "IO", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", 00158 "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", 00159 "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "MH", "MK", "ML", "MM", "MN", 00160 "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", 00161 "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", 00162 "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", 00163 "QA", "RE", "RO", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", 00164 "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TC", "TD", 00165 "TF", "TG", "TH", "TJ", "TK", "TM", "TN", "TO", "TL", "TR", "TT", "TV", "TW", 00166 "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", 00167 "VU", "WF", "WS", "YE", "YT", "RS", "ZA", "ZM", "ME", "ZW", "A1", "A2", "O1", 00168 "AX", "GG", "IM", "JE", "BL", "MF" 00169 ); 00170 00171 public static $COUNTRY_CODES3 = array( 00172 "","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","ANT","AGO","AQ","ARG", 00173 "ASM","AUT","AUS","ABW","AZE","BIH","BRB","BGD","BEL","BFA","BGR","BHR","BDI", 00174 "BEN","BMU","BRN","BOL","BRA","BHS","BTN","BV","BWA","BLR","BLZ","CAN","CC", 00175 "COD","CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI","CUB","CPV", 00176 "CX","CYP","CZE","DEU","DJI","DNK","DMA","DOM","DZA","ECU","EST","EGY","ESH", 00177 "ERI","ESP","ETH","FIN","FJI","FLK","FSM","FRO","FRA","FX","GAB","GBR","GRD", 00178 "GEO","GUF","GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","GS","GTM","GUM", 00179 "GNB","GUY","HKG","HM","HND","HRV","HTI","HUN","IDN","IRL","ISR","IND","IO", 00180 "IRQ","IRN","ISL","ITA","JAM","JOR","JPN","KEN","KGZ","KHM","KIR","COM","KNA", 00181 "PRK","KOR","KWT","CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU", 00182 "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI","MMR","MNG","MAC", 00183 "MNP","MTQ","MRT","MSR","MLT","MUS","MDV","MWI","MEX","MYS","MOZ","NAM","NCL", 00184 "NER","NFK","NGA","NIC","NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER", 00185 "PYF","PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW","PRY","QAT", 00186 "REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN","SWE","SGP","SHN","SVN","SJM", 00187 "SVK","SLE","SMR","SEN","SOM","SUR","STP","SLV","SYR","SWZ","TCA","TCD","TF", 00188 "TGO","THA","TJK","TKL","TLS","TKM","TUN","TON","TUR","TTO","TUV","TWN","TZA", 00189 "UKR","UGA","UM","USA","URY","UZB","VAT","VCT","VEN","VGB","VIR","VNM","VUT", 00190 "WLF","WSM","YEM","YT","SRB","ZAF","ZMB","MNE","ZWE","A1","A2","O1", 00191 "ALA","GGY","IMN","JEY","BLM","MAF" 00192 ); 00193 00194 public static $COUNTRY_NAMES = array( 00195 "", "Asia/Pacific Region", "Europe", "Andorra", "United Arab Emirates", 00196 "Afghanistan", "Antigua and Barbuda", "Anguilla", "Albania", "Armenia", 00197 "Netherlands Antilles", "Angola", "Antarctica", "Argentina", "American Samoa", 00198 "Austria", "Australia", "Aruba", "Azerbaijan", "Bosnia and Herzegovina", 00199 "Barbados", "Bangladesh", "Belgium", "Burkina Faso", "Bulgaria", "Bahrain", 00200 "Burundi", "Benin", "Bermuda", "Brunei Darussalam", "Bolivia", "Brazil", 00201 "Bahamas", "Bhutan", "Bouvet Island", "Botswana", "Belarus", "Belize", 00202 "Canada", "Cocos (Keeling) Islands", "Congo, The Democratic Republic of the", 00203 "Central African Republic", "Congo", "Switzerland", "Cote D'Ivoire", "Cook Islands", 00204 "Chile", "Cameroon", "China", "Colombia", "Costa Rica", "Cuba", "Cape Verde", 00205 "Christmas Island", "Cyprus", "Czech Republic", "Germany", "Djibouti", 00206 "Denmark", "Dominica", "Dominican Republic", "Algeria", "Ecuador", "Estonia", 00207 "Egypt", "Western Sahara", "Eritrea", "Spain", "Ethiopia", "Finland", "Fiji", 00208 "Falkland Islands (Malvinas)", "Micronesia, Federated States of", "Faroe Islands", 00209 "France", "France, Metropolitan", "Gabon", "United Kingdom", 00210 "Grenada", "Georgia", "French Guiana", "Ghana", "Gibraltar", "Greenland", 00211 "Gambia", "Guinea", "Guadeloupe", "Equatorial Guinea", "Greece", "South Georgia and the South Sandwich Islands", 00212 "Guatemala", "Guam", "Guinea-Bissau", 00213 "Guyana", "Hong Kong", "Heard Island and McDonald Islands", "Honduras", 00214 "Croatia", "Haiti", "Hungary", "Indonesia", "Ireland", "Israel", "India", 00215 "British Indian Ocean Territory", "Iraq", "Iran, Islamic Republic of", 00216 "Iceland", "Italy", "Jamaica", "Jordan", "Japan", "Kenya", "Kyrgyzstan", 00217 "Cambodia", "Kiribati", "Comoros", "Saint Kitts and Nevis", "Korea, Democratic People's Republic of", 00218 "Korea, Republic of", "Kuwait", "Cayman Islands", 00219 "Kazakstan", "Lao People's Democratic Republic", "Lebanon", "Saint Lucia", 00220 "Liechtenstein", "Sri Lanka", "Liberia", "Lesotho", "Lithuania", "Luxembourg", 00221 "Latvia", "Libyan Arab Jamahiriya", "Morocco", "Monaco", "Moldova, Republic of", 00222 "Madagascar", "Marshall Islands", "Macedonia", 00223 "Mali", "Myanmar", "Mongolia", "Macau", "Northern Mariana Islands", 00224 "Martinique", "Mauritania", "Montserrat", "Malta", "Mauritius", "Maldives", 00225 "Malawi", "Mexico", "Malaysia", "Mozambique", "Namibia", "New Caledonia", 00226 "Niger", "Norfolk Island", "Nigeria", "Nicaragua", "Netherlands", "Norway", 00227 "Nepal", "Nauru", "Niue", "New Zealand", "Oman", "Panama", "Peru", "French Polynesia", 00228 "Papua New Guinea", "Philippines", "Pakistan", "Poland", "Saint Pierre and Miquelon", 00229 "Pitcairn Islands", "Puerto Rico", "Palestinian Territory", 00230 "Portugal", "Palau", "Paraguay", "Qatar", "Reunion", "Romania", 00231 "Russian Federation", "Rwanda", "Saudi Arabia", "Solomon Islands", 00232 "Seychelles", "Sudan", "Sweden", "Singapore", "Saint Helena", "Slovenia", 00233 "Svalbard and Jan Mayen", "Slovakia", "Sierra Leone", "San Marino", "Senegal", 00234 "Somalia", "Suriname", "Sao Tome and Principe", "El Salvador", "Syrian Arab Republic", 00235 "Swaziland", "Turks and Caicos Islands", "Chad", "French Southern Territories", 00236 "Togo", "Thailand", "Tajikistan", "Tokelau", "Turkmenistan", 00237 "Tunisia", "Tonga", "Timor-Leste", "Turkey", "Trinidad and Tobago", "Tuvalu", 00238 "Taiwan", "Tanzania, United Republic of", "Ukraine", 00239 "Uganda", "United States Minor Outlying Islands", "United States", "Uruguay", 00240 "Uzbekistan", "Holy See (Vatican City State)", "Saint Vincent and the Grenadines", 00241 "Venezuela", "Virgin Islands, British", "Virgin Islands, U.S.", 00242 "Vietnam", "Vanuatu", "Wallis and Futuna", "Samoa", "Yemen", "Mayotte", 00243 "Serbia", "South Africa", "Zambia", "Montenegro", "Zimbabwe", 00244 "Anonymous Proxy","Satellite Provider","Other", 00245 "Aland Islands","Guernsey","Isle of Man","Jersey","Saint Barthelemy","Saint Martin" 00246 ); 00247 00248 // storage / caching flags 00249 const STANDARD = 0; 00250 const MEMORY_CACHE = 1; 00251 const SHARED_MEMORY = 2; 00252 00253 // Database structure constants 00254 const COUNTRY_BEGIN = 16776960; 00255 const STATE_BEGIN_REV0 = 16700000; 00256 const STATE_BEGIN_REV1 = 16000000; 00257 00258 const STRUCTURE_INFO_MAX_SIZE = 20; 00259 const DATABASE_INFO_MAX_SIZE = 100; 00260 const COUNTRY_EDITION = 106; 00261 const REGION_EDITION_REV0 = 112; 00262 const REGION_EDITION_REV1 = 3; 00263 const CITY_EDITION_REV0 = 111; 00264 const CITY_EDITION_REV1 = 2; 00265 const ORG_EDITION = 110; 00266 const SEGMENT_RECORD_LENGTH = 3; 00267 const STANDARD_RECORD_LENGTH = 3; 00268 const ORG_RECORD_LENGTH = 4; 00269 const MAX_RECORD_LENGTH = 4; 00270 const MAX_ORG_RECORD_LENGTH = 300; 00271 const FULL_RECORD_LENGTH = 50; 00272 00273 const US_OFFSET = 1; 00274 const CANADA_OFFSET = 677; 00275 const WORLD_OFFSET = 1353; 00276 const FIPS_RANGE = 360; 00277 00278 // SHMOP memory address 00279 const SHM_KEY = 0x4f415401; 00280 00284 private $flags = 0; 00285 00289 private $filehandle; 00290 00294 private $memoryBuffer; 00295 00299 private $databaseType; 00300 00304 private $databaseSegments; 00305 00309 private $recordLength; 00310 00315 private $shmid; 00316 00321 private static $instances = array(); 00322 00333 public function __construct($filename = null, $flags = null) 00334 { 00335 if ($filename !== null) { 00336 $this->open($filename, $flags); 00337 } 00338 // store the instance, so that it will be returned by a call to 00339 // getInstance() (with the same db filename). 00340 self::$instances[$filename] = $this; 00341 } 00342 00392 public static function getInstance($filename = null, $flags = null) 00393 { 00394 if (!isset(self::$instances[$filename])) { 00395 self::$instances[$filename] = new Net_GeoIP($filename, $flags); 00396 } 00397 return self::$instances[$filename]; 00398 } 00399 00410 public function open($filename, $flags = null) 00411 { 00412 if ($flags !== null) { 00413 $this->flags = $flags; 00414 } 00415 if ($this->flags & self::SHARED_MEMORY) { 00416 $this->shmid = @shmop_open(self::SHM_KEY, "a", 0, 0); 00417 if ($this->shmid === false) { 00418 $this->loadSharedMemory($filename); 00419 $this->shmid = @shmop_open(self::SHM_KEY, "a", 0, 0); 00420 if ($this->shmid === false) { // should never be false as loadSharedMemory() will throw Exc if cannot create 00421 throw new PEAR_Exception("Unable to open shared memory at key: " . dechex(self::SHM_KEY)); 00422 } 00423 } 00424 } else { 00425 $this->filehandle = fopen($filename, "rb"); 00426 if (!$this->filehandle) { 00427 throw new PEAR_Exception("Unable to open file: $filename"); 00428 } 00429 if ($this->flags & self::MEMORY_CACHE) { 00430 $s_array = fstat($this->filehandle); 00431 $this->memoryBuffer = fread($this->filehandle, $s_array['size']); 00432 } 00433 } 00434 $this->setupSegments(); 00435 } 00436 00446 protected function loadSharedMemory($filename) 00447 { 00448 $fp = fopen($filename, "rb"); 00449 if (!$fp) { 00450 throw new PEAR_Exception("Unable to open file: $filename"); 00451 } 00452 $s_array = fstat($fp); 00453 $size = $s_array['size']; 00454 00455 if ($shmid = @shmop_open(self::SHM_KEY, "w", 0, 0)) { 00456 shmop_delete($shmid); 00457 shmop_close($shmid); 00458 } 00459 00460 if ($shmid = @shmop_open(self::SHM_KEY, "c", 0644, $size)) { 00461 $offset = 0; 00462 while ($offset < $size) { 00463 $buf = fread($fp, 524288); 00464 shmop_write($shmid, $buf, $offset); 00465 $offset += 524288; 00466 } 00467 shmop_close($shmid); 00468 } 00469 00470 fclose($fp); 00471 } 00472 00479 protected function setupSegments() 00480 { 00481 00482 $this->databaseType = self::COUNTRY_EDITION; 00483 $this->recordLength = self::STANDARD_RECORD_LENGTH; 00484 00485 if ($this->flags & self::SHARED_MEMORY) { 00486 00487 $offset = shmop_size($this->shmid) - 3; 00488 for ($i = 0; $i < self::STRUCTURE_INFO_MAX_SIZE; $i++) { 00489 $delim = shmop_read($this->shmid, $offset, 3); 00490 $offset += 3; 00491 if ($delim == (chr(255).chr(255).chr(255))) { 00492 $this->databaseType = ord(shmop_read($this->shmid, $offset, 1)); 00493 $offset++; 00494 if ($this->databaseType === self::REGION_EDITION_REV0) { 00495 $this->databaseSegments = self::STATE_BEGIN_REV0; 00496 } elseif ($this->databaseType === self::REGION_EDITION_REV1) { 00497 $this->databaseSegments = self::STATE_BEGIN_REV1; 00498 } elseif (($this->databaseType === self::CITY_EDITION_REV0) 00499 || ($this->databaseType === self::CITY_EDITION_REV1) 00500 || ($this->databaseType === self::ORG_EDITION)) { 00501 $this->databaseSegments = 0; 00502 $buf = shmop_read($this->shmid, $offset, self::SEGMENT_RECORD_LENGTH); 00503 for ($j = 0; $j < self::SEGMENT_RECORD_LENGTH; $j++) { 00504 $this->databaseSegments += (ord($buf[$j]) << ($j * 8)); 00505 } 00506 if ($this->databaseType === self::ORG_EDITION) { 00507 $this->recordLength = self::ORG_RECORD_LENGTH; 00508 } 00509 } 00510 break; 00511 } else { 00512 $offset -= 4; 00513 } 00514 } 00515 if ($this->databaseType == self::COUNTRY_EDITION) { 00516 $this->databaseSegments = self::COUNTRY_BEGIN; 00517 } 00518 00519 } else { 00520 00521 $filepos = ftell($this->filehandle); 00522 fseek($this->filehandle, -3, SEEK_END); 00523 for ($i = 0; $i < self::STRUCTURE_INFO_MAX_SIZE; $i++) { 00524 $delim = fread($this->filehandle, 3); 00525 if ($delim == (chr(255).chr(255).chr(255))) { 00526 $this->databaseType = ord(fread($this->filehandle, 1)); 00527 if ($this->databaseType === self::REGION_EDITION_REV0) { 00528 $this->databaseSegments = self::STATE_BEGIN_REV0; 00529 } elseif ($this->databaseType === self::REGION_EDITION_REV1) { 00530 $this->databaseSegments = self::STATE_BEGIN_REV1; 00531 } elseif ($this->databaseType === self::CITY_EDITION_REV0 00532 || $this->databaseType === self::CITY_EDITION_REV1 00533 || $this->databaseType === self::ORG_EDITION) { 00534 $this->databaseSegments = 0; 00535 $buf = fread($this->filehandle, self::SEGMENT_RECORD_LENGTH); 00536 for ($j = 0; $j < self::SEGMENT_RECORD_LENGTH; $j++) { 00537 $this->databaseSegments += (ord($buf[$j]) << ($j * 8)); 00538 } 00539 if ($this->databaseType === self::ORG_EDITION) { 00540 $this->recordLength = self::ORG_RECORD_LENGTH; 00541 } 00542 } 00543 break; 00544 } else { 00545 fseek($this->filehandle, -4, SEEK_CUR); 00546 } 00547 } 00548 if ($this->databaseType === self::COUNTRY_EDITION) { 00549 $this->databaseSegments = self::COUNTRY_BEGIN; 00550 } 00551 fseek($this->filehandle, $filepos, SEEK_SET); 00552 00553 } 00554 } 00555 00561 public function close() 00562 { 00563 if ($this->flags & self::SHARED_MEMORY) { 00564 return shmop_close($this->shmid); 00565 } else { 00566 // right now even if file was cached in RAM the file was not closed 00567 // so it's safe to expect no error w/ fclose() 00568 return fclose($this->filehandle); 00569 } 00570 } 00571 00586 protected function lookupCountryId($addr) 00587 { 00588 $ipnum = ip2long($addr); 00589 if ($ipnum === false) { 00590 throw new PEAR_Exception("Invalid IP address: " . var_export($addr, true), self::ERR_INVALID_IP); 00591 } 00592 if ($this->databaseType !== self::COUNTRY_EDITION) { 00593 throw new PEAR_Exception("Invalid database type; lookupCountry*() methods expect Country database."); 00594 } 00595 return $this->seekCountry($ipnum) - self::COUNTRY_BEGIN; 00596 } 00597 00609 public function lookupCountryCode($addr) 00610 { 00611 return self::$COUNTRY_CODES[$this->lookupCountryId($addr)]; 00612 } 00613 00624 public function lookupCountryName($addr) 00625 { 00626 return self::$COUNTRY_NAMES[$this->lookupCountryId($addr)]; 00627 } 00628 00638 protected function seekCountry($ipnum) 00639 { 00640 $offset = 0; 00641 for ($depth = 31; $depth >= 0; --$depth) { 00642 if ($this->flags & self::MEMORY_CACHE) { 00643 $buf = substr($this->memoryBuffer, 2 * $this->recordLength * $offset, 2 * $this->recordLength); 00644 } elseif ($this->flags & self::SHARED_MEMORY) { 00645 $buf = shmop_read($this->shmid, 2 * $this->recordLength * $offset, 2 * $this->recordLength); 00646 } else { 00647 if (fseek($this->filehandle, 2 * $this->recordLength * $offset, SEEK_SET) !== 0) { 00648 throw new PEAR_Exception("fseek failed"); 00649 } 00650 $buf = fread($this->filehandle, 2 * $this->recordLength); 00651 } 00652 $x = array(0,0); 00653 for ($i = 0; $i < 2; ++$i) { 00654 for ($j = 0; $j < $this->recordLength; ++$j) { 00655 $x[$i] += ord($buf[$this->recordLength * $i + $j]) << ($j * 8); 00656 } 00657 } 00658 if ($ipnum & (1 << $depth)) { 00659 if ($x[1] >= $this->databaseSegments) { 00660 return $x[1]; 00661 } 00662 $offset = $x[1]; 00663 } else { 00664 if ($x[0] >= $this->databaseSegments) { 00665 return $x[0]; 00666 } 00667 $offset = $x[0]; 00668 } 00669 } 00670 throw new PEAR_Exception("Error traversing database - perhaps it is corrupt?"); 00671 } 00672 00684 public function lookupOrg($addr) 00685 { 00686 $ipnum = ip2long($addr); 00687 if ($ipnum === false) { 00688 throw new PEAR_Exception("Invalid IP address: " . var_export($addr, true), self::ERR_INVALID_IP); 00689 } 00690 if ($this->databaseType !== self::ORG_EDITION) { 00691 throw new PEAR_Exception("Invalid database type; lookupOrg() method expects Org/ISP database.", self::ERR_DB_FORMAT); 00692 } 00693 return $this->getOrg($ipnum); 00694 } 00695 00706 public function lookupRegion($addr) 00707 { 00708 $ipnum = ip2long($addr); 00709 if ($ipnum === false) { 00710 throw new PEAR_Exception("Invalid IP address: " . var_export($addr, true), self::ERR_INVALID_IP); 00711 } 00712 if ($this->databaseType !== self::REGION_EDITION_REV0 && $this->databaseType !== self::REGION_EDITION_REV1) { 00713 throw new PEAR_Exception("Invalid database type; lookupRegion() method expects Region database.", self::ERR_DB_FORMAT); 00714 } 00715 return $this->getRegion($ipnum); 00716 } 00717 00728 public function lookupLocation($addr) 00729 { 00730 include_once 'Net/GeoIP/Location.php'; 00731 $ipnum = ip2long($addr); 00732 if ($ipnum === false) { 00733 throw new PEAR_Exception("Invalid IP address: " . var_export($addr, true), self::ERR_INVALID_IP); 00734 } 00735 if ($this->databaseType !== self::CITY_EDITION_REV0 && $this->databaseType !== self::CITY_EDITION_REV1) { 00736 throw new PEAR_Exception("Invalid database type; lookupLocation() method expects City database."); 00737 } 00738 return $this->getRecord($ipnum); 00739 } 00740 00748 protected function getOrg($ipnum) 00749 { 00750 $seek_org = $this->seekCountry($ipnum); 00751 if ($seek_org == $this->databaseSegments) { 00752 return null; 00753 } 00754 $record_pointer = $seek_org + (2 * $this->recordLength - 1) * $this->databaseSegments; 00755 if ($this->flags & self::SHARED_MEMORY) { 00756 $org_buf = shmop_read($this->shmid, $record_pointer, self::MAX_ORG_RECORD_LENGTH); 00757 } else { 00758 fseek($this->filehandle, $record_pointer, SEEK_SET); 00759 $org_buf = fread($this->filehandle, self::MAX_ORG_RECORD_LENGTH); 00760 } 00761 $org_buf = substr($org_buf, 0, strpos($org_buf, 0)); 00762 return $org_buf; 00763 } 00764 00772 protected function getRegion($ipnum) 00773 { 00774 if ($this->databaseType == self::REGION_EDITION_REV0) { 00775 $seek_region = $this->seekCountry($ipnum) - self::STATE_BEGIN_REV0; 00776 if ($seek_region >= 1000) { 00777 $country_code = "US"; 00778 $region = chr(($seek_region - 1000)/26 + 65) . chr(($seek_region - 1000)%26 + 65); 00779 } else { 00780 $country_code = self::$COUNTRY_CODES[$seek_region]; 00781 $region = ""; 00782 } 00783 return array($country_code, $region); 00784 } elseif ($this->databaseType == self::REGION_EDITION_REV1) { 00785 $seek_region = $this->seekCountry($ipnum) - self::STATE_BEGIN_REV1; 00786 //print $seek_region; 00787 if ($seek_region < self::US_OFFSET) { 00788 $country_code = ""; 00789 $region = ""; 00790 } elseif ($seek_region < self::CANADA_OFFSET) { 00791 $country_code = "US"; 00792 $region = chr(($seek_region - self::US_OFFSET)/26 + 65) . chr(($seek_region - self::US_OFFSET)%26 + 65); 00793 } elseif ($seek_region < self::WORLD_OFFSET) { 00794 $country_code = "CA"; 00795 $region = chr(($seek_region - self::CANADA_OFFSET)/26 + 65) . chr(($seek_region - self::CANADA_OFFSET)%26 + 65); 00796 } else { 00797 $country_code = self::$COUNTRY_CODES[($seek_region - self::WORLD_OFFSET) / self::FIPS_RANGE]; 00798 $region = ""; 00799 } 00800 return array ($country_code,$region); 00801 } 00802 } 00803 00812 protected function getRecord($ipnum) 00813 { 00814 $seek_country = $this->seekCountry($ipnum); 00815 if ($seek_country == $this->databaseSegments) { 00816 return null; 00817 } 00818 00819 $record_pointer = $seek_country + (2 * $this->recordLength - 1) * $this->databaseSegments; 00820 00821 if ($this->flags & self::SHARED_MEMORY) { 00822 $record_buf = shmop_read($this->shmid, $record_pointer, self::FULL_RECORD_LENGTH); 00823 } else { 00824 fseek($this->filehandle, $record_pointer, SEEK_SET); 00825 $record_buf = fread($this->filehandle, self::FULL_RECORD_LENGTH); 00826 } 00827 00828 $record = new Net_GeoIP_Location(); 00829 00830 $record_buf_pos = 0; 00831 $char = ord(substr($record_buf, $record_buf_pos, 1)); 00832 00833 $record->countryCode = self::$COUNTRY_CODES[$char]; 00834 $record->countryCode3 = self::$COUNTRY_CODES3[$char]; 00835 $record->countryName = self::$COUNTRY_NAMES[$char]; 00836 $record_buf_pos++; 00837 $str_length = 0; 00838 00839 //get region 00840 $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1)); 00841 while ($char != 0) { 00842 $str_length++; 00843 $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1)); 00844 } 00845 if ($str_length > 0) { 00846 $record->region = substr($record_buf, $record_buf_pos, $str_length); 00847 } 00848 $record_buf_pos += $str_length + 1; 00849 $str_length = 0; 00850 00851 //get city 00852 $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1)); 00853 while ($char != 0) { 00854 $str_length++; 00855 $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1)); 00856 } 00857 if ($str_length > 0) { 00858 $record->city = substr($record_buf, $record_buf_pos, $str_length); 00859 } 00860 $record_buf_pos += $str_length + 1; 00861 $str_length = 0; 00862 00863 //get postal code 00864 $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1)); 00865 while ($char != 0) { 00866 $str_length++; 00867 $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1)); 00868 } 00869 if ($str_length > 0) { 00870 $record->postalCode = substr($record_buf, $record_buf_pos, $str_length); 00871 } 00872 $record_buf_pos += $str_length + 1; 00873 $str_length = 0; 00874 $latitude = 0; 00875 $longitude = 0; 00876 for ($j = 0;$j < 3; ++$j) { 00877 $char = ord(substr($record_buf, $record_buf_pos++, 1)); 00878 $latitude += ($char << ($j * 8)); 00879 } 00880 $record->latitude = ($latitude/10000) - 180; 00881 00882 for ($j = 0;$j < 3; ++$j) { 00883 $char = ord(substr($record_buf, $record_buf_pos++, 1)); 00884 $longitude += ($char << ($j * 8)); 00885 } 00886 $record->longitude = ($longitude/10000) - 180; 00887 00888 if ($this->databaseType === self::CITY_EDITION_REV1) { 00889 $dmaarea_combo = 0; 00890 if ($record->countryCode == "US") { 00891 for ($j = 0;$j < 3;++$j) { 00892 $char = ord(substr($record_buf, $record_buf_pos++, 1)); 00893 $dmaarea_combo += ($char << ($j * 8)); 00894 } 00895 $record->dmaCode = floor($dmaarea_combo/1000); 00896 $record->areaCode = $dmaarea_combo%1000; 00897 } 00898 } 00899 00900 return $record; 00901 } 00902 00903 } 00904