diff --git a/README.md b/README.md index b4d64cc..7d6db73 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ It also provides information about IP addresses (Public proxies, VPN services, T ### Features - Fast +- LRU cache - Released under the GNU (LGPL v.3) ### Install @@ -27,8 +28,10 @@ Here's a quick example: require_once dirname(__DIR__) . '/vendor/autoload.php'; $factory = new Udger\ParserFactory(); $parser = $factory->getParser(); -$parser->setDataFile(sys_get_temp_dir() . "/udgercache/udgerdb_v3.dat"); -$parser->setUA('Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36'); +$parser->setDataFile(sys_get_temp_dir() . "/udgercache/udgerdb_v3.dat"); +//$parser->setCacheEnable(false); +//$parser->setCacheSize(4000); +$parser->setUA('Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-A510F Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.5 Chrome/38.0.2125.102 Mobile Safari/537.36'); $parser->setIP("2A02:598:7000:116:0:0:0:101"); $ret = $parser->parse(); echo "
"; @@ -38,41 +41,46 @@ echo ""; Array ( - [user_agent] => Array + [user_agent] => Array ( - [ua_string] => Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36 - [ua_class] => Browser - [ua_class_code] => browser - [ua] => Chrome 48.0.2564.97 - [ua_version] => 48.0.2564.97 - [ua_version_major] => 48 - [ua_uptodate_current_version] => 48 - [ua_family] => Chrome - [ua_family_code] => chrome - [ua_family_homepage] => http://www.google.com/chrome/ - [ua_family_vendor] => Google Inc. - [ua_family_vendor_code] => google_inc - [ua_family_vendor_homepage] => https://www.google.com/about/company/ - [ua_family_icon] => chrome.png - [ua_family_icon_big] => chrome_big.png - [ua_family_info_url] => https://udger.com/resources/ua-list/browser-detail?browser=Chrome + [ua_string] => Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-A510F Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.5 Chrome/38.0.2125.102 Mobile Safari/537.36 + [ua_class] => Mobile browser + [ua_class_code] => mobile_browser + [ua] => Mobile Samsung Browser 3.5 + [ua_version] => 3.5 + [ua_version_major] => 3 + [ua_uptodate_current_version] => + [ua_family] => Mobile Samsung Browser + [ua_family_code] => mobile_samsung_browser + [ua_family_homepage] => http://developer.samsung.com/internet + [ua_family_vendor] => SAMSUNG + [ua_family_vendor_code] => samsung + [ua_family_vendor_homepage] => http://www.samsung.com/ + [ua_family_icon] => samsung_browser.png + [ua_family_icon_big] => samsung_browser_big.png + [ua_family_info_url] => https://udger.com/resources/ua-list/browser-detail?browser=Mobile Samsung Browser [ua_engine] => WebKit/Blink - [os] => Windows 7 - [os_code] => windows_7 - [os_homepage] => https://en.wikipedia.org/wiki/Windows_7 - [os_icon] => windows-7.png - [os_icon_big] => windows-7_big.png - [os_info_url] => https://udger.com/resources/ua-list/os-detail?os=Windows 7 - [os_family] => Windows - [os_family_code] => windows - [os_family_vendor] => Microsoft Corporation. - [os_family_vendor_code] => microsoft_corporation - [os_family_vendor_homepage] => https://www.microsoft.com/about/ - [device_class] => Desktop - [device_class_code] => desktop - [device_class_icon] => desktop.png - [device_class_icon_big] => desktop_big.png - [device_class_info_url] => https://udger.com/resources/ua-list/device-detail?device=Desktop + [os] => Android 5.1 lollipop + [os_code] => android_5_1 + [os_homepage] => https://en.wikipedia.org/wiki/Android_Lollipop + [os_icon] => android.png + [os_icon_big] => android_big.png + [os_info_url] => https://udger.com/resources/ua-list/os-detail?os=Android 5.1 lollipop + [os_family] => Android + [os_family_code] => android + [os_family_vendor] => Google, Inc. + [os_family_vendor_code] => google_inc + [os_family_vendor_homepage] => https://www.google.com/about/company/ + [device_class] => Smartphone + [device_class_code] => smartphone + [device_class_icon] => phone.png + [device_class_icon_big] => phone_big.png + [device_class_info_url] => https://udger.com/resources/ua-list/device-detail?device=Smartphone + [device_marketname] => Galaxy A5 (2016) + [device_vendor] => Samsung + [device_vendor_code] => samsung + [device_vendor_homepage] => http://www.samsung.com/ + [device_vendor_icon] => samsung.png [crawler_last_seen] => [crawler_category] => [crawler_category_code] => @@ -121,6 +129,9 @@ Array ### Automatic updates download - for autoupdate data use Udger data updater (https://udger.com/support/documentation/?doc=62) +### Documentation for programmers +- https://udger.com/pub/documentation/parser/PHP/html/ + ### Author - The Udger.com Team (info@udger.com) diff --git a/examples/parse.php b/examples/parse.php index f7c2b40..10ade5a 100644 --- a/examples/parse.php +++ b/examples/parse.php @@ -5,6 +5,8 @@ // creates a new UdgerParser object $factory = new Udger\ParserFactory(sys_get_temp_dir() . "/udgercache/udgerdb_v3.dat"); $parser = $factory->getParser(); +//$parser->setCacheEnable(false); +//$parser->setCacheSize(4000); try { $parser->setUA('Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36'); diff --git a/src/Helper/IP.php b/src/Helper/IP.php index 3037750..6c0b2e8 100644 --- a/src/Helper/IP.php +++ b/src/Helper/IP.php @@ -22,7 +22,7 @@ public function getIpVersion($ip) return self::IPv6; } - if (false !== filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + else if (false !== filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { return self::IPv4; } // invalid ip @@ -39,4 +39,26 @@ public function getIpLong($ip) { return sprintf('%u', ip2long($ip)); } + + + /** + * Ipv6 to array + * + * @param string $ip + * @return array + */ + public function getIp6array($ip){ + // expand - example: "2600:3c00::" -> "2600:3c00:0000:0000:0000:0000:0000:0000" + $hex = unpack("H*hex", inet_pton($ip)); + $ipStr = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1); + + $ipIntArray = array(); + $ipStrArray = split(":", $ipStr); + + foreach ($ipStrArray as &$value) { + $ipIntArray[] = hexdec($value); + } + + return $ipIntArray; + } } \ No newline at end of file diff --git a/src/Helper/IPInterface.php b/src/Helper/IPInterface.php index b92cac6..d5f0605 100644 --- a/src/Helper/IPInterface.php +++ b/src/Helper/IPInterface.php @@ -14,4 +14,6 @@ interface IPInterface { public function getIpVersion($ip); public function getIpLong($ip); + + public function getIp6array($ip); } diff --git a/src/Parser.php b/src/Parser.php index 5a5a5e9..44049c5 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -74,6 +74,21 @@ class Parser implements ParserInterface * @var IPInterface */ protected $ipHelper; + + /** + * @boolean LRU cache enable/disable + */ + protected $cacheEnable = true; + + /** + * @array LRU cache + */ + protected $cache = array(); + + /** + * @int LRU cache size + */ + protected $cacheSize = 3000; /** * @param LoggerInterface $logger @@ -199,6 +214,13 @@ public function parse() 'device_class_icon' => '', 'device_class_icon_big' => '', 'device_class_info_url' => '', + 'device_marketname' => '', + 'device_brand' => '', + 'device_brand_code' => '', + 'device_brand_homepage' => '', + 'device_brand_icon' => '', + 'device_brand_icon_big' => '', + 'device_brand_info_url' => '', 'crawler_last_seen' => '', 'crawler_category' => '', 'crawler_category_code' => '', @@ -237,155 +259,201 @@ public function parse() if (!empty($this->ua)) { $this->logger->debug("parse useragent string: START (useragent: " . $this->ua . ")"); - $client_id = 0; - $client_class_id = -1; - $os_id = 0; - $deviceclass_id = 0; - $ret['user_agent']['ua_string'] = $this->ua; - $ret['user_agent']['ua_class'] = 'Unrecognized'; - $ret['user_agent']['ua_class_code'] = 'unrecognized'; - - // crawler - $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 - FROM udger_crawler_list - LEFT JOIN udger_crawler_class ON udger_crawler_class.id=udger_crawler_list.class_id - WHERE ua_string='" . $this->ua . "'"); - - if ($r = $q->fetchArray(SQLITE3_ASSOC)) { - $this->logger->debug("parse useragent string: crawler found"); - - $client_class_id = 99; - $ret['user_agent']['ua_class'] = 'Crawler'; - $ret['user_agent']['ua_class_code'] = 'crawler'; - $ret['user_agent']['ua'] = $r['name']; - $ret['user_agent']['ua_version'] = $r['ver']; - $ret['user_agent']['ua_version_major'] = $r['ver_major']; - $ret['user_agent']['ua_family'] = $r['family']; - $ret['user_agent']['ua_family_code'] = $r['family_code']; - $ret['user_agent']['ua_family_homepage'] = $r['family_homepage']; - $ret['user_agent']['ua_family_vendor'] = $r['vendor']; - $ret['user_agent']['ua_family_vendor_code'] = $r['vendor_code']; - $ret['user_agent']['ua_family_vendor_homepage'] = $r['vendor_homepage']; - $ret['user_agent']['ua_family_icon'] = $r['family_icon']; - $ret['user_agent']['ua_family_info_url'] = "https://udger.com/resources/ua-list/bot-detail?bot=" . $r['family'] . "#id" . $r['botid']; - $ret['user_agent']['crawler_last_seen'] = $r['last_seen']; - $ret['user_agent']['crawler_category'] = $r['crawler_classification']; - $ret['user_agent']['crawler_category_code'] = $r['crawler_classification_code']; - $ret['user_agent']['crawler_respect_robotstxt'] = $r['respect_robotstxt']; - } else { - // client - $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 - FROM udger_client_regex - JOIN udger_client_list ON udger_client_list.id=udger_client_regex.client_id - JOIN udger_client_class ON udger_client_class.id=udger_client_list.class_id - ORDER BY sequence ASC"); - while ($r = $q->fetchArray(SQLITE3_ASSOC)) { - if (@preg_match($r["regstring"], $this->ua, $result)) { - $this->logger->debug("parse useragent string: client found"); - $client_id = $r['client_id']; - $client_class_id = $r['class_id']; - $ret['user_agent']['ua_class'] = $r['client_classification']; - $ret['user_agent']['ua_class_code'] = $r['client_classification_code']; - if (isset($result[1])) { - $ret['user_agent']['ua'] = $r['name'] . " " . $result[1]; - $ret['user_agent']['ua_version'] = $result[1]; - $ver_major = explode(".", $result[1]); - $ret['user_agent']['ua_version_major'] = $ver_major[0]; - } else { - $ret['user_agent']['ua'] = $r['name']; - $ret['user_agent']['ua_version'] = ''; - $ret['user_agent']['ua_version_major'] = ''; + + $usedCache = false; + if($this->cacheEnable) { + $retCache = $this->getCache( md5($this->ua) ); + if($retCache) { + $ret['user_agent'] = unserialize($retCache); + $usedCache = true; + } + } + if(!$usedCache) { + $client_id = 0; + $client_class_id = -1; + $os_id = 0; + $deviceclass_id = 0; + $ret['user_agent']['ua_string'] = $this->ua; + $ret['user_agent']['ua_class'] = 'Unrecognized'; + $ret['user_agent']['ua_class_code'] = 'unrecognized'; + + // crawler + $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 + FROM udger_crawler_list + LEFT JOIN udger_crawler_class ON udger_crawler_class.id=udger_crawler_list.class_id + WHERE ua_string='" . $this->dbdat->escapeString($this->ua) . "'"); + + if ($r = $q->fetchArray(SQLITE3_ASSOC)) { + $this->logger->debug("parse useragent string: crawler found"); + + $client_class_id = 99; + $ret['user_agent']['ua_class'] = 'Crawler'; + $ret['user_agent']['ua_class_code'] = 'crawler'; + $ret['user_agent']['ua'] = $r['name']; + $ret['user_agent']['ua_version'] = $r['ver']; + $ret['user_agent']['ua_version_major'] = $r['ver_major']; + $ret['user_agent']['ua_family'] = $r['family']; + $ret['user_agent']['ua_family_code'] = $r['family_code']; + $ret['user_agent']['ua_family_homepage'] = $r['family_homepage']; + $ret['user_agent']['ua_family_vendor'] = $r['vendor']; + $ret['user_agent']['ua_family_vendor_code'] = $r['vendor_code']; + $ret['user_agent']['ua_family_vendor_homepage'] = $r['vendor_homepage']; + $ret['user_agent']['ua_family_icon'] = $r['family_icon']; + $ret['user_agent']['ua_family_info_url'] = "https://udger.com/resources/ua-list/bot-detail?bot=" . $r['family'] . "#id" . $r['botid']; + $ret['user_agent']['crawler_last_seen'] = $r['last_seen']; + $ret['user_agent']['crawler_category'] = $r['crawler_classification']; + $ret['user_agent']['crawler_category_code'] = $r['crawler_classification_code']; + $ret['user_agent']['crawler_respect_robotstxt'] = $r['respect_robotstxt']; + } else { + // client + $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 + FROM udger_client_regex + JOIN udger_client_list ON udger_client_list.id=udger_client_regex.client_id + JOIN udger_client_class ON udger_client_class.id=udger_client_list.class_id + ORDER BY sequence ASC"); + while ($r = $q->fetchArray(SQLITE3_ASSOC)) { + if (@preg_match($r["regstring"], $this->ua, $result)) { + $this->logger->debug("parse useragent string: client found"); + $client_id = $r['client_id']; + $client_class_id = $r['class_id']; + $ret['user_agent']['ua_class'] = $r['client_classification']; + $ret['user_agent']['ua_class_code'] = $r['client_classification_code']; + if (isset($result[1])) { + $ret['user_agent']['ua'] = $r['name'] . " " . $result[1]; + $ret['user_agent']['ua_version'] = $result[1]; + $ver_major = explode(".", $result[1]); + $ret['user_agent']['ua_version_major'] = $ver_major[0]; + } else { + $ret['user_agent']['ua'] = $r['name']; + $ret['user_agent']['ua_version'] = ''; + $ret['user_agent']['ua_version_major'] = ''; + } + $ret['user_agent']['ua_uptodate_current_version'] = $r['uptodate_current_version']; + $ret['user_agent']['ua_family'] = $r['name']; + $ret['user_agent']['ua_family_code'] = $r['name_code']; + $ret['user_agent']['ua_family_homepage'] = $r['homepage']; + $ret['user_agent']['ua_family_vendor'] = $r['vendor']; + $ret['user_agent']['ua_family_vendor_code'] = $r['vendor_code']; + $ret['user_agent']['ua_family_vendor_homepage'] = $r['vendor_homepage']; + $ret['user_agent']['ua_family_icon'] = $r['icon']; + $ret['user_agent']['ua_family_icon_big'] = $r['icon_big']; + $ret['user_agent']['ua_family_info_url'] = "https://udger.com/resources/ua-list/browser-detail?browser=" . $r['name']; + $ret['user_agent']['ua_engine'] = $r['engine']; + break; } - $ret['user_agent']['ua_uptodate_current_version'] = $r['uptodate_current_version']; - $ret['user_agent']['ua_family'] = $r['name']; - $ret['user_agent']['ua_family_code'] = $r['name_code']; - $ret['user_agent']['ua_family_homepage'] = $r['homepage']; - $ret['user_agent']['ua_family_vendor'] = $r['vendor']; - $ret['user_agent']['ua_family_vendor_code'] = $r['vendor_code']; - $ret['user_agent']['ua_family_vendor_homepage'] = $r['vendor_homepage']; - $ret['user_agent']['ua_family_icon'] = $r['icon']; - $ret['user_agent']['ua_family_icon_big'] = $r['icon_big']; - $ret['user_agent']['ua_family_info_url'] = "https://udger.com/resources/ua-list/browser-detail?browser=" . $r['name']; - $ret['user_agent']['ua_engine'] = $r['engine']; - break; } - } - // os - $q = $this->dbdat->query("SELECT os_id,regstring,family,family_code,name,name_code,homepage,icon,icon_big,vendor,vendor_code,vendor_homepage - FROM udger_os_regex - JOIN udger_os_list ON udger_os_list.id=udger_os_regex.os_id - ORDER BY sequence ASC"); - while ($r = $q->fetchArray(SQLITE3_ASSOC)) { - if (@preg_match($r["regstring"], $this->ua, $result)) { - $this->logger->debug("parse useragent string: os found"); - $os_id = $r['os_id']; - $ret['user_agent']['os'] = $r['name']; - $ret['user_agent']['os_code'] = $r['name_code']; - $ret['user_agent']['os_homepage'] = $r['homepage']; - $ret['user_agent']['os_icon'] = $r['icon']; - $ret['user_agent']['os_icon_big'] = $r['icon_big']; - $ret['user_agent']['os_info_url'] = "https://udger.com/resources/ua-list/os-detail?os=" . $r['name']; - $ret['user_agent']['os_family'] = $r['family']; - $ret['user_agent']['os_family_code'] = $r['family_code']; - $ret['user_agent']['os_family_vendor'] = $r['vendor']; - $ret['user_agent']['os_family_vendor_code'] = $r['vendor_code']; - $ret['user_agent']['os_family_vendor_homepage'] = $r['vendor_homepage']; - break; + // os + $q = $this->dbdat->query("SELECT os_id,regstring,family,family_code,name,name_code,homepage,icon,icon_big,vendor,vendor_code,vendor_homepage + FROM udger_os_regex + JOIN udger_os_list ON udger_os_list.id=udger_os_regex.os_id + ORDER BY sequence ASC"); + while ($r = $q->fetchArray(SQLITE3_ASSOC)) { + if (@preg_match($r["regstring"], $this->ua, $result)) { + $this->logger->debug("parse useragent string: os found"); + $os_id = $r['os_id']; + $ret['user_agent']['os'] = $r['name']; + $ret['user_agent']['os_code'] = $r['name_code']; + $ret['user_agent']['os_homepage'] = $r['homepage']; + $ret['user_agent']['os_icon'] = $r['icon']; + $ret['user_agent']['os_icon_big'] = $r['icon_big']; + $ret['user_agent']['os_info_url'] = "https://udger.com/resources/ua-list/os-detail?os=" . $r['name']; + $ret['user_agent']['os_family'] = $r['family']; + $ret['user_agent']['os_family_code'] = $r['family_code']; + $ret['user_agent']['os_family_vendor'] = $r['vendor']; + $ret['user_agent']['os_family_vendor_code'] = $r['vendor_code']; + $ret['user_agent']['os_family_vendor_homepage'] = $r['vendor_homepage']; + break; + } } - } - // client_os_relation - if ($os_id == 0 AND $client_id != 0) { - $q = $this->dbdat->query("SELECT os_id,family,family_code,name,name_code,homepage,icon,icon_big,vendor,vendor_code,vendor_homepage - FROM udger_client_os_relation - JOIN udger_os_list ON udger_os_list.id=udger_client_os_relation.os_id - WHERE client_id=" . $client_id . " "); - if ($r = $q->fetchArray(SQLITE3_ASSOC)) { - $this->logger->debug("parse useragent string: client os relation found"); - $os_id = $r['os_id']; - $ret['user_agent']['os'] = $r['name']; - $ret['user_agent']['os_code'] = $r['name_code']; - $ret['user_agent']['os_homepage'] = $r['homepage']; - $ret['user_agent']['os_icon'] = $r['icon']; - $ret['user_agent']['os_icon_big'] = $r['icon_big']; - $ret['user_agent']['os_info_url'] = "https://udger.com/resources/ua-list/os-detail?os=" . $r['name']; - $ret['user_agent']['os_family'] = $r['family']; - $ret['user_agent']['os_family_code'] = $r['family_code']; - $ret['user_agent']['os_family_vendor'] = $r['vendor']; - $ret['user_agent']['os_family_vendor_code'] = $r['vendor_code']; - $ret['user_agent']['os_family_vendor_homepage'] = $r['vendor_homepage']; + // client_os_relation + if ($os_id == 0 AND $client_id != 0) { + $q = $this->dbdat->query("SELECT os_id,family,family_code,name,name_code,homepage,icon,icon_big,vendor,vendor_code,vendor_homepage + FROM udger_client_os_relation + JOIN udger_os_list ON udger_os_list.id=udger_client_os_relation.os_id + WHERE client_id=" . $client_id . " "); + if ($r = $q->fetchArray(SQLITE3_ASSOC)) { + $this->logger->debug("parse useragent string: client os relation found"); + $os_id = $r['os_id']; + $ret['user_agent']['os'] = $r['name']; + $ret['user_agent']['os_code'] = $r['name_code']; + $ret['user_agent']['os_homepage'] = $r['homepage']; + $ret['user_agent']['os_icon'] = $r['icon']; + $ret['user_agent']['os_icon_big'] = $r['icon_big']; + $ret['user_agent']['os_info_url'] = "https://udger.com/resources/ua-list/os-detail?os=" . $r['name']; + $ret['user_agent']['os_family'] = $r['family']; + $ret['user_agent']['os_family_code'] = $r['family_code']; + $ret['user_agent']['os_family_vendor'] = $r['vendor']; + $ret['user_agent']['os_family_vendor_code'] = $r['vendor_code']; + $ret['user_agent']['os_family_vendor_homepage'] = $r['vendor_homepage']; + } } - } - //device - $q = $this->dbdat->query("SELECT deviceclass_id,regstring,name,name_code,icon,icon_big - FROM udger_deviceclass_regex - JOIN udger_deviceclass_list ON udger_deviceclass_list.id=udger_deviceclass_regex.deviceclass_id - ORDER BY sequence ASC"); - - while ($r = $q->fetchArray(SQLITE3_ASSOC)) { - if (@preg_match($r["regstring"], $this->ua, $result)) { - $this->logger->debug("parse useragent string: device found by regex"); - $deviceclass_id = $r['deviceclass_id']; - $ret['user_agent']['device_class'] = $r['name']; - $ret['user_agent']['device_class_code'] = $r['name_code']; - $ret['user_agent']['device_class_icon'] = $r['icon']; - $ret['user_agent']['device_class_icon_big'] = $r['icon_big']; - $ret['user_agent']['device_class_info_url'] = "https://udger.com/resources/ua-list/device-detail?device=" . $r['name']; - break; + //device + $q = $this->dbdat->query("SELECT deviceclass_id,regstring,name,name_code,icon,icon_big + FROM udger_deviceclass_regex + JOIN udger_deviceclass_list ON udger_deviceclass_list.id=udger_deviceclass_regex.deviceclass_id + ORDER BY sequence ASC"); + + while ($r = $q->fetchArray(SQLITE3_ASSOC)) { + if (@preg_match($r["regstring"], $this->ua, $result)) { + $this->logger->debug("parse useragent string: device found by regex"); + $deviceclass_id = $r['deviceclass_id']; + $ret['user_agent']['device_class'] = $r['name']; + $ret['user_agent']['device_class_code'] = $r['name_code']; + $ret['user_agent']['device_class_icon'] = $r['icon']; + $ret['user_agent']['device_class_icon_big'] = $r['icon_big']; + $ret['user_agent']['device_class_info_url'] = "https://udger.com/resources/ua-list/device-detail?device=" . $r['name']; + break; + } } - } - if ($deviceclass_id == 0 AND $client_class_id != -1) { - $q = $this->dbdat->query("SELECT deviceclass_id,name,name_code,icon,icon_big + if ($deviceclass_id == 0 AND $client_class_id != -1) { + $q = $this->dbdat->query("SELECT deviceclass_id,name,name_code,icon,icon_big FROM udger_deviceclass_list JOIN udger_client_class ON udger_client_class.deviceclass_id=udger_deviceclass_list.id WHERE udger_client_class.id=" . $client_class_id . " "); - if ($r = $q->fetchArray(SQLITE3_ASSOC)) { - $this->logger->debug("parse useragent string: device found by deviceclass"); - $deviceclass_id = $r['deviceclass_id']; - $ret['user_agent']['device_class'] = $r['name']; - $ret['user_agent']['device_class_code'] = $r['name_code']; - $ret['user_agent']['device_class_icon'] = $r['icon']; - $ret['user_agent']['device_class_icon_big'] = $r['icon_big']; - $ret['user_agent']['device_class_info_url'] = "https://udger.com/resources/ua-list/device-detail?device=" . $r['name']; + if ($r = $q->fetchArray(SQLITE3_ASSOC)) { + $this->logger->debug("parse useragent string: device found by deviceclass"); + $deviceclass_id = $r['deviceclass_id']; + $ret['user_agent']['device_class'] = $r['name']; + $ret['user_agent']['device_class_code'] = $r['name_code']; + $ret['user_agent']['device_class_icon'] = $r['icon']; + $ret['user_agent']['device_class_icon_big'] = $r['icon_big']; + $ret['user_agent']['device_class_info_url'] = "https://udger.com/resources/ua-list/device-detail?device=" . $r['name']; + } + } + + // device marketname + if($ret['user_agent']['os_family_code']) { + $q = $this->dbdat->query("SELECT id,regstring FROM udger_devicename_regex WHERE + ((os_family_code='".$ret['user_agent']['os_family_code']."' AND os_code='-all-') + OR + (os_family_code='".$ret['user_agent']['os_family_code']."' AND os_code='".$ret['user_agent']['os_code']."')) + order by sequence"); + while ($r = $q->fetchArray(SQLITE3_ASSOC)) { + @preg_match($r["regstring"],$this->ua,$result); + + if(array_key_exists(1, $result)) { + $qC=$this->dbdat->query("SELECT marketname,brand_code,brand,brand_url,icon,icon_big + FROM udger_devicename_list + JOIN udger_devicename_brand ON udger_devicename_brand.id=udger_devicename_list.brand_id + WHERE regex_id=".$r["id"]." and code = '".trim($result[1])."' "); + + if($rC = $qC->fetchArray(SQLITE3_ASSOC)) { + $this->logger->debug("parse useragent string: device marketname found"); + $ret['user_agent']['device_marketname'] = $rC['marketname']; + $ret['user_agent']['device_brand'] = $rC['brand']; + $ret['user_agent']['device_brand_code'] = $rC['brand_code']; + $ret['user_agent']['device_brand_homepage'] = $rC['brand_url']; + $ret['user_agent']['device_brand_icon'] = $rC['icon']; + $ret['user_agent']['device_brand_icon_big'] = $rC['icon_big']; + $ret['user_agent']['device_brand_info_url'] = "https://udger.com/resources/ua-list/devices-brand-detail?brand=".$rC['brand_code']; + + break; + } + } + } + } + if($this->cacheEnable) { + $this->setCache( md5($this->ua) , serialize($ret['user_agent']) ); } } } @@ -445,15 +513,37 @@ public function parse() $ret['ip_address']['ip_classification_code'] = 'unrecognized'; } - if ($this->ipHelper->getIpVersion($ret['ip_address']['ip_ver']) === IPInterface::IPv4) { + if ($this->ipHelper->getIpVersion($ret['ip_address']['ip']) === IPInterface::IPv4) { - $ipLong = $this->ipHelper->getIpLongsprintf($ret['ip_address']['ip']); + $ipLong = $this->ipHelper->getIpLong($ret['ip_address']['ip']); $q = $this->dbdat->query("select name,name_code,homepage FROM udger_datacenter_range JOIN udger_datacenter_list ON udger_datacenter_range.datacenter_id=udger_datacenter_list.id where iplong_from <= " . $ipLong . " AND iplong_to >= " . $ipLong . " "); + if ($r = $q->fetchArray(SQLITE3_ASSOC)) { + $ret['ip_address']['datacenter_name'] = $r['name']; + $ret['ip_address']['datacenter_name_code'] = $r['name_code']; + $ret['ip_address']['datacenter_homepage'] = $r['homepage']; + } + } + else if ($this->ipHelper->getIpVersion($ret['ip_address']['ip']) === IPInterface::IPv6) { + $ipInt = $this->ipHelper->getIp6array($ret['ip_address']['ip']); + $q = $this->dbdat->query("select name,name_code,homepage + FROM udger_datacenter_range6 + JOIN udger_datacenter_list ON udger_datacenter_range6.datacenter_id=udger_datacenter_list.id + where + iplong_from0 <= ".$ipInt[0]." AND iplong_to0 >= ".$ipInt[0]." AND + iplong_from1 <= ".$ipInt[1]." AND iplong_to1 >= ".$ipInt[1]." AND + iplong_from2 <= ".$ipInt[2]." AND iplong_to2 >= ".$ipInt[2]." AND + iplong_from3 <= ".$ipInt[3]." AND iplong_to3 >= ".$ipInt[3]." AND + iplong_from4 <= ".$ipInt[4]." AND iplong_to4 >= ".$ipInt[4]." AND + iplong_from5 <= ".$ipInt[5]." AND iplong_to5 >= ".$ipInt[5]." AND + iplong_from6 <= ".$ipInt[6]." AND iplong_to6 >= ".$ipInt[6]." AND + iplong_from7 <= ".$ipInt[7]." AND iplong_to7 >= ".$ipInt[7]." + "); + if ($r = $q->fetchArray(SQLITE3_ASSOC)) { $ret['ip_address']['datacenter_name'] = $r['name']; $ret['ip_address']['datacenter_name_code'] = $r['name_code']; @@ -463,7 +553,7 @@ public function parse() } $this->logger->debug("parse IP address: END, unset IP address"); - $this->ua = ''; + $this->ip = ''; } return $ret; } @@ -475,10 +565,76 @@ protected function setDBdat() { if (is_null($this->dbdat)) { $this->logger->debug(sprintf("db: open file: %s", $this->path)); - $this->dbdat = new \SQLite3($this->path); + $this->dbdat = new \SQLite3($this->path, SQLITE3_OPEN_READONLY); } } - + + /** + * LRU cashe set + */ + protected function setCache($key, $value) { + $this->logger->debug('LRUcache: set to key' . $key); + $this->cache[$key] = $value; + if (count($this->cache) > $this->cacheSize) { + array_shift($this->cache); + } + } + + /** + * LRU cashe get + */ + protected function getCache($key) { + $this->logger->debug('LRUcache: get key' . $key); + if ( ! isset($this->cache[$key])) { + $this->logger->debug('LRUcache: key' . $key . ' Not Found' ); + return null; + } + // Put the value gotten to last. + $tmpValue = $this->cache[$key]; + unset($this->cache[$key]); + $this->cache[$key] = $tmpValue; + $this->logger->debug('LRUcache: key' . $key . ' Found' ); + return $tmpValue; + } + + /** + * Set LRU cache enable/disable + * + * @param bool + * @return bool + */ + public function setCacheEnable($set) + { + $this->cacheEnable = $set; + $log = $set ? 'true' : 'false'; + $this->logger->debug('LRUcache: enable/disable: ' . $log ); + return true; + } + + /** + * Set LRU cache enable/disable + * + * @param Int + * @return bool + */ + public function setCacheSize($size) + { + $this->cacheSize = $size; + $this->logger->debug('LRUcache: set size: ' . $size ); + return true; + } + /** + * Clear LRU cache + * + * @return bool + */ + public function clearCache() + { + $this->cache = array(); + $this->logger->debug('LRUcache: clear cache'); + return true; + } + /** * Set path to sqlite file * @@ -489,11 +645,7 @@ public function setDataFile($path) { if (false === file_exists($path)) { throw new \Exception(sprintf("%s does not exist", $path)); - } - - if (false === is_writable($path)) { - throw new \Exception(sprintf("%s is not writable", $path)); - } + } $this->path = $path;