Import/Core_geoip.php
[Pman.Core] / Import / Core_geoip.php
1 <?php
2
3 require_once 'Pman/Roo.php';
4
5 class Pman_Core_Import_Core_geoip extends Pman_Roo
6 {
7     static $cli_desc = "Insert the geoip database";
8     
9     static $cli_opts = array();
10     
11     var $id_mapping = array();
12
13     function getAuth()
14     {
15         $ff = HTML_FlexyFramework::get();
16         if (!$ff->cli) {
17             die("access denied");
18         }
19         HTML_FlexyFramework::ensureSingle(__FILE__, $this);
20         return true;
21     }
22     
23     function post()
24     {
25         $this->get();
26     }
27     
28     function get()
29     {
30         
31         PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($this, 'onPearError'));
32         
33         $location = '/tmp/GeoLite2-City-Locations.csv';
34         $block = '/tmp/GeoLite2-City-Blocks.csv';
35         
36         if(!file_exists($location) || !file_exists($block)){
37             $this->jerr('GeoLite2-City-Locations.csv OR GeoLite2-City-Blocks.csv does not exists?!');
38         }
39         
40         $this->log("Insert location data start");
41         
42         $this->insertLocation($location);
43         
44         $this->log("Insert Block data start");
45         
46         $this->insertBlock($block);
47         
48         $this->jok("DONE");
49     }
50     
51     function insertLocation($csv)
52     {
53         ini_set("auto_detect_line_endings", true);
54         
55         $linecount = count(file($csv));
56         
57         $fh = fopen($csv, 'r');
58         
59         if (!$fh) {
60             $this->jerr("invalid location file");
61         }
62         
63         $req = array(
64             'GEONAME_ID', 'CONTINENT_CODE', 'CONTINENT_NAME',
65             'COUNTRY_ISO_CODE', 'COUNTRY_NAME', 'SUBDIVISION_ISO_CODE',
66             'SUBDIVISION_NAME', 'CITY_NAME', 'METRO_CODE',
67             'TIME_ZONE'
68         );
69         
70         $cols = false;
71         
72         while(false !== ($n = fgetcsv($fh,10000, ',', '"'))) {
73             if(!array_filter($n)){ // empty row
74                 continue;
75             }
76             
77             if (!$cols) {
78                 $cols = array();
79                 foreach($n as $k) {
80                     $cols[] = strtoupper(trim($k));
81                 }
82                 
83                 if (empty($cols)) {
84                     continue;
85                 }
86                 foreach($req as $r) {
87                     if (!in_array($r,$cols)) {
88                         $cols = false;
89                         break;
90                     }
91                 }
92                 continue;
93             }
94             
95             $row = array();
96             
97             foreach($cols as $i=>$k) {
98                 $row[$k] = trim($n[$i]);
99             }
100             
101             $this->processLocation($row);
102         }
103         
104     }
105     
106     function insertBlock($csv)
107     {
108         ini_set("auto_detect_line_endings", true);
109         
110         $fh = fopen($csv, 'r');
111         if (!$fh) {
112             $this->jerr("invalid location file");
113         }
114         
115         $req = array(
116             'NETWORK_START_IP', 'NETWORK_MASK_LENGTH', 'GEONAME_ID',
117             'REGISTERED_COUNTRY_GEONAME_ID', 'REPRESENTED_COUNTRY_GEONAME_ID', 'POSTAL_CODE',
118             'LATITUDE', 'LONGITUDE', 'IS_ANONYMOUS_PROXY',
119             'IS_SATELLITE_PROVIDER'
120         );
121         
122         $cols = false;
123         
124         while(false !== ($n = fgetcsv($fh,10000, ',', '"'))) {
125             if(!array_filter($n)){ // empty row
126                 continue;
127             }
128             
129             if (!$cols) {
130                 $cols = array();
131                 foreach($n as $k) {
132                     $cols[] = strtoupper(trim($k));
133                 }
134                 
135                 if (empty($cols)) {
136                     continue;
137                 }
138                 foreach($req as $r) {
139                     if (!in_array($r,$cols)) {
140                         $cols = false;
141                         break;
142                     }
143                 }
144                 continue;
145             }
146             
147             $row = array();
148             
149             foreach($cols as $i=>$k) {
150                 $row[$k] = trim($n[$i]);
151             }
152             
153             $this->processBlock($row);
154         }
155         
156     }
157     
158     
159     
160     function processLocation($row)
161     {   
162         $continent = $this->processContinent($row['CONTINENT_CODE'], $row['CONTINENT_NAME']);
163         
164         $country = $this->processCountry($row['COUNTRY_ISO_CODE'], $row['COUNTRY_NAME'], $continent);
165         
166         $division = $this->processDivision($row['SUBDIVISION_ISO_CODE'], $row['SUBDIVISION_NAME']);
167         
168         $city = $this->processCity($row['CITY_NAME'], $row['METRO_CODE'], $row['TIME_ZONE'], $country, $division);
169         
170         if(!empty($city) && !empty($city->id)){
171             $this->id_mapping[$row['GEONAME_ID']] = $city->id;
172         }
173     }
174     
175     function processContinent($code, $name)
176     {
177         if(empty($code)){
178             return false;
179         }
180         
181         $continent = DB_DataObject::factory('core_geoip_continent');
182         if(!$continent->get('code', $code)){
183             $continent->setFrom(array(
184                 'code' => $code,
185                 'name' => (!empty($name)) ? $name : $code
186             ));
187
188             $continent->insert();
189         }
190         
191         return $continent;
192     }
193     
194     function processCountry($code, $name, $continent)
195     {
196         if(empty($code)){
197             return false;
198         }
199         
200         $country = DB_DataObject::factory('core_geoip_country');
201         if(!$country->get('code', $code)){
202             $country->setFrom(array(
203                 'code' => $code,
204                 'name' => (!empty($name)) ? $name : $code,
205                 'continent_id' => (!empty($continent) && !empty($continent->id)) ? $continent->id : 0
206             ));
207
208             $country->insert();
209         }
210         
211         return $country;
212     }
213     
214     function processDivision($code, $name)
215     {
216         if(empty($code)){
217             return false;
218         }
219         
220         $division = DB_DataObject::factory('core_geoip_division');
221         if(!$division->get('code', $code)){
222             $division->setFrom(array(
223                 'code' => $code,
224                 'name' => (!empty($name)) ? $name : $code
225             ));
226
227             $division->insert();
228         }
229         
230         return $division;
231     }
232     
233     function processCity($name, $metro_code, $time_zone, $country, $division)
234     {
235         if(empty($name)){
236             return false;
237         }
238         
239         $city = DB_DataObject::factory('core_geoip_city');
240         
241         if($city->get('name', $name)){
242             return $city;
243         }
244         
245         $city->setFrom(array(
246             'name' => $name,
247             'metro_code' => $metro_code,
248             'time_zone' => $time_zone,
249             'country_id' => (!empty($country) && !empty($country->id)) ? $country->id : 0,
250             'division_id' => (!empty($division) && !empty($division->id)) ? $division->id : 0
251         ));
252         
253         $city->insert();
254         
255         return $city;
256         
257     }
258     
259     function processBlock($row)
260     {
261         if(empty($this->id_mapping[$row['GEONAME_ID']])){
262             $this->log("Missing mapping for {$row['GEONAME_ID']}");
263             $this->log("IP : {$row['NETWORK_START_IP']}");
264             return;
265         }
266         
267         $network_mapping = DB_DataObject::factory('core_geoip_network_mapping');
268         
269         $start_ip = array_pop(explode(":", $row['NETWORK_START_IP']));
270         
271         $network_mapping->setFrom(array(
272             'start_ip' => $start_ip,
273             'mask_length' => pow(2, (128 - $row['NETWORK_MASK_LENGTH'])),
274             'city_id' => $this->id_mapping[$row['GEONAME_ID']]
275         ));
276         
277         if(!$network_mapping->find(true)){
278             $network_mapping->insert();
279         }
280         
281         $location = DB_DataObject::factory('core_geoip_location');
282         if(!$location->get('city_id', $network_mapping->city_id)){
283             $location->setFrom(array(
284                 'latitude' => $row['LATITUDE'],
285                 'longitude' => $row['LONGITUDE'],
286                 'city_id' => $network_mapping->city_id
287             ));
288         }
289         
290         
291         if(!empty($row['POSTAL_CODE'])){
292             $city = DB_DataObject::factory('core_geoip_city');
293             if($city->get($network_mapping->city_id)){
294                 return;
295             }
296
297             $oc = clone($city);
298             $city->postal_code = $row['POSTAL_CODE'];
299             
300             $city->update($oc);
301         }
302         
303     }
304     
305     function log($str)
306     {
307         echo "$str \n";
308     }
309 }