Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/pear/Net/GeoIP.php
Go to the documentation of this file.
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 
 All Data Structures Namespaces Files Functions Variables Enumerations