13use Psr\Log\LoggerInterface;
29 protected $timeout = 60;
36 protected $api_url =
'http://api.udger.com/v3';
81 protected $cacheEnable =
true;
86 protected $cache = array();
91 protected $cacheSize = 3000;
99 $this->logger = $logger;
100 $this->ipHelper = $ipHelper;
110 $this->logger->debug(
"account: start");
112 if (empty($this->access_key)) {
113 throw new \Exception(
"access key not set");
116 $accountUrl = sprintf(
"%s/%s", $this->api_url,
"account");
117 $client = new \GuzzleHttp\Client();
119 $result = $client->post($accountUrl, array(
120 'multipart' => array(
122 'name' =>
'accesskey',
123 'contents' => $this->access_key
126 'timeout' => $this->timeout
129 $contents = $result->getBody()->getContents();
130 $data = json_decode($contents,
true);
133 if (isset($data[
'flag']) && $data[
'flag'] > 0) {
134 throw new \Exception($data[
'errortext']);
148 $this->logger->debug(
'setting: set useragent string to ' . $ua);
161 $this->logger->debug(
'setting: set IP address to ' . $ip);
176 if (is_null($this->dbdat) ===
true) {
177 $this->logger->debug(
'db: data file not found, download the data manually from http://data.udger.com/');
178 return array(
'flag' => 3,
179 'errortext' =>
'data file not found');
183 $ret = array(
'user_agent' =>
184 array(
'ua_string' =>
'',
186 'ua_class_code' =>
'',
189 'ua_version_major' =>
'',
190 'ua_uptodate_current_version' =>
'',
192 'ua_family_code' =>
'',
193 'ua_family_homepage' =>
'',
194 'ua_family_vendor' =>
'',
195 'ua_family_vendor_code' =>
'',
196 'ua_family_vendor_homepage' =>
'',
197 'ua_family_icon' =>
'',
198 'ua_family_icon_big' =>
'',
199 'ua_family_info_url' =>
'',
208 'os_family_code' =>
'',
209 'os_family_vendor' =>
'',
210 'os_family_vendor_code' =>
'',
211 'os_family_vendor_homepage' =>
'',
212 'device_class' =>
'',
213 'device_class_code' =>
'',
214 'device_class_icon' =>
'',
215 'device_class_icon_big' =>
'',
216 'device_class_info_url' =>
'',
217 'device_marketname' =>
'',
218 'device_brand' =>
'',
219 'device_brand_code' =>
'',
220 'device_brand_homepage' =>
'',
221 'device_brand_icon' =>
'',
222 'device_brand_icon_big' =>
'',
223 'device_brand_info_url' =>
'',
224 'crawler_last_seen' =>
'',
225 'crawler_category' =>
'',
226 'crawler_category_code' =>
'',
227 'crawler_respect_robotstxt' =>
''
232 'ip_classification' =>
'',
233 'ip_classification_code' =>
'',
235 'ip_last_seen' =>
'',
237 'ip_country_code' =>
'',
239 'crawler_name' =>
'',
241 'crawler_ver_major' =>
'',
242 'crawler_family' =>
'',
243 'crawler_family_code' =>
'',
244 'crawler_family_homepage' =>
'',
245 'crawler_family_vendor' =>
'',
246 'crawler_family_vendor_code' =>
'',
247 'crawler_family_vendor_homepage' =>
'',
248 'crawler_family_icon' =>
'',
249 'crawler_family_info_url' =>
'',
250 'crawler_last_seen' =>
'',
251 'crawler_category' =>
'',
252 'crawler_category_code' =>
'',
253 'crawler_respect_robotstxt' =>
'',
254 'datacenter_name' =>
'',
255 'datacenter_name_code' =>
'',
256 'datacenter_homepage' =>
''
260 if (!empty($this->ua)) {
261 $this->logger->debug(
"parse useragent string: START (useragent: " . $this->ua .
")");
264 if($this->cacheEnable) {
265 $retCache = $this->getCache( md5($this->ua) );
267 $ret[
'user_agent'] = unserialize($retCache);
273 $client_class_id = -1;
276 $ret[
'user_agent'][
'ua_string'] = $this->ua;
277 $ret[
'user_agent'][
'ua_class'] =
'Unrecognized';
278 $ret[
'user_agent'][
'ua_class_code'] =
'unrecognized';
281 $q = $this->dbdat->query(
"SELECT udger_crawler_list.id as botid,name,ver,ver_major,last_seen,respect_robotstxt,family,family_code,family_homepage,family_icon,vendor,vendor_code,vendor_homepage,crawler_classification,crawler_classification_code
282 FROM udger_crawler_list
283 LEFT JOIN udger_crawler_class ON udger_crawler_class.id=udger_crawler_list.class_id
284 WHERE ua_string='" . $this->dbdat->escapeString($this->ua) .
"'");
286 if ($r = $q->fetchArray(SQLITE3_ASSOC)) {
287 $this->logger->debug(
"parse useragent string: crawler found");
289 $client_class_id = 99;
290 $ret[
'user_agent'][
'ua_class'] =
'Crawler';
291 $ret[
'user_agent'][
'ua_class_code'] =
'crawler';
292 $ret[
'user_agent'][
'ua'] = $r[
'name'];
293 $ret[
'user_agent'][
'ua_version'] = $r[
'ver'];
294 $ret[
'user_agent'][
'ua_version_major'] = $r[
'ver_major'];
295 $ret[
'user_agent'][
'ua_family'] = $r[
'family'];
296 $ret[
'user_agent'][
'ua_family_code'] = $r[
'family_code'];
297 $ret[
'user_agent'][
'ua_family_homepage'] = $r[
'family_homepage'];
298 $ret[
'user_agent'][
'ua_family_vendor'] = $r[
'vendor'];
299 $ret[
'user_agent'][
'ua_family_vendor_code'] = $r[
'vendor_code'];
300 $ret[
'user_agent'][
'ua_family_vendor_homepage'] = $r[
'vendor_homepage'];
301 $ret[
'user_agent'][
'ua_family_icon'] = $r[
'family_icon'];
302 $ret[
'user_agent'][
'ua_family_info_url'] =
"https://udger.com/resources/ua-list/bot-detail?bot=" . $r[
'family'] .
"#id" . $r[
'botid'];
303 $ret[
'user_agent'][
'crawler_last_seen'] = $r[
'last_seen'];
304 $ret[
'user_agent'][
'crawler_category'] = $r[
'crawler_classification'];
305 $ret[
'user_agent'][
'crawler_category_code'] = $r[
'crawler_classification_code'];
306 $ret[
'user_agent'][
'crawler_respect_robotstxt'] = $r[
'respect_robotstxt'];
309 $q = $this->dbdat->query(
"SELECT class_id,client_id,regstring,name,name_code,homepage,icon,icon_big,engine,vendor,vendor_code,vendor_homepage,uptodate_current_version,client_classification,client_classification_code
310 FROM udger_client_regex
311 JOIN udger_client_list ON udger_client_list.id=udger_client_regex.client_id
312 JOIN udger_client_class ON udger_client_class.id=udger_client_list.class_id
313 ORDER BY sequence ASC");
314 while ($r = $q->fetchArray(SQLITE3_ASSOC)) {
315 if (@preg_match($r[
"regstring"], $this->ua, $result)) {
316 $this->logger->debug(
"parse useragent string: client found");
317 $client_id = $r[
'client_id'];
318 $client_class_id = $r[
'class_id'];
319 $ret[
'user_agent'][
'ua_class'] = $r[
'client_classification'];
320 $ret[
'user_agent'][
'ua_class_code'] = $r[
'client_classification_code'];
321 if (isset($result[1])) {
322 $ret[
'user_agent'][
'ua'] = $r[
'name'] .
" " . $result[1];
323 $ret[
'user_agent'][
'ua_version'] = $result[1];
324 $ver_major = explode(
".", $result[1]);
325 $ret[
'user_agent'][
'ua_version_major'] = $ver_major[0];
327 $ret[
'user_agent'][
'ua'] = $r[
'name'];
328 $ret[
'user_agent'][
'ua_version'] =
'';
329 $ret[
'user_agent'][
'ua_version_major'] =
'';
331 $ret[
'user_agent'][
'ua_uptodate_current_version'] = $r[
'uptodate_current_version'];
332 $ret[
'user_agent'][
'ua_family'] = $r[
'name'];
333 $ret[
'user_agent'][
'ua_family_code'] = $r[
'name_code'];
334 $ret[
'user_agent'][
'ua_family_homepage'] = $r[
'homepage'];
335 $ret[
'user_agent'][
'ua_family_vendor'] = $r[
'vendor'];
336 $ret[
'user_agent'][
'ua_family_vendor_code'] = $r[
'vendor_code'];
337 $ret[
'user_agent'][
'ua_family_vendor_homepage'] = $r[
'vendor_homepage'];
338 $ret[
'user_agent'][
'ua_family_icon'] = $r[
'icon'];
339 $ret[
'user_agent'][
'ua_family_icon_big'] = $r[
'icon_big'];
340 $ret[
'user_agent'][
'ua_family_info_url'] =
"https://udger.com/resources/ua-list/browser-detail?browser=" . $r[
'name'];
341 $ret[
'user_agent'][
'ua_engine'] = $r[
'engine'];
346 $q = $this->dbdat->query(
"SELECT os_id,regstring,family,family_code,name,name_code,homepage,icon,icon_big,vendor,vendor_code,vendor_homepage
348 JOIN udger_os_list ON udger_os_list.id=udger_os_regex.os_id
349 ORDER BY sequence ASC");
350 while ($r = $q->fetchArray(SQLITE3_ASSOC)) {
351 if (@preg_match($r[
"regstring"], $this->ua, $result)) {
352 $this->logger->debug(
"parse useragent string: os found");
353 $os_id = $r[
'os_id'];
354 $ret[
'user_agent'][
'os'] = $r[
'name'];
355 $ret[
'user_agent'][
'os_code'] = $r[
'name_code'];
356 $ret[
'user_agent'][
'os_homepage'] = $r[
'homepage'];
357 $ret[
'user_agent'][
'os_icon'] = $r[
'icon'];
358 $ret[
'user_agent'][
'os_icon_big'] = $r[
'icon_big'];
359 $ret[
'user_agent'][
'os_info_url'] =
"https://udger.com/resources/ua-list/os-detail?os=" . $r[
'name'];
360 $ret[
'user_agent'][
'os_family'] = $r[
'family'];
361 $ret[
'user_agent'][
'os_family_code'] = $r[
'family_code'];
362 $ret[
'user_agent'][
'os_family_vendor'] = $r[
'vendor'];
363 $ret[
'user_agent'][
'os_family_vendor_code'] = $r[
'vendor_code'];
364 $ret[
'user_agent'][
'os_family_vendor_homepage'] = $r[
'vendor_homepage'];
369 if ($os_id == 0 AND $client_id != 0) {
370 $q = $this->dbdat->query(
"SELECT os_id,family,family_code,name,name_code,homepage,icon,icon_big,vendor,vendor_code,vendor_homepage
371 FROM udger_client_os_relation
372 JOIN udger_os_list ON udger_os_list.id=udger_client_os_relation.os_id
373 WHERE client_id=" . $client_id .
" ");
374 if ($r = $q->fetchArray(SQLITE3_ASSOC)) {
375 $this->logger->debug(
"parse useragent string: client os relation found");
376 $os_id = $r[
'os_id'];
377 $ret[
'user_agent'][
'os'] = $r[
'name'];
378 $ret[
'user_agent'][
'os_code'] = $r[
'name_code'];
379 $ret[
'user_agent'][
'os_homepage'] = $r[
'homepage'];
380 $ret[
'user_agent'][
'os_icon'] = $r[
'icon'];
381 $ret[
'user_agent'][
'os_icon_big'] = $r[
'icon_big'];
382 $ret[
'user_agent'][
'os_info_url'] =
"https://udger.com/resources/ua-list/os-detail?os=" . $r[
'name'];
383 $ret[
'user_agent'][
'os_family'] = $r[
'family'];
384 $ret[
'user_agent'][
'os_family_code'] = $r[
'family_code'];
385 $ret[
'user_agent'][
'os_family_vendor'] = $r[
'vendor'];
386 $ret[
'user_agent'][
'os_family_vendor_code'] = $r[
'vendor_code'];
387 $ret[
'user_agent'][
'os_family_vendor_homepage'] = $r[
'vendor_homepage'];
391 $q = $this->dbdat->query(
"SELECT deviceclass_id,regstring,name,name_code,icon,icon_big
392 FROM udger_deviceclass_regex
393 JOIN udger_deviceclass_list ON udger_deviceclass_list.id=udger_deviceclass_regex.deviceclass_id
394 ORDER BY sequence ASC");
396 while ($r = $q->fetchArray(SQLITE3_ASSOC)) {
397 if (@preg_match($r[
"regstring"], $this->ua, $result)) {
398 $this->logger->debug(
"parse useragent string: device found by regex");
399 $deviceclass_id = $r[
'deviceclass_id'];
400 $ret[
'user_agent'][
'device_class'] = $r[
'name'];
401 $ret[
'user_agent'][
'device_class_code'] = $r[
'name_code'];
402 $ret[
'user_agent'][
'device_class_icon'] = $r[
'icon'];
403 $ret[
'user_agent'][
'device_class_icon_big'] = $r[
'icon_big'];
404 $ret[
'user_agent'][
'device_class_info_url'] =
"https://udger.com/resources/ua-list/device-detail?device=" . $r[
'name'];
408 if ($deviceclass_id == 0 AND $client_class_id != -1) {
409 $q = $this->dbdat->query(
"SELECT deviceclass_id,name,name_code,icon,icon_big
410 FROM udger_deviceclass_list
411 JOIN udger_client_class ON udger_client_class.deviceclass_id=udger_deviceclass_list.id
412 WHERE udger_client_class.id=" . $client_class_id .
" ");
413 if ($r = $q->fetchArray(SQLITE3_ASSOC)) {
414 $this->logger->debug(
"parse useragent string: device found by deviceclass");
415 $deviceclass_id = $r[
'deviceclass_id'];
416 $ret[
'user_agent'][
'device_class'] = $r[
'name'];
417 $ret[
'user_agent'][
'device_class_code'] = $r[
'name_code'];
418 $ret[
'user_agent'][
'device_class_icon'] = $r[
'icon'];
419 $ret[
'user_agent'][
'device_class_icon_big'] = $r[
'icon_big'];
420 $ret[
'user_agent'][
'device_class_info_url'] =
"https://udger.com/resources/ua-list/device-detail?device=" . $r[
'name'];
425 if($ret[
'user_agent'][
'os_family_code']) {
426 $q = $this->dbdat->query(
"SELECT id,regstring FROM udger_devicename_regex WHERE
427 ((os_family_code='".$ret[
'user_agent'][
'os_family_code'].
"' AND os_code='-all-')
429 (os_family_code='".$ret[
'user_agent'][
'os_family_code'].
"' AND os_code='".$ret[
'user_agent'][
'os_code'].
"'))
431 while ($r = $q->fetchArray(SQLITE3_ASSOC)) {
432 @preg_match($r[
"regstring"],$this->ua,$result);
434 if(array_key_exists(1, $result)) {
435 $qC=$this->dbdat->query(
"SELECT marketname,brand_code,brand,brand_url,icon,icon_big
436 FROM udger_devicename_list
437 JOIN udger_devicename_brand ON udger_devicename_brand.id=udger_devicename_list.brand_id
438 WHERE regex_id=".$r[
"id"].
" and code = '".\SQLite3::escapeString(trim($result[1])).
"' COLLATE NOCASE ");
440 if($rC = $qC->fetchArray(SQLITE3_ASSOC)) {
441 $this->logger->debug(
"parse useragent string: device marketname found");
442 $ret[
'user_agent'][
'device_marketname'] = $rC[
'marketname'];
443 $ret[
'user_agent'][
'device_brand'] = $rC[
'brand'];
444 $ret[
'user_agent'][
'device_brand_code'] = $rC[
'brand_code'];
445 $ret[
'user_agent'][
'device_brand_homepage'] = $rC[
'brand_url'];
446 $ret[
'user_agent'][
'device_brand_icon'] = $rC[
'icon'];
447 $ret[
'user_agent'][
'device_brand_icon_big'] = $rC[
'icon_big'];
448 $ret[
'user_agent'][
'device_brand_info_url'] =
"https://udger.com/resources/ua-list/devices-brand-detail?brand=".$rC[
'brand_code'];
455 if($this->cacheEnable) {
456 $this->setCache( md5($this->ua) , serialize($ret[
'user_agent']) );
461 $this->logger->debug(
"parse useragent string: END, unset useragent string");
465 if (!empty($this->ip)) {
466 $this->logger->debug(
"parse IP address: START (IP: " . $this->ip .
")");
467 $ret[
'ip_address'][
'ip'] = $this->ip;
468 $ipver = $this->ipHelper->getIpVersion($this->ip);
470 if ($ipver !==
false) {
471 if ($ipver === IPInterface::IPv6) {
472 $this->ip = inet_ntop(inet_pton($this->ip));
473 $this->logger->debug(
"compress IP address is:" . $this->ip);
476 $ret[
'ip_address'][
'ip_ver'] = $ipver;
477 $q = $this->dbdat->query(
"SELECT udger_crawler_list.id as botid,ip_last_seen,ip_hostname,ip_country,ip_city,ip_country_code,ip_classification,ip_classification_code,
478 name,ver,ver_major,last_seen,respect_robotstxt,family,family_code,family_homepage,family_icon,vendor,vendor_code,vendor_homepage,crawler_classification,crawler_classification_code
480 JOIN udger_ip_class ON udger_ip_class.id=udger_ip_list.class_id
481 LEFT JOIN udger_crawler_list ON udger_crawler_list.id=udger_ip_list.crawler_id
482 LEFT JOIN udger_crawler_class ON udger_crawler_class.id=udger_crawler_list.class_id
483 WHERE ip='" . $this->ip .
"' ORDER BY sequence");
485 if ($r = $q->fetchArray(SQLITE3_ASSOC)) {
486 $ret[
'ip_address'][
'ip_classification'] = $r[
'ip_classification'];
487 $ret[
'ip_address'][
'ip_classification_code'] = $r[
'ip_classification_code'];
488 $ret[
'ip_address'][
'ip_last_seen'] = $r[
'ip_last_seen'];
489 $ret[
'ip_address'][
'ip_hostname'] = $r[
'ip_hostname'];
490 $ret[
'ip_address'][
'ip_country'] = $r[
'ip_country'];
491 $ret[
'ip_address'][
'ip_country_code'] = $r[
'ip_country_code'];
492 $ret[
'ip_address'][
'ip_city'] = $r[
'ip_city'];
494 $ret[
'ip_address'][
'crawler_name'] = $r[
'name'];
495 $ret[
'ip_address'][
'crawler_ver'] = $r[
'ver'];
496 $ret[
'ip_address'][
'crawler_ver_major'] = $r[
'ver_major'];
497 $ret[
'ip_address'][
'crawler_family'] = $r[
'family'];
498 $ret[
'ip_address'][
'crawler_family_code'] = $r[
'family_code'];
499 $ret[
'ip_address'][
'crawler_family_homepage'] = $r[
'family_homepage'];
500 $ret[
'ip_address'][
'crawler_family_vendor'] = $r[
'vendor'];
501 $ret[
'ip_address'][
'crawler_family_vendor_code'] = $r[
'vendor_code'];
502 $ret[
'ip_address'][
'crawler_family_vendor_homepage'] = $r[
'vendor_homepage'];
503 $ret[
'ip_address'][
'crawler_family_icon'] = $r[
'family_icon'];
504 if ($r[
'ip_classification_code'] ==
'crawler') {
505 $ret[
'ip_address'][
'crawler_family_info_url'] =
"https://udger.com/resources/ua-list/bot-detail?bot=" . $r[
'family'] .
"#id" . $r[
'botid'];
507 $ret[
'ip_address'][
'crawler_last_seen'] = $r[
'last_seen'];
508 $ret[
'ip_address'][
'crawler_category'] = $r[
'crawler_classification'];
509 $ret[
'ip_address'][
'crawler_category_code'] = $r[
'crawler_classification_code'];
510 $ret[
'ip_address'][
'crawler_respect_robotstxt'] = $r[
'respect_robotstxt'];
512 $ret[
'ip_address'][
'ip_classification'] =
'Unrecognized';
513 $ret[
'ip_address'][
'ip_classification_code'] =
'unrecognized';
516 if ($this->ipHelper->getIpVersion($ret[
'ip_address'][
'ip']) === IPInterface::IPv4) {
518 $ipLong = $this->ipHelper->getIpLong($ret[
'ip_address'][
'ip']);
520 $q = $this->dbdat->query(
"select name,name_code,homepage
521 FROM udger_datacenter_range
522 JOIN udger_datacenter_list ON udger_datacenter_range.datacenter_id=udger_datacenter_list.id
523 where iplong_from <= " . $ipLong .
" AND iplong_to >= " . $ipLong .
" ");
525 if ($r = $q->fetchArray(SQLITE3_ASSOC)) {
526 $ret[
'ip_address'][
'datacenter_name'] = $r[
'name'];
527 $ret[
'ip_address'][
'datacenter_name_code'] = $r[
'name_code'];
528 $ret[
'ip_address'][
'datacenter_homepage'] = $r[
'homepage'];
531 else if ($this->ipHelper->getIpVersion($ret[
'ip_address'][
'ip']) === IPInterface::IPv6) {
532 $ipInt = $this->ipHelper->getIp6array($ret[
'ip_address'][
'ip']);
533 $q = $this->dbdat->query(
"select name,name_code,homepage
534 FROM udger_datacenter_range6
535 JOIN udger_datacenter_list ON udger_datacenter_range6.datacenter_id=udger_datacenter_list.id
537 iplong_from0 <= ".$ipInt[0].
" AND iplong_to0 >= ".$ipInt[0].
" AND
538 iplong_from1 <= ".$ipInt[1].
" AND iplong_to1 >= ".$ipInt[1].
" AND
539 iplong_from2 <= ".$ipInt[2].
" AND iplong_to2 >= ".$ipInt[2].
" AND
540 iplong_from3 <= ".$ipInt[3].
" AND iplong_to3 >= ".$ipInt[3].
" AND
541 iplong_from4 <= ".$ipInt[4].
" AND iplong_to4 >= ".$ipInt[4].
" AND
542 iplong_from5 <= ".$ipInt[5].
" AND iplong_to5 >= ".$ipInt[5].
" AND
543 iplong_from6 <= ".$ipInt[6].
" AND iplong_to6 >= ".$ipInt[6].
" AND
544 iplong_from7 <= ".$ipInt[7].
" AND iplong_to7 >= ".$ipInt[7].
"
547 if ($r = $q->fetchArray(SQLITE3_ASSOC)) {
548 $ret[
'ip_address'][
'datacenter_name'] = $r[
'name'];
549 $ret[
'ip_address'][
'datacenter_name_code'] = $r[
'name_code'];
550 $ret[
'ip_address'][
'datacenter_homepage'] = $r[
'homepage'];
555 $this->logger->debug(
"parse IP address: END, unset IP address");
566 if (is_null($this->dbdat)) {
567 $this->logger->debug(sprintf(
"db: open file: %s", $this->path));
568 $this->dbdat = new \SQLite3($this->path, SQLITE3_OPEN_READONLY);
576 $this->logger->debug(
'LRUcache: set to key' . $key);
577 $this->cache[$key] = $value;
578 if (count($this->cache) > $this->cacheSize) {
579 array_shift($this->cache);
587 $this->logger->debug(
'LRUcache: get key' . $key);
588 if ( ! isset($this->cache[$key])) {
589 $this->logger->debug(
'LRUcache: key' . $key .
' Not Found' );
593 $tmpValue = $this->cache[$key];
594 unset($this->cache[$key]);
595 $this->cache[$key] = $tmpValue;
596 $this->logger->debug(
'LRUcache: key' . $key .
' Found' );
608 $this->cacheEnable = $set;
609 $log = $set ?
'true' :
'false';
610 $this->logger->debug(
'LRUcache: enable/disable: ' . $log );
622 $this->cacheSize = $size;
623 $this->logger->debug(
'LRUcache: set size: ' . $size );
633 $this->cache = array();
634 $this->logger->debug(
'LRUcache: clear cache');
646 if (
false === file_exists($path)) {
647 throw new \Exception(sprintf(
"%s does not exist", $path));
663 $this->logger->debug(
'setting: set accesskey to ' . $access_key);
664 $this->access_key = $access_key;
__construct(LoggerInterface $logger, IPInterface $ipHelper)
setAccessKey($access_key)