From 41df51204c9da58160ea2a28f91f9ba35a66d144 Mon Sep 17 00:00:00 2001 From: Niels Leenheer Date: Tue, 8 Dec 2015 13:59:53 +0100 Subject: [PATCH] Built WhichBrowserLegacy from commit (unavailable) on WhichBrowser/WhichBrowser on branch (unavailable) --- .htaccess | 2 +- composer.json | 7 +- data/browsers-bots.php | 21 + data/browsers-chrome.php | 2 + data/build-android.php | 2 +- data/models-android.php | 56 ++- data/profiles.php | 59 +++ src/Analyser.php | 6 +- src/Analyser/Camouflage.php | 385 +++++++++--------- src/Analyser/Corrections.php | 14 +- src/Analyser/Header/BrowserId.php | 2 +- src/Analyser/Header/OperaMini.php | 6 +- src/Analyser/Header/UCBrowserNew.php | 74 +++- src/Analyser/Header/UCBrowserOld.php | 10 +- src/Analyser/Header/Useragent/Browser.php | 85 ++-- src/Analyser/Header/Useragent/Device/Cars.php | 12 +- .../Header/Useragent/Device/Ereader.php | 133 +++--- .../Header/Useragent/Device/Gaming.php | 183 ++++----- .../Header/Useragent/Device/Media.php | 11 +- .../Header/Useragent/Device/Mobile.php | 10 +- .../Header/Useragent/Device/Signage.php | 27 +- .../Header/Useragent/Device/Television.php | 8 +- src/Analyser/Header/Useragent/Engine.php | 1 - src/Analyser/Header/Useragent/Os.php | 13 +- src/Data/BrowserIds.php | 20 +- src/Data/BuildIds.php | 24 +- src/Data/DeviceModels.php | 2 - src/Model/Browser.php | 14 +- src/Model/Device.php | 31 +- src/Model/Engine.php | 4 - src/Model/Main.php | 66 +-- src/Model/Os.php | 13 +- src/Model/Primitive/Base.php | 21 +- src/Model/Primitive/NameVersion.php | 42 +- src/Model/Version.php | 33 +- 35 files changed, 853 insertions(+), 546 deletions(-) diff --git a/.htaccess b/.htaccess index a0da459..e8e192c 100644 --- a/.htaccess +++ b/.htaccess @@ -1,2 +1,2 @@ RewriteEngine on -RewriteRule ^detect.js$ detect.php +RewriteRule ^detect.js$ detect.php diff --git a/composer.json b/composer.json index af6c729..a1a7846 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,11 @@ { - "name": "whichbrowser/whichbrowser", + "name": "whichbrowser/legacy", "description": "Project containing the legacy version of WhichBrowser", + + "replace": { + "whichbrowser/whichbrowser": "^1.0|^2.0" + } + "keywords": ["useragent","browser"], "homepage": "http://whichbrowser.net", "license": "MIT", diff --git a/data/browsers-bots.php b/data/browsers-bots.php index 636a120..108438c 100644 --- a/data/browsers-bots.php +++ b/data/browsers-bots.php @@ -39,9 +39,11 @@ [ 'name' => 'Butterfly', 'regexp' => '/Butterfly\/([0-9.]*)/u' ], [ 'name' => 'CiteSeerX', 'regexp' => '/heritrix\/([0-9.]*)/u' ], [ 'name' => 'Cliqzbot', 'regexp' => '/Cliqzbot\/([0-9.]*)/u' ], + [ 'name' => 'CloudFare Always Online', 'regexp' => '/CloudFlare-AlwaysOnline\/([0-9.]*)/u' ], [ 'name' => 'CommaFeed', 'regexp' => '/CommaFeed\/([0-9.]*)/u' ], [ 'name' => 'CommonCrawl', 'regexp' => '/CCBot\/([0-9.]*)/u' ], [ 'name' => 'Data Hotel Watchdog', 'regexp' => '/Data-Hotel-Watchdog\/([0-9.]*)/u' ], + [ 'name' => 'Exabot Thumbnails', 'regexp' => '/Exabot-Thumbnails/u' ], [ 'name' => 'ExactSeek', 'regexp' => '/ExactSeek Crawler/u' ], [ 'name' => 'Ezooms Crawler', 'regexp' => '/Ezooms\/([0-9.]*)/u' ], [ 'name' => 'Facebook', 'regexp' => '/facebookplatform\/([0-9.]*)/u' ], @@ -59,12 +61,16 @@ [ 'name' => 'Feedly', 'regexp' => '/MetaFeedly\/([0-9.]*)/u' ], [ 'name' => 'Feedspot', 'regexp' => '/Feedspot/u' ], [ 'name' => 'FeedValidator', 'regexp' => '/FeedValidator\/([0-9.]*)/u' ], + [ 'name' => 'FeedZirra', 'regexp' => '/feedzirra/u' ], [ 'name' => 'Fever', 'regexp' => '/Fever\/([0-9.]*)/u' ], [ 'name' => 'Flamingo Search', 'regexp' => '/Flamingo_SearchEngine/u' ], [ 'name' => 'FTRF: Friendly Robot', 'regexp' => '/FTRF: Friendly robot\/([0-9.]*)/u' ], [ 'name' => 'Genieo Web Filter', 'regexp' => '/Genieo\/([0-9.]*)/u' ], + [ 'name' => 'GNIP', 'regexp' => '/UnwindFetchor\/([0-9.]*)/u' ], [ 'name' => 'Gocrawl', 'regexp' => '/Googlebot \(gocrawl v([0-9.]*)\)/u' ], [ 'name' => 'Goo', 'regexp' => '/ichiro\/mobile goo/u' ], + [ 'name' => 'Goo Blog Search', 'regexp' => '/gooblogsearch\/([0-9.]*)/u' ], + [ 'name' => 'Goo RSS Reader', 'regexp' => '/gooRSSreader([0-9.]*)/u' ], [ 'name' => 'Googlebot', 'regexp' => '/Google[Bb]ot\/([0-9.]*)/u' ], [ 'name' => 'Googlebot Mobile', 'regexp' => '/Googlebot-Mobile\/([0-9.]*)/u' ], [ 'name' => 'Googlebot Image', 'regexp' => '/Googlebot-Image\/([0-9.]*)/u' ], @@ -83,6 +89,9 @@ [ 'name' => 'Google Wireless Transcoder', 'regexp' => '/Google Wireless Transcoder/u' ], [ 'name' => 'Google Play Newsstand', 'regexp' => '/GoogleProducer/u' ], [ 'name' => 'Grub', 'regexp' => '/grub-client-([0-9.]*)/u' ], + [ 'name' => 'Hatena Antenna', 'regexp' => '/Hatena Antenna\/([0-9.]*)/u' ], + [ 'name' => 'Hatena Diary', 'regexp' => '/Hatena Diary RSS Module/u' ], + [ 'name' => 'Hatena Pagetitle', 'regexp' => '/Hatena Pagetitle Agent\/([0-9.]*)/u' ], [ 'name' => 'HeartRails Capture', 'regexp' => '/HeartRails_Capture\/([0-9.]*)/u' ], [ 'name' => 'HTTPMon', 'regexp' => '/HTTPMon\/([0-9.]*)/u' ], [ 'name' => 'HubPages', 'regexp' => '/HubPages V([0-9.]*)/u' ], @@ -95,6 +104,7 @@ [ 'name' => 'Livedoor', 'regexp' => '/livedoor/u' ], [ 'name' => 'Magpie RSS', 'regexp' => '/MagpieRSS\/([0-9.]*)/u' ], [ 'name' => 'Mapian News Bot', 'regexp' => '/mapion-news-bot\/([0-9.]*)/u' ], + [ 'name' => 'Mixi', 'regexp' => '/mixi-check\/([0-9.]*)/u' ], [ 'name' => 'Monitor.us', 'regexp' => '/monitor.us/u' ], [ 'name' => 'Naver Yeti', 'regexp' => '/Yeti\/([0-9.]*)/u' ], [ 'name' => 'Netcraft Survey Bot', 'regexp' => '/Netcraft Web Server Survey/u' ], @@ -106,13 +116,19 @@ [ 'name' => 'NewsGator', 'regexp' => '/NewsGatorOnline\/([0-9.]*)/u' ], [ 'name' => 'OpenWebSpider', 'regexp' => '/OpenWebSpider v([0-9.]*)/u' ], [ 'name' => 'OrangeBot', 'regexp' => '/OrangeBot-Collector\/([0-9.]*)/u' ], + [ 'name' => 'Picsearch bot', 'regexp' => '/psbot-page/u' ], [ 'name' => 'Pingdom', 'regexp' => '/Pingdom.com_bot_version_([0-9.]*)/u' ], [ 'name' => 'Pinterest', 'regexp' => '/Pinterest\/([0-9.]*)/u' ], [ 'name' => 'PostRank', 'regexp' => '/PostRank\/([0-9.]*)/u' ], [ 'name' => 'PowerMapper', 'regexp' => '/CrawlerProcess \(http:\/\/www\.PowerMapper\.com\) \/([0-9.]*)/u' ], + [ 'name' => 'Radian 6', 'regexp' => '/R6_FeedFetcher/u' ], + [ 'name' => 'Radian 6', 'regexp' => '/R6_CommentReader/u' ], + [ 'name' => 'RssBar', 'regexp' => '/RssBar\/([0-9.]*)/u' ], [ 'name' => 'QuerySeekerSpider', 'regexp' => '/QuerySeekerSpider\/([0-9.]*)/u' ], [ 'name' => 'Scrapy', 'regexp' => '/Scrapy\/([0-9.]*)/u' ], + [ 'name' => 'ScreenerBot', 'regexp' => '/ScreenerBot Crawler Beta ([0-9.]*)/u' ], [ 'name' => 'ShopWiki', 'regexp' => '/ShopWiki\/([0-9.]*)/u' ], + [ 'name' => 'SilverReader', 'regexp' => '/SilverReader\/([0-9.]*)/u' ], [ 'name' => 'SimplePie', 'regexp' => '/SimplePie\/([0-9.]*)/u' ], [ 'name' => 'Sogou Web Spider', 'regexp' => '/sogou spider/u' ], [ 'name' => 'Sogou Web Spider', 'regexp' => '/Sogou pic spider\/([0-9.]*)/u' ], @@ -120,8 +136,12 @@ [ 'name' => 'Sogou Web Spider', 'regexp' => '/Sogou web spider\/([0-9.]*)/u' ], [ 'name' => 'Soso Web Spider', 'regexp' => '/Sosospider\/([0-9.]*)/u' ], [ 'name' => 'Soso Web Spider', 'regexp' => '/Sosospider/u' ], + [ 'name' => 'Spinn3r', 'regexp' => '/Spinn3r ([0-9.]*)/iu' ], + [ 'name' => 'Summify', 'regexp' => '/Summify\/([0-9.]*)/u' ], + [ 'name' => 'Twisted PageGetter', 'regexp' => '/Twisted PageGetter/u' ], [ 'name' => 'Twitterbot', 'regexp' => '/Twitterbot\/([0-9.]*)/u' ], [ 'name' => 'Tiny Tiny RSS', 'regexp' => '/Tiny Tiny RSS\/([0-9.]*)/u' ], + [ 'name' => 'Typhoeus', 'regexp' => '/Typhoeus/u' ], [ 'name' => 'Voilabot', 'regexp' => '/Voila[Bb]ot/u' ], [ 'name' => 'VocusBot', 'regexp' => '/VocusBot ([0-9.]*)/u' ], [ 'name' => 'W3C CSS Validator', 'regexp' => '/Jigsaw\/([0-9.]*)/u' ], @@ -132,6 +152,7 @@ [ 'name' => 'W3C Markup Validator', 'regexp' => '/W3C_Validator\/([0-9.]*)/u' ], [ 'name' => 'WebbCrawler', 'regexp' => '/WebbCrawler ([0-9.]*)/u' ], [ 'name' => 'WordPress', 'regexp' => '/WordPress\/([0-9.]*)/u' ], + [ 'name' => 'WWW Mechanize', 'regexp' => '/WWW-Mechanize\/([0-9.]*)/u' ], [ 'name' => 'YaCy Bot', 'regexp' => '/yacybot/u' ], [ 'name' => 'Yandex Anti Virus', 'regexp' => '/YandexAntivirus\/([0-9.]*)/u' ], [ 'name' => 'Yandex Blogs', 'regexp' => '/YandexBlogs\/([0-9.]*)/u' ], diff --git a/data/browsers-chrome.php b/data/browsers-chrome.php index 3f802b3..3e8ef9e 100644 --- a/data/browsers-chrome.php +++ b/data/browsers-chrome.php @@ -53,6 +53,7 @@ '44.0.2403' => 'stable', '45.0.2454' => 'stable', '46.0.2490' => 'stable', + '47.0.2526' => 'stable', ]; Chrome::$MOBILE = [ @@ -78,4 +79,5 @@ '44.0.2403' => 'stable', '45.0.2454' => 'stable', '46.0.2490' => 'stable', + '47.0.2526' => 'stable', ]; diff --git a/data/build-android.php b/data/build-android.php index 26f1de1..3696bef 100644 --- a/data/build-android.php +++ b/data/build-android.php @@ -132,7 +132,7 @@ 'LMY47Z' => '5.1.1', 'LMY48B' => '5.1.1', - 'MPZ44Q' => ['value' => '5.2', 'alias' => 'M'], + 'MPZ44Q' => ['value' => '6.0', 'alias' => 'M'], ]; // Source: http://source.android.com/source/build-numbers.html diff --git a/data/models-android.php b/data/models-android.php index 2c90cf4..dcea159 100644 --- a/data/models-android.php +++ b/data/models-android.php @@ -178,6 +178,7 @@ 'TCC8920 STB!' => [ 'Telechips', 'TCC8920 based device', DeviceType::DEVBOARD ], 'TCC893X!' => [ 'Telechips', 'TCC893X based device', DeviceType::DEVBOARD ], 'TCC8935 HDMI!' => [ 'Telechips', 'TCC8935 based device', DeviceType::DEVBOARD ], + 'TCC8975 STB!' => [ 'Telechips', 'TCC8975 based device', DeviceType::DEVBOARD ], 'OMAP' => [ 'Texas Instruments', 'OMAP based device', DeviceType::DEVBOARD ], 'OMAP SS' => [ 'Texas Instruments', 'OMAP based device', DeviceType::DEVBOARD ], 'LogicPD Zoom2' => [ 'Texas Instruments', 'OMAP based device', DeviceType::DEVBOARD ], @@ -2109,8 +2110,11 @@ 'Coolpad Y1' => [ 'Coolpad', 'Y1' ], 'Coolpad Y60!' => [ 'Coolpad', 'Y60' ], 'Coolpad Y70!' => [ 'Coolpad', 'Y70' ], + 'Coolpad Y71!' => [ 'Coolpad', 'Y71' ], 'Coolpad Y75!' => [ 'Coolpad', 'Y75' ], + 'Coolpad Y76!' => [ 'Coolpad', 'Y76' ], 'Coolpad Y80!' => [ 'Coolpad', 'Y80' ], + 'Coolpad Y82!' => [ 'Coolpad', 'Y82' ], 'CP3700A' => [ 'Coolpad', '3700' ], 'Coolpad 5010' => [ 'Coolpad', '5010' ], 'Coolpad 5108' => [ 'Coolpad', '5108' ], @@ -2125,12 +2129,14 @@ 'Coolpad 5218!' => [ 'Coolpad', '5218' ], 'Coolpad 5219' => [ 'Coolpad', '5219' ], 'Coolpad 5230!' => [ 'Coolpad', '5230' ], + 'Coolpad 5261!' => [ 'Coolpad', '5261' ], 'Coolpad 5263!' => [ 'Coolpad', '5263' ], 'Coolpad 5310' => [ 'Coolpad', '5310' ], 'Coolpad 5311' => [ 'Coolpad', '5311' ], 'Coolpad 5313' => [ 'Coolpad', '5313' ], 'Coolpad 5313S' => [ 'Coolpad', '5313S' ], 'Coolpad 5316' => [ 'Coolpad', '5316' ], + 'Coolpad 5360' => [ 'Coolpad', '5360' ], '5560S' => [ 'Coolpad', '5560S' ], 'Coolpad 5820' => [ 'Coolpad', '5820' ], '5832' => [ 'Coolpad', '5832' ], @@ -2221,6 +2227,7 @@ 'Coolpad F1 8297W' => [ 'Coolpad', 'Dashen F1' ], 'Coolpad 8670' => [ 'Coolpad', 'Note 8670' ], 'Coolpad 8675!' => [ 'Coolpad', 'Dashen F2' ], + 'Coolpad 8676!' => [ 'Coolpad', 'Note 3 8676' ], 'Coolpad 8690' => [ 'Coolpad', 'Dashen X7' ], 'Coolpad 8702' => [ 'Coolpad', '8702' ], 'Coolpad 8705' => [ 'Coolpad', '8705' ], @@ -3556,7 +3563,9 @@ 'Highscreen Spark' => [ 'Highscreen', 'Spark' ], 'ZeraF' => [ 'Highscreen', 'Zera F' ], 'Zera F' => [ 'Highscreen', 'Zera F' ], + 'Zera f rev.S' => [ 'Highscreen', 'Zera F' ], 'Zera S' => [ 'Highscreen', 'Zera S' ], + 'Zera S Rev.S' => [ 'Highscreen', 'Zera S' ], 'Zera-S-Power' => [ 'Highscreen', 'Zera S Power' ], 'HLV-T!!' => [ @@ -4360,13 +4369,14 @@ 'S8-701u' => [ 'Huawei', 'MediaPad T1', DeviceType::TABLET ], 'T1-A21L' => [ 'Huawei', 'MediaPad T1', DeviceType::TABLET ], 'T1-701u' => [ 'Huawei', 'MediaPad T1', DeviceType::TABLET ], + 'T1-701ua' => [ 'Huawei', 'MediaPad T1', DeviceType::TABLET ], + 'S8-701w' => [ 'Huawei', 'MediaPad T1', DeviceType::TABLET ], 'MediaPad T1 8.0 Pro' => [ 'Huawei', 'MediaPad T1 Pro', DeviceType::TABLET ], 'MediaPad X1 7.0' => [ 'Huawei', 'MediaPad X1', DeviceType::TABLET ], 'X1 7.0' => [ 'Huawei', 'MediaPad X1', DeviceType::TABLET ], 'MediaPad X1' => [ 'Huawei', 'MediaPad X1', DeviceType::TABLET ], 'MediaPad 7D' => [ 'Huawei', 'MediaPad X1', DeviceType::TABLET ], 'MediaPad X1 S 7.0' => [ 'Huawei', 'MediaPad X1 S', DeviceType::TABLET ], - 'S8-701w' => [ 'Huawei', 'Honor S8-701w', DeviceType::TABLET ], 'Huawei A199' => [ 'Huawei', 'A199' ], 'Huawei B199' => [ 'Huawei', 'B199' ], 'Huawei C199' => [ 'Huawei', 'C199' ], @@ -4421,7 +4431,7 @@ 'Z100-(L09|TL00)!' => [ 'Huawei', 'Ascend Mate 7' ], 'M200-(UL00)!' => [ 'Huawei', 'Mate 8' ], 'unknown M200-L09' => [ 'Huawei', 'Mate 8' ], - 'HUAWEI CRR-(L09|CL00|UL00)!' => [ 'Huawei', 'Mate S' ], + 'HUAWEI CRR-(L09|CL00|UL00|UL20)!' => [ 'Huawei', 'Mate S' ], 'Huawei S8520' => [ 'Huawei', 'S8520' ], 'Huawei S8600' => [ 'Huawei', 'S8600' ], 'Huawei T8100' => [ 'Huawei', 'T8100' ], @@ -4469,7 +4479,7 @@ 'HUAWEI U8951!' => [ 'Huawei', 'Ascend G510' ], 'Huawei ?U9000!' => [ 'Huawei', 'Ascend X' ], 'TIT-(AL00)!' => [ 'Huawei', 'Enjoy 5' ], - 'HUAWEI TIT-(AL00)!' => [ 'Huawei', 'Enjoy 5' ], + 'HUAWEI TIT-(AL00|U02)!' => [ 'Huawei', 'Enjoy 5' ], 'HUAWEI HONOR 2' => [ 'Huawei', 'Honor 2' ], 'Huawei U9508' => [ 'Huawei', 'Honor 2' ], 'Huawei ?U9508!' => [ 'Huawei', 'Honor 2 Quad-core' ], @@ -4487,7 +4497,7 @@ 'HUAWEI Honor 3c w' => [ 'Huawei', 'Honor 3C' ], 'CHM-(CL00|TL00H|TL00|U01|UL00)!' => [ 'Huawei', 'Honor Play 4C' ], 'SCL-(L001|L004|AL00|CL00|TL00H)!' => [ 'Huawei', 'Honor 4A' ], - 'HUAWEI SCL-(L04)!' => [ 'Huawei', 'Honor 4A' ], + 'HUAWEI SCL-(L03|L04)!' => [ 'Huawei', 'Honor 4A' ], 'CHE-(TL00|TL00H)!' => [ 'Huawei', 'Honor 4X' ], 'HW-Che1-CL10' => [ 'Huawei', 'Honor 4X' ], 'Che1-(L04|CL10|CL20)!' => [ 'Huawei', 'Honor 4X' ], @@ -5832,6 +5842,7 @@ 'YOGA Tablet 2-830LC' => [ 'Lenovo', 'Yoga Tablet 2 830LC', DeviceType::TABLET ], 'YOGA Tablet 2-1050F' => [ 'Lenovo', 'Yoga Tablet 2 1050F', DeviceType::TABLET ], 'YOGA Tablet 2-1050L' => [ 'Lenovo', 'Yoga Tablet 2 1050L', DeviceType::TABLET ], + 'YOGA Tablet 2-1050LC' => [ 'Lenovo', 'Yoga Tablet 2 1050LC', DeviceType::TABLET ], 'YOGA Tablet 2 Pro-1380F' => [ 'Lenovo', 'Yoga Tablet 2 Pro 1380F', DeviceType::TABLET ], 'YOGA Tablet 2 Pro-1380L' => [ 'Lenovo', 'Yoga Tablet 2 Pro 1380L', DeviceType::TABLET ], 'Lenovo A7' => [ 'Lenovo', 'Tab A7', DeviceType::TABLET ], @@ -5839,7 +5850,7 @@ 'Lenovo A10-70LC' => [ 'Lenovo', 'Tab A10', DeviceType::TABLET ], 'Lenovo 2 A7-30F' => [ 'Lenovo', 'Tab 2 A7', DeviceType::TABLET ], 'Lenovo 2 A7-30TC' => [ 'Lenovo', 'Tab 2 A7', DeviceType::TABLET ], - 'Tab2A7-10F' => [ 'Lenovo', 'Tab 2 A7', DeviceType::TABLET ], + 'Tab2A7-(10|20)!' => [ 'Lenovo', 'Tab 2 A7', DeviceType::TABLET ], 'Lenovo TAB 2 A7-30(F|GC|HC)!' => [ 'Lenovo', 'Tab 2 A7', DeviceType::TABLET ], 'Lenovo TAB 2 A8-50F' => [ 'Lenovo', 'Tab 2 A8', DeviceType::TABLET ], 'Lenovo TAB 2 A10-70(F|L)!' => [ 'Lenovo', 'Tab 2 A10', DeviceType::TABLET ], @@ -6458,6 +6469,7 @@ 'LG-VK410' => [ 'LG', 'G Pad 7.0', DeviceType::TABLET ], 'LG-VK700' => [ 'LG', 'G Pad 10.1', DeviceType::TABLET ], 'LG-VK810' => [ 'LG', 'G Pad 8.3', DeviceType::TABLET ], + 'LG-VK815' => [ 'LG', 'G Pad X 8.3', DeviceType::TABLET ], ], 'LG-VN[0-9]{3,3}!!' => [ @@ -6536,6 +6548,7 @@ 'VK700' => [ 'LG', 'G Pad 10.1', DeviceType::TABLET ], 'VK810 4G' => [ 'LG', 'G Pad 8.3', DeviceType::TABLET ], + 'VK815' => [ 'LG', 'G Pad X 8.3', DeviceType::TABLET ], 'VM670' => [ 'LG', 'Optimus V' ], 'VS[0-9]{3,3}!!' => [ @@ -7304,12 +7317,12 @@ 'XT10(49|50|52|53|55|56|58|60)!' => [ 'Motorola', 'Moto X' ], 'XT10(63|64|68|69|72|77|78|79)!' => [ 'Motorola', 'Moto G (2014)' ], 'XT1080!' => [ 'Motorola', 'Droid Ultra' ], - 'XT10(85|92|93|94|95|96|97)!' => [ 'Motorola', 'Moto X (2014)' ], + 'XT10(85|92|93|94|95|96|97|98)!' => [ 'Motorola', 'Moto X (2014)' ], 'XT11(00|03)!' => [ 'Motorola', 'Nexus 6' ], 'XT1115!' => [ 'Motorola', 'Moto X Pro' ], 'XT1225' => [ 'Motorola', 'Moto Maxx' ], 'XT12(50|54)!' => [ 'Motorola', 'Droid Turbo' ], - 'XT15(24|26|28)!' => [ 'Motorola', 'Moto E (2015)' ], + 'XT15(24|26|27|28)!' => [ 'Motorola', 'Moto E (2015)' ], 'XT15(40|41|42|43|44|48|50)!' => [ 'Motorola', 'Moto G (2015)' ], 'XT15(62|63)!' => [ 'Motorola', 'Moto X Play' ], 'XT1565' => [ 'Motorola', 'Droid MAXX 2' ], @@ -7317,7 +7330,7 @@ 'XT1575' => [ 'Motorola', 'Moto X Pure Edition' ], // 'XT1578' => [ 'Motorola', '"Clark"' ], 'XT1580' => [ 'Motorola', 'Moto X Force' ], -// 'XT1585' => [ 'Motorola', '"Kinzie"' ], + 'XT1585' => [ 'Motorola', 'Droid Turbo 2' ], '201M' => [ 'Motorola', 'Droid RAZR M' ], 'Atrix 2' => [ 'Motorola', 'ATRIX 2' ], 'Atrix 2 WeifanZ' => [ 'Motorola', 'ATRIX 2' ], @@ -7842,6 +7855,7 @@ 'OPPOX9015' => [ 'Oppo', 'Find X9015' ], 'X9017' => [ 'Oppo', 'Finder X9017' ], 'OPPOX9017' => [ 'Oppo', 'Finder X9017' ], + 'FIND7' => [ 'Oppo', 'Find 7 X9070' ], 'OPPO find7' => [ 'Oppo', 'Find 7 X9070' ], 'X9070' => [ 'Oppo', 'Find 7 X9070' ], 'X9076' => [ 'Oppo', 'Find 7 X9076' ], @@ -7930,6 +7944,7 @@ 'N51[11|17]!' => [ 'Oppo', 'N1 mini' ], 'N5207' => [ 'Oppo', 'N3' ], 'OPPO R7' => [ 'Oppo', 'R7' ], + 'OPPO R7s' => [ 'Oppo', 'R7s' ], 'OPPO R7 Plus' => [ 'Oppo', 'R7 Plus' ], 'A31c' => [ 'Oppo', 'A31c' ], 'W8' => [ 'Oppo', 'W8' ], @@ -8133,6 +8148,7 @@ ], 'PHICOMM!!' => [ + 'PHICOMM CLUE L' => [ 'Phicomm', 'Clue L' ], 'PHICOMM ENERGY M' => [ 'Phicomm', 'Energy M' ], 'PHICOMM C230v' => [ 'Phicomm', 'C230v' ], 'Phicomm C230w' => [ 'Phicomm', 'C230w' ], @@ -8482,6 +8498,7 @@ 'PMT3677 Wi' => [ 'Prestigio', 'Multipad Ultra+ 7.0', DeviceType::TABLET ], 'PMT5001 3G' => [ 'Prestigio', 'Multipad Muze 5001 3G', DeviceType::TABLET ], 'PMT5002 Wi' => [ 'Prestigio', 'Multipad Wize 5002', DeviceType::TABLET ], + 'PMT5008 3G' => [ 'Prestigio', 'Multipad Muze 5008 3G', DeviceType::TABLET ], 'PMT5287 4G' => [ 'Prestigio', 'Multipad Ranger 8.0 4G', DeviceType::TABLET ], 'PMT5487 3G' => [ 'Prestigio', 'Multipad Quantum 8.0 3G', DeviceType::TABLET ], 'PMT5587 Wi' => [ 'Prestigio', 'Multipad 8.0 HD', DeviceType::TABLET ], @@ -9405,7 +9422,9 @@ 'Galaxy S II' => [ 'Samsung', 'Galaxy S II' ], 'Galaxy S2' => [ 'Samsung', 'Galaxy S II' ], 'GalaxyS2' => [ 'Samsung', 'Galaxy S II' ], + 'Galaxy S2!' => [ 'Samsung', 'Galaxy S II' ], 'Galaxy S III' => [ 'Samsung', 'Galaxy S III' ], + 'GALAXY SIII' => [ 'Samsung', 'Galaxy S III' ], 'Galaxy S3' => [ 'Samsung', 'Galaxy S III' ], 'GalaxyS4' => [ 'Samsung', 'Galaxy S4' ], 'Galaxy S4' => [ 'Samsung', 'Galaxy S4' ], @@ -9415,6 +9434,7 @@ 'Galaxy S4 Mini GT-I9505' => [ 'Samsung', 'Galaxy S4 Mini' ], 'Galaxy S4 Zoom' => [ 'Samsung', 'Galaxy S4 Zoom' ], 'GALAXY S5' => [ 'Samsung', 'Galaxy S5' ], + 'Galaxy S5 Sprint' => [ 'Samsung', 'Galaxy S5' ], 'Galaxy S6' => [ 'Samsung', 'Galaxy S6' ], 'Galaxy S6 Edge' => [ 'Samsung', 'Galaxy S6 Edge' ], 'Galaxy X' => [ 'Samsung', 'Galaxy X' ], @@ -9428,6 +9448,9 @@ 'S2' => [ 'Samsung', 'Galaxy S II' ], 'S3' => [ 'Samsung', 'Galaxy S III' ], 'S4' => [ 'Samsung', 'Galaxy S4' ], + 'S5' => [ 'Samsung', 'Galaxy S5' ], + 'S5 Mini!' => [ 'Samsung', 'Galaxy S5 Mini' ], + 'S6 Edge+!' => [ 'Samsung', 'Galaxy S6 Edge+' ], 'Note III' => [ 'Samsung', 'Galaxy Note 3' ], 'Captivate-I897' => [ 'Samsung', 'Captivate' ], 'Aegis2' => [ 'Samsung', 'Stratosphere II' ], @@ -9441,6 +9464,7 @@ 'SC-01E' => [ 'Samsung', 'Galaxy Tab 7.7 Plus', DeviceType::TABLET ], 'SC-01F' => [ 'Samsung', 'Galaxy Note 3' ], 'SC-01G' => [ 'Samsung', 'Galaxy Note Edge' ], + 'SC-01H' => [ 'Samsung', 'Galaxy Active neo' ], 'SC-02B' => [ 'Samsung', 'Galaxy S' ], 'SC-02C' => [ 'Samsung', 'Galaxy S II' ], 'SC-02D' => [ 'Samsung', 'Galaxy Tab 7.0 Plus', DeviceType::TABLET ], @@ -9492,11 +9516,13 @@ 'S1005KTAB' => [ 'Serioux', 'GoTab S1005KTAB', DeviceType::TABLET ], 'STARXTREM' => [ 'SFR', 'STARXTREM' ], 'STARXTREM II' => [ 'SFR', 'STARXTREM II' ], + 'STARXTREM 4' => [ 'SFR', 'STARXTREM 4' ], 'Android edition by sfr STARADDICT' => [ 'SFR', 'STARADDICT' ], 'V961' => [ 'SFR', 'STARADDICT II' ], 'Smartphone Android by SFR STARADDICT II' => [ 'SFR', 'STARADDICT II' ], 'STARADDICT II Plus' => [ 'SFR', 'STARADDICT II Plus' ], 'STARADDICT III' => [ 'SFR', 'STARADDICT III' ], + 'STARADDICT 4' => [ 'SFR', 'STARADDICT 4' ], 'Android Edition Starnaute' => [ 'SFR', 'STARNAUTE' ], 'STARNAUTE II' => [ 'SFR', 'STARNAUTE II' ], 'Starshine' => [ 'SFR', 'STARSHINE' ], @@ -9952,6 +9978,7 @@ 'SO-03E' => [ 'Sony', 'Xperia Tablet Z', DeviceType::TABLET ], // Pollux 'SO-03F' => [ 'Sony', 'Xperia Z2' ], // Sirius 'SO-03G' => [ 'Sony', 'Xperia Z4' ], + 'SO-03H' => [ 'Sony', 'Xperia Z5 Premium' ], 'SO-04D' => [ 'Sony', 'Xperia GX' ], // Hayabusa 'SO-04E' => [ 'Sony', 'Xperia A' ], // Dogo 'SO-04EM' => [ 'Sony', 'Xperia feat. HATSUNE MIKU' ], @@ -10030,6 +10057,8 @@ 'Xperia Z1 Compact' => [ 'Sony', 'Xperia Z1 Compact' ], // Amami 'Xperia Z2' => [ 'Sony', 'Xperia Z2' ], // Sirius 'Xperia Z3' => [ 'Sony', 'Xperia Z3' ], // ... + 'Xperia Z3+' => [ 'Sony', 'Xperia Z3+' ], // ... + 'XPERIA Z3 Compact' => [ 'Sony', 'Xperia Z3 Compact' ], 'Xperia-Z' => [ 'Sony', 'Xperia Z' ], // Yuga 'Xperia-Z1' => [ 'Sony', 'Xperia Z1' ], // Honami 'Xperia™ C' => [ 'Sony', 'Xperia C' ], // Pelican @@ -10037,6 +10066,7 @@ 'Xperia™ Miku' => [ 'Sony', 'Xperia Feat. Hatsune Miku' ], // Dogo 'Xperia Tablet S' => [ 'Sony', 'Xperia Tablet S', DeviceType::TABLET ], 'Xperia Live with Walkman' => [ 'Sony Ericsson', 'Live with Walkman' ], // Coconut + 'Xperia Tablet Z' => [ 'Sony', 'Xperia Tablet Z', DeviceType::TABLET ], 'Xperia Tablet Z LTE' => [ 'Sony', 'Xperia Tablet Z', DeviceType::TABLET ], 'Xperia Tablet Z Wi-Fi' => [ 'Sony', 'Xperia Tablet Z', DeviceType::TABLET ], 'Xperia Z2 Tablet Wifi' => [ 'Sony', 'Xperia Tablet Z2', DeviceType::TABLET ], @@ -10144,6 +10174,7 @@ 'Mi-516' => [ 'Spice', 'Mi-516 Stellar' ], 'Spice Mi-519' => [ 'Spice', 'Mi-519 Stellar' ], 'SpiceMI-520' => [ 'Spice', 'Mi-520 Stellar' ], + 'SpiceMI-520N' => [ 'Spice', 'Mi-520 Stellar' ], 'Spice Mi-525' => [ 'Spice', 'Mi-525 Stellar Pinnacle FHD' ], 'Spice Mi-526' => [ 'Spice', 'Mi-526 Stellar' ], 'Spice Mi-530' => [ 'Spice', 'Mi-530 Stellar Pinnacle' ], @@ -11149,6 +11180,7 @@ 'vivo X520L' => [ 'Vivo', 'Xplay 3S' ], 'vivo Xplay3S' => [ 'Vivo', 'Xplay 3S' ], 'vivo Xplay3S A' => [ 'Vivo', 'Xplay 3S' ], + 'vivo X710F' => [ 'Vivo', 'Xshot' ], 'vivo X710L' => [ 'Vivo', 'Xshot' ], 'vivo Xshot' => [ 'Vivo', 'Xshot' ], 'vivo Xshoot' => [ 'Vivo', 'Xshot' ], @@ -11177,6 +11209,7 @@ 'vivo Y22T' => [ 'Vivo', 'Y22T' ], 'vivo Y23L' => [ 'Vivo', 'Y23L' ], 'vivo Y27' => [ 'Vivo', 'Y27' ], + 'vivo Y27L' => [ 'Vivo', 'Y27L' ], 'vivo Y28' => [ 'Vivo', 'Y28' ], 'vivo Y28L' => [ 'Vivo', 'Y28L' ], 'vivo Y29L' => [ 'Vivo', 'Y29L' ], @@ -11589,6 +11622,8 @@ 'YEZZ-4E' => [ 'Yezz', 'Andy 4E' ], 'Andy 4E' => [ 'Yezz', 'Andy 4E' ], 'Andy 4EI' => [ 'Yezz', 'Andy 4EI' ], + 'ANDY 5EI' => [ 'Yezz', 'Andy 5EI' ], + 'Yezz-ANDY5EL' => [ 'Yezz', 'Andy 5EL' ], 'C868' => [ 'Yicheer', 'C868' ], 'DEM752NC' => [ 'Yifang', 'M752' ], 'EMR1879' => [ 'Yidong', 'EMR1879', DeviceType::TABLET ], @@ -11708,6 +11743,7 @@ 'ZTE Blade Apex2' => [ 'ZTE', 'Blade Apex2' ], 'ZTE Blade A430' => [ 'ZTE', 'Blade A430' ], 'ZTE Blade A450' => [ 'ZTE', 'Blade A450' ], + 'ZTE Blade A570' => [ 'ZTE', 'Blade A570' ], 'ZTE BLADE C' => [ 'ZTE', 'Blade C' ], 'ZTE Blade C2 Plus' => [ 'ZTE', 'Blade C2 Plus' ], 'ZTE Blade C310' => [ 'ZTE', 'Blade C310' ], @@ -11801,6 +11837,7 @@ 'ZTE Q507T' => [ 'ZTE', 'Q507T' ], 'ZTE Q508U' => [ 'ZTE', 'Q508U' ], 'ZTE Q509T' => [ 'ZTE', 'Q509T' ], + 'ZTE Q529C' => [ 'ZTE', 'Q529C' ], 'ZTE Q529E' => [ 'ZTE', 'Q529E' ], 'ZTE Q529T' => [ 'ZTE', 'Q529T' ], 'ZTE C N600!' => [ 'ZTE', 'N600' ], @@ -12107,7 +12144,10 @@ '003Z' => [ 'ZTE', 'Softbank 003Z' ], '008Z' => [ 'ZTE', 'Softbank 008Z' ], '009Z' => [ 'ZTE', 'Softbank Star7' ], + 'ZTE A2015' => [ 'ZTE', 'A2015' ], 'ZTE A2016' => [ 'ZTE', 'A2016' ], + 'ZTE B2015' => [ 'ZTE', 'B2015' ], + 'ZTE C2016' => [ 'ZTE', 'C2016' ], 'ZTE STAR' => [ 'ZTE', 'Star 1' ], 'ZTE S2004' => [ 'ZTE', 'Tianji 3' ], 'ZTE S2005' => [ 'ZTE', 'Star 2' ], diff --git a/data/profiles.php b/data/profiles.php index 675675a..367dd45 100644 --- a/data/profiles.php +++ b/data/profiles.php @@ -93,6 +93,7 @@ 'http://www-ccpp.tcl-ta.com/files/ALCATEL_A206G.rdf' => [ 'Alcatel', 'A206G', null, DeviceType::MOBILE ], 'http://www-ccpp.tcl-ta.com/files/ALCATEL_A383G.rdf' => [ 'Alcatel', 'A383G', null, DeviceType::MOBILE ], 'http://www-ccpp.tcl-ta.com/files/ALCATEL_A392G.rdf' => [ 'Alcatel', 'A392G', null, DeviceType::MOBILE ], + 'http://www-ccpp.tcl-ta.com/files/ALCATEL_A392T.rdf' => [ 'Alcatel', 'A392T', null, DeviceType::MOBILE ], 'http://www-ccpp.tcl-ta.com/files/A480G.xml' => [ 'Alcatel', 'A480G', 'Android', DeviceType::MOBILE ], 'http://www-ccpp-mpd.alcatel.com/files/ALCATEL-BF4_2.0.rdf' => [ 'Alcatel', 'BF4', null, DeviceType::MOBILE ], 'http://www-ccpp-mpd.alcatel.com/files/ALCATEL-BF5_1.0.rdf' => [ 'Alcatel', 'BF5', null, DeviceType::MOBILE ], @@ -263,6 +264,7 @@ 'http://www-ccpp.tcl-ta.com/files/ALCATELOneTouch4023X.xml' => [ 'Alcatel', 'One Touch Pixi 3 (3.5)', 'Firefox OS', DeviceType::MOBILE ], 'http://www-ccpp.tcl-ta.com/files/ONE_TOUCH_4014D.xml' => [ 'Alcatel', 'One Touch Pixi 3 (4)', 'Android', DeviceType::MOBILE ], 'http://www-ccpp.tcl-ta.com/files/5065D.xml' => [ 'Alcatel', 'One Touch Pixi 3 (5)', 'Android', DeviceType::MOBILE ], + 'http://www-ccpp.tcl-ta.com/files/5054O.xml' => [ 'Alcatel', 'One Touch Pixi 3 (5.5)', 'Android', DeviceType::MOBILE ], 'http://www-ccpp.tcl-ta.com/files/4045A.xml' => [ 'Alcatel', 'One Touch Pop 2 (4)', 'Android', DeviceType::MOBILE ], 'http://www-ccpp.tcl-ta.com/files/5042A.xml' => [ 'Alcatel', 'One Touch Pop 2 (4.5)', 'Android', DeviceType::MOBILE ], 'http://www-ccpp.tcl-ta.com/files/5042D.xml' => [ 'Alcatel', 'One Touch Pop 2 (4.5)', 'Android', DeviceType::MOBILE ], @@ -543,6 +545,7 @@ 'http://www.bluhelp.com/upload/xmlfiles/STUDIO5.5S.xml' => [ 'BLU', 'Studio 5.5s', 'Android', DeviceType::MOBILE ], 'http://www.bluhelp.com/upload/xmlfiles/STUDIO_G.xml' => [ 'BLU', 'Studio G', 'Android', DeviceType::MOBILE ], 'http://www.bluhelp.com/upload/xmlfiles/STUDIO5.0S_HD.xml' => [ 'BLU', 'Studio X', 'Android', DeviceType::MOBILE ], + 'http://www.bluhelp.com/upload/xmlfiles/STUDIO_X.xml' => [ 'BLU', 'Studio X', 'Android', DeviceType::MOBILE ], 'http://www.bluhelp.com/upload/xmlfiles/Touchbook_7.0_3G.xml' => [ 'BLU', 'Touch Book 7.0', 'Android', DeviceType::TABLET ], 'http://www.bmobile.eu.com/uaprofile/Bmobile_AX1030.xml' => [ 'Bmobile', 'AX1030', 'Android', DeviceType::MOBILE ], 'http://www.bmobile.eu.com/uaprofile/Bmobile_AX1060.xml' => [ 'Bmobile', 'AX1060', 'Android', DeviceType::MOBILE ], @@ -829,6 +832,7 @@ 'http://device.sprintpcs.com/HTC/0PCV1-VIRGIN/1426521.rdf' => [ 'HTC', 'Desire 510', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/HTC/0PCV1-VIRGIN/1476521.rdf' => [ 'HTC', 'Desire 510', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/HTC/0PCV1-VIRGIN/1486522.rdf' => [ 'HTC', 'Desire 510', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/HTC/0PCV1-VIRGIN/1496523.rdf' => [ 'HTC', 'Desire 510', 'Android', DeviceType::MOBILE ], 'http://www.htcmms.com.tw/Android/ATT/7l3xFmWvDC/ua-profile.xml' => [ 'HTC', 'Desire 510', 'Android', DeviceType::MOBILE ], 'http://www.htcmms.com.tw/Android/BM/7l3xFmWvDC/ua-profile.xml' => [ 'HTC', 'Desire 510', 'Android', DeviceType::MOBILE ], 'http://www.htcmms.com.tw/Android/Common/R183PSZ1oa/ua-profile.xml' => [ 'HTC', 'Desire 510', 'Android', DeviceType::MOBILE ], @@ -1561,6 +1565,7 @@ 'http://wap1.huawei.com/uaprof/HUAWEI_CHC-U03_UAProfile.xml' => [ 'Huawei', 'Ascend G650', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_HUAWEI_G660-L075.xml' => [ 'Huawei', 'Ascend G660', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_%s_UAProfile.xml' => [ 'Huawei', 'Ascend G7', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/HUAWEI_G7-L01_OrangeUAProfile.xml' => [ 'Huawei', 'Ascend G7', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_G7-L01_UAProfile.xml' => [ 'Huawei', 'Ascend G7', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_G7-L03_UAProfile.xml' => [ 'Huawei', 'Ascend G7', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_G7-TL00_UAProfile.xml' => [ 'Huawei', 'Ascend G7', 'Android', DeviceType::MOBILE ], @@ -1649,6 +1654,7 @@ 'http://wap1.huawei.com/uaprof/HUAWEI_GRA_L09_DRM_UAProfile.xml' => [ 'Huawei', 'Ascend P8', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_GRA_L09_UAProfile.xml' => [ 'Huawei', 'Ascend P8', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_GRA_L09_VDF_UAProfile_3G.xml' => [ 'Huawei', 'Ascend P8', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/HUAWEI_X100-UL00_UAProfile.xml' => [ 'Huawei', 'Ascend P8', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_HUAWEI_GRA-CL00_1_20150317.xml' => [ 'Huawei', 'Ascend P8', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_HUAWEI_GRA-CL10_1_20150317.xml' => [ 'Huawei', 'Ascend P8', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_M100-CL00_1_20150120.xml' => [ 'Huawei', 'Ascend P8', 'Android', DeviceType::MOBILE ], @@ -1657,6 +1663,7 @@ 'http://wap1.huawei.com/uaprof/HUAWEI_ALE-L04_5.1_UAProfile.xml' => [ 'Huawei', 'Ascend P8 Lite', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_ALE-L21_DRM_UAProfile.xml' => [ 'Huawei', 'Ascend P8 Lite', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_ALE-L21_FT_UAProfile.xml' => [ 'Huawei', 'Ascend P8 Lite', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/HUAWEI_ALE-L21_PL_UAProfile.xml' => [ 'Huawei', 'Ascend P8 Lite', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_ALE-L21_UAProfile.xml' => [ 'Huawei', 'Ascend P8 Lite', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_ALE-L23_NLA_UAProfile.xml' => [ 'Huawei', 'Ascend P8 Lite', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_ALE-L23_UAProfile.xml' => [ 'Huawei', 'Ascend P8 Lite', 'Android', DeviceType::MOBILE ], @@ -1706,6 +1713,7 @@ 'http://wap1.huawei.com/uaprof/HuaweiY221-U03_UAProfile.xml' => [ 'Huawei', 'Ascend Y221', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HuaweiY221-U12_UAProfile.xml' => [ 'Huawei', 'Ascend Y221', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HuaweiY221-U22_UAProfile.xml' => [ 'Huawei', 'Ascend Y221', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/OrinoquiaAuyantepui+Y221-U03_UAProfile.xml' => [ 'Huawei', 'Ascend Y221', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HuaweiY300-0000GPRS-UNICOM.xml' => [ 'Huawei', 'Ascend Y300', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HuaweiY300-0000GPRS.xml' => [ 'Huawei', 'Ascend Y300', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HuaweiY300-0100GPRS-FL.xml' => [ 'Huawei', 'Ascend Y300', 'Android', DeviceType::MOBILE ], @@ -1742,6 +1750,7 @@ 'http://wap1.huawei.com/uaprof/HuaweiY340-U081-Normal.xml' => [ 'Huawei', 'Ascend Y340', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/Y360-U03_UAProfile.xml' => [ 'Huawei', 'Ascend Y360', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/Y360-U23_UAProfile.xml' => [ 'Huawei', 'Ascend Y360', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/Y360-U31_UAProfile.xml' => [ 'Huawei', 'Ascend Y360', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/Y360-U61_UAProfile.xml' => [ 'Huawei', 'Ascend Y360', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_Y511-U00.xml' => [ 'Huawei', 'Ascend Y511', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_Y511-U10.xml' => [ 'Huawei', 'Ascend Y511', 'Android', DeviceType::MOBILE ], @@ -1788,6 +1797,7 @@ 'http://wap1.huawei.com/uaprof/HUAWEI_Y635-L03_UAProfile_DRM.xml' => [ 'Huawei', 'Ascend Y635', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_Y635-L21_UAProfile.xml' => [ 'Huawei', 'Ascend Y635', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_Y635-L21_UAProfile_EUROPE.xml' => [ 'Huawei', 'Ascend Y635', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/HUAWEI_Y635-TL00_UAProfile.xml' => [ 'Huawei', 'Ascend Y635', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_HUAWEI_Y635-CL00_1_20140930.xml' => [ 'Huawei', 'Ascend Y635', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_HUAWEI_B199.xml' => [ 'Huawei', 'B199', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_HUAWEI_B199_1_20130806.xml' => [ 'Huawei', 'B199', 'Android', DeviceType::MOBILE ], @@ -1815,6 +1825,7 @@ 'http://wap1.huawei.com/uaprof/HuaweiC8850v100CDMA.xml' => [ 'Huawei', 'C8850', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HuaweiU8687-Normal.xml' => [ 'Huawei', 'Chronos', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_TIT-AL00_UAProfile .xml' => [ 'Huawei', 'Enjoy 5', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/HUAWEI_TIT-U02_UAProfile .xml' => [ 'Huawei', 'Enjoy 5', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_HUAWEI_CM990_1_20130108.xml' => [ 'Huawei', 'Evolución 3', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HuaweiUM840v100GPRS.xml' => [ 'Huawei', 'Evolution', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HuaweiUM840v100WCDMA.xml' => [ 'Huawei', 'Evolution', 'Android', DeviceType::MOBILE ], @@ -1862,6 +1873,7 @@ 'http://wap1.huawei.com/uaprof/HW_SCL-CL00_1_20150420.xml' => [ 'Huawei', 'Honor 4A', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_SCL-L01_Europe_DRM-UAProfile.xml' => [ 'Huawei', 'Honor 4A', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_SCL-L01_UAProfile.xml' => [ 'Huawei', 'Honor 4A', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/HW_SCL-L03_UAProfile-DRM.xml' => [ 'Huawei', 'Honor 4A', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_SCL-L04_UAProfile.xml' => [ 'Huawei', 'Honor 4A', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_SCL-L04_UAProfile_1MB.xml' => [ 'Huawei', 'Honor 4A', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_SCL-TL00H_UAProfile.xml' => [ 'Huawei', 'Honor 4A', 'Android', DeviceType::MOBILE ], @@ -1887,6 +1899,7 @@ 'http://wap1.huawei.com/uaprof/HUAWEI_Che2-UL00_UAProfile.xml' => [ 'Huawei', 'Honor 4X', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_HUAWEI_Che1-CL10_1_20140801.xml' => [ 'Huawei', 'Honor 4X', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_HUAWEI_Che1-CL20.xml' => [ 'Huawei', 'Honor 4X', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/HW_KIW-AL10_UAProfile.xml' => [ 'Huawei', 'Honor 5X', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_KIW-CL00_1_20150425.xml' => [ 'Huawei', 'Honor 5X', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_KIW-TL00H_UAProfile.xml' => [ 'Huawei', 'Honor 5X', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_H60_J1_UAProfile.xml' => [ 'Huawei', 'Honor 6', 'Android', DeviceType::MOBILE ], @@ -1974,6 +1987,7 @@ 'http://wap1.huawei.com/uaprof/HUAWEI_CRR_L09_UAProfile.xml' => [ 'Huawei', 'Mate 8', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_M200_L09_UAProfile.xml' => [ 'Huawei', 'Mate 8', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_CRR-UL00_UAProfile.xml' => [ 'Huawei', 'Mate S', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/HUAWEI_CRR-UL20_UAProfile.xml' => [ 'Huawei', 'Mate S', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_CRR_L09_UAProfile_3G.xml' => [ 'Huawei', 'Mate S', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HW_CRR-CL00_1_20150310.xml' => [ 'Huawei', 'Mate S', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HuaweiMediaPadEVDODataOnly.xml' => [ 'Huawei', 'MediaPad', 'Android', DeviceType::TABLET ], @@ -2001,6 +2015,7 @@ 'http://wap1.huawei.com/uaprof/HuaweiMediaPad_S7-72Xu.xml' => [ 'Huawei', 'MediaPad 7 Youth 2', 'Android', DeviceType::TABLET ], 'http://wap1.huawei.com/uaprof/HuaweiMediaPad_S8-301L.xml' => [ 'Huawei', 'MediaPad 8 Vogue', 'Android', DeviceType::TABLET ], 'http://wap1.huawei.com/uaprof/HuaweiMediaPad_S8-301u.xml' => [ 'Huawei', 'MediaPad M1', 'Android', DeviceType::TABLET ], + 'http://wap1.huawei.com/uaprof/HuaweiMediaPad_S8-301u_4_4.xml' => [ 'Huawei', 'MediaPad M1', 'Android', DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HuaweiMediaPad_S8-301w.xml' => [ 'Huawei', 'MediaPad M1', 'Android', DeviceType::TABLET ], 'http://wap1.huawei.com/uaprof/HuaweiMediaPad_S8-301L_4_4.xml' => [ 'Huawei', 'MediaPad M1 403HW', 'Android', DeviceType::TABLET ], 'http://wap1.huawei.com/uaprof/LST.xml' => [ 'Huawei', 'MediaPad M2', 'Android', DeviceType::TABLET ], @@ -2009,6 +2024,7 @@ 'http://wap1.huawei.com/uaprof/HuaweiMediaPad_S8-701w.xml' => [ 'Huawei', 'MediaPad T1', 'Android', DeviceType::TABLET ], 'http://wap1.huawei.com/uaprof/HuaweiMediapad_S8-70Xu.xml' => [ 'Huawei', 'MediaPad T1', 'Android', DeviceType::TABLET ], 'http://wap1.huawei.com/uaprof/HuaweiMediapad_T1-701u.xml' => [ 'Huawei', 'Mediapad T1', 'Android', DeviceType::MOBILE ], + 'http://wap1.huawei.com/uaprof/HuaweiMediapad_T1-701ua.xml' => [ 'Huawei', 'MediaPad T1', 'Android', DeviceType::TABLET ], 'http://wap1.huawei.com/uaprof/HuaweiMediapad_T1-702u.xml' => [ 'Huawei', 'MediaPad T1', 'Android', DeviceType::TABLET ], 'http://wap1.huawei.com/uaprof/HuaweiMediaPad_T1-821L.xml' => [ 'Huawei', 'MediaPad T1', 'Android', DeviceType::TABLET ], 'http://wap1.huawei.com/uaprof/HuaweiMediaPad_T1-A21L.xml' => [ 'Huawei', 'MediaPad T1', 'Android', DeviceType::TABLET ], @@ -2056,6 +2072,7 @@ 'http://wap1.huawei.com/uaprof/HUAWEI_U2800A_UAProfile.xml' => [ 'Huawei', 'U2800', null, DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_U2801_UAProfile.xml' => [ 'Huawei', 'U2801', 'Brew', DeviceType::MOBILE ], 'http://wap.huawei.com/uaprof/HuaweiU3100v100UNIWCDMA.xml' => [ 'Huawei', 'U3100', null, DeviceType::MOBILE ], + 'http://wap.huawei.com/uaprof/HuaweiU3205v100WCDMA.xml' => [ 'Huawei', 'U3205', null, DeviceType::MOBILE ], 'http://wap.huawei.com/uaprof/HuaweiU3300v100GPRS.xml' => [ 'Huawei', 'U3300', null, DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_U3900_ATTNormal.xml' => [ 'Huawei', 'U3900', null, DeviceType::MOBILE ], 'http://wap1.huawei.com/uaprof/HUAWEI_U5120_UAProfile.xml' => [ 'Huawei', 'U5120', null, DeviceType::MOBILE ], @@ -2510,9 +2527,11 @@ 'http://device.sprintpcs.com/LG/LS996-SPRINT/LS996ZV6.rdf' => [ 'LG', 'G Flex 2', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/LG/LS996-SPRINT/LS996ZV7.rdf' => [ 'LG', 'G Flex 2', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/LG/LS996-SPRINT/LS996ZV8.rdf' => [ 'LG', 'G Flex 2', 'Android', DeviceType::MOBILE ], + 'http://gsm.lge.com/html/gsm/LS996-M10-D1.xml' => [ 'LG', 'G Flex 2', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/MbAHlRXTX34T2a8f/H950-M10-D1.xml' => [ 'LG', 'G Flex 2', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/MbAHlRXTX34T2a8f/H955-M20-D1.xml' => [ 'LG', 'G Flex 2', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/MbAHlRXTX34T2a8f/H955-M3-D1.xml' => [ 'LG', 'G Flex 2', 'Android', DeviceType::MOBILE ], + 'http://gsm.lge.com/html/gsm/MbAHlRXTX34T2a8f/H955-M6-D1.xml' => [ 'LG', 'G Flex 2', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/MbAHlRXTX34T2a8f/H959-M3-D1.xml' => [ 'LG', 'G Flex 2', 'Android', DeviceType::MOBILE ], 'http://pix.cspire.com/UA/profile/lg/as995/as995.xml' => [ 'LG', 'G Flex 2', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/V410-D1.xml' => [ 'LG', 'G Pad 7.0', 'Android', DeviceType::TABLET ], @@ -2520,6 +2539,7 @@ 'http://gsm.lge.com/html/gsm/V490-M3-D1.xml' => [ 'LG', 'G Pad 7.0', 'Android', DeviceType::TABLET ], 'http://device.sprintpcs.com/LG/LK430-Chameleon/latest' => [ 'LG', 'G Pad F 7.0', 'Android', DeviceType::TABLET ], 'http://device.sprintpcs.com/LG/LK430-SPRINT/LK430ZV3.rdf' => [ 'LG', 'G Pad F 7.0', 'Android', DeviceType::TABLET ], + 'http://device.sprintpcs.com/LG/LK430-SPRINT/LK430ZV4.rdf' => [ 'LG', 'G Pad F 7.0', 'Android', DeviceType::TABLET ], 'http://gsm.lge.com/html/gsm/iBpgg_0u_ASxAV_F/V495-D1.xml' => [ 'LG', 'G Pad F 7.0', 'Android', DeviceType::TABLET ], 'http://gsm.lge.com/html/gsm/_-0_bP_4P_s73ov-/V930-D1.xml' => [ 'LG', 'G Pad X 10.1', 'Android', DeviceType::TABLET ], 'http://gsm.lge.com/html/gsm/D830-M3-D1.xml' => [ 'LG', 'G Pro 2', 'Android', DeviceType::MOBILE ], @@ -2642,6 +2662,7 @@ 'http://gsm.lge.com/html/gsm/618-M3-D1.xml' => [ 'LG', 'G2 mini', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/8-M3-D1.xml' => [ 'LG', 'G2 mini', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/D610-M3-D1.xml' => [ 'LG', 'G2 mini', 'Android', DeviceType::MOBILE ], + 'http://gsm.lge.com/html/gsm/D610TR-M3-D1.xml' => [ 'LG', 'G2 mini', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/D610TR-M5-D1.xml' => [ 'LG', 'G2 mini', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/D618-M3-D1.xml' => [ 'LG', 'G2 mini', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/D618-M4-D1.xml' => [ 'LG', 'G2 mini', 'Android', DeviceType::MOBILE ], @@ -2659,6 +2680,7 @@ 'http://device.sprintpcs.com/LG/LS990-SPRINT/LS990ZV8.rdf' => [ 'LG', 'G3', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/LG/LS990-SPRINT/LS990ZVA.rdf' => [ 'LG', 'G3', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/LG/LS990-SPRINT/LS990ZVB.rdf' => [ 'LG', 'G3', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/LG/LS990-SPRINT/LS990ZVC.rdf' => [ 'LG', 'G3', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/%H:%M:%S/D855-M3-D1.xml' => [ 'LG', 'G3', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/%s/%s/%s/D855-M3-D1.xml' => [ 'LG', 'G3', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/985 4G-M3-D1.xml' => [ 'LG', 'G3', 'Android', DeviceType::MOBILE ], @@ -2738,6 +2760,7 @@ 'http://gsm.lge.com/html/gsm/YSdHbanpHC5h2R_E/H818-M4-D1.xml' => [ 'LG', 'G4', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/YSdHbanpHC5h2R_E/H818-M5-D1.xml' => [ 'LG', 'G4', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/YSdHbanpHC5h2R_E/H819-M3-D1.xml' => [ 'LG', 'G4', 'Android', DeviceType::MOBILE ], + 'http://gsm.lge.com/html/gsm/eNsCGw_apwMhnXPM/H900-M10-D1.xml' => [ 'LG', 'G4 Pro', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/-pBWguyi4C2qxxHn/H540-M3-D1.xml' => [ 'LG', 'G4 Stylus', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/-pBWguyi4C2qxxHn/H540-M4-D1.xml' => [ 'LG', 'G4 Stylus', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/b7_gceeg_u9fMBZq/H630-M3-D1.xml' => [ 'LG', 'G4 Stylus', 'Android', DeviceType::MOBILE ], @@ -2782,6 +2805,7 @@ 'http://gsm.lge.com/html/gsm/F310L-M3-D1.xml' => [ 'LG', 'GX', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/F310L-M9-D1-KK.xml' => [ 'LG', 'GX', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/F310LR-M3-D1-KK.xml' => [ 'LG', 'GX', 'Android', DeviceType::MOBILE ], + 'http://gsm.lge.com/html/gsm/F310LR-M9-D1-KK.xml' => [ 'LG', 'GX', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/LG-GX500.xml' => [ 'LG', 'GX500', null, DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/LG-HB620T.xml' => [ 'LG', 'HB620T', null, DeviceType::MOBILE ], 'http://uaprof.vtext.com/lge/vs950/vs950.xml' => [ 'LG', 'Intuition', 'Android', DeviceType::MOBILE ], @@ -3015,9 +3039,11 @@ 'http://gsm.lge.com/html/gsm/1XolXoCnSn7_dGTS/H520-M10-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/1XolXoCnSn7_dGTS/H520-M3-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/1XolXoCnSn7_dGTS/H522-M3-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], + 'http://gsm.lge.com/html/gsm/1XolXoCnSn7_dGTS/H525-M3-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/1XolXoCnSn7_dGTS/H525-M5-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/1XolXoCnSn7_dGTS/H525n-M3-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/1XolXoCnSn7_dGTS/H525n-M5-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], + 'http://gsm.lge.com/html/gsm/Dsi6X_y8P_In4gbf/H500-M10-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/Dsi6X_y8P_In4gbf/H500-M3-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/Dsi6X_y8P_In4gbf/H502-M10-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], 'http://gsm.lge.com/html/gsm/Dsi6X_y8P_In4gbf/H502-M3-D1.xml' => [ 'LG', 'Magna', 'Android', DeviceType::MOBILE ], @@ -3362,6 +3388,7 @@ 'http://gsm.lge.com/html/gsm/P940h-M6-D2.xml' => [ 'LG', 'PRADA 3.0', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/LG/LGLS620-Chameleon/latest' => [ 'LG', 'Realm', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/LG/LS620-BOOST/LS620ZV3.rdf' => [ 'LG', 'Realm', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/LG/LS620-BOOST/LS620ZV4.rdf' => [ 'LG', 'Realm', 'Android', DeviceType::MOBILE ], 'http://wapuaprof.wap.mycricket.com/lg/LG-LW770.xml' => [ 'LG', 'Regard', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/LG/LX260/LX260V09.rdf' => [ 'LG', 'Rumor LX260', null, DeviceType::MOBILE ], 'http://device.sprintpcs.com/LG/LX260/LX260V0a.rdf' => [ 'LG', 'Rumor LX260', null, DeviceType::MOBILE ], @@ -3497,6 +3524,7 @@ 'http://www.1066.cn/uaprof/prof/Micromax/Micromax_A093.xml' => [ 'Micromax', 'A93 Canvas Elanza', 'Android', DeviceType::MOBILE ], 'http://www.1066.cn/uaprof/prof/Micromax/Micromax_AQ5001.xml' => [ 'Micromax', 'AQ5001 Canvas Juice 2', 'Android', DeviceType::MOBILE ], 'http://202.58.121.191/MTK_Phone_KK_UAprofile.xml' => [ 'Micromax', 'Canvas Tab P470', 'Android', DeviceType::TABLET ], + 'Micromax X450' => [ 'Micromax', 'X450', null, DeviceType::MOBILE ], 'http://zune.net/uaprof/ZuneHD.xml' => [ 'Microsoft', 'Zune HD', null, ], 'http://www.mio-tech.com.tw/download/smartphone/Mio8390r101.xml' => [ 'Mio', '8390', null, DeviceType::MOBILE ], 'http://www.mio-tech.com.tw/download/smartphone/MioA700.xml' => [ 'Mio', 'A700', null, DeviceType::MOBILE ], @@ -3735,7 +3763,11 @@ 'http://uaprof.motorola.com/phoneconfig/xt788/Profile/xt788.rdf' => [ 'Motorola', 'XT788', 'Android', DeviceType::MOBILE ], 'http://nmsc.ctvap.cn/uaprof/MOT/MOT_XT928_1_20110914.XML' => [ 'Motorola', 'XT928', 'Android', DeviceType::MOBILE ], 'http://uaprof.motorola.com/phoneconfig/ZN200/Profile/ZN200.rdf' => [ 'Motorola', 'ZN200', null, DeviceType::MOBILE ], + 'http://wap.nexustelco.com/uaprofile/MovistarD5.xml' => [ 'Movistar', 'Dual D5', 'Android', DeviceType::MOBILE ], + 'http://wap.nexustelco.com/uaprofile/GO775.xml' => [ 'Movistar', 'Go Mobile 775', 'Android', DeviceType::MOBILE ], + 'http://wap.nexustelco.com/uaprofile/GO778.xml' => [ 'Movistar', 'Go Mobile 778', 'Android', DeviceType::MOBILE ], 'http://wap.nexustelco.com/uaprofile/GO950.xml' => [ 'Movistar', 'Go Mobile 950', 'Android', DeviceType::MOBILE ], + 'http://wap.nexustelco.com/wap/uaprofile/GO963.xml' => [ 'Movistar', 'Go Mobile 963', 'Android', DeviceType::MOBILE ], 'http://wap.nexustelco.com/uaprofile/GO980.xml' => [ 'Movistar', 'Go Mobile 980', 'Android', DeviceType::MOBILE ], 'http://www.zte.com.cn/mobile/uaprof/Movistar-Motion.xml' => [ 'Movistar', 'Motion', 'Android', DeviceType::MOBILE ], 'http://www.zte.com.cn/mobile/uaprof/Movistar-One.xml' => [ 'Movistar', 'One', 'Android', DeviceType::MOBILE ], @@ -4730,6 +4762,7 @@ 'http://www.oppo.com/resource/UA-PROF/OPPOR2001.xml' => [ 'Oppo', 'Find 5 mini R827T', 'Android', DeviceType::MOBILE ], 'http://www.oppo.com/resource/UA-PROF/OPPOR827T.xml' => [ 'Oppo', 'Find 5 mini R827T', 'Android', DeviceType::MOBILE ], 'http://www.oppo.com/resource/UA-PROF/OPPOX909T.xml' => [ 'Oppo', 'Find 5 X909', 'Android', DeviceType::MOBILE ], + 'http://ua.prof.oppo.com/resource/ua-PROF/OPPOFIND7.xml' => [ 'Oppo', 'Find 7 X9070', 'Android', DeviceType::MOBILE ], 'http://www.oppo.com/resource/UA-PROF/OPPOX9070.xml' => [ 'Oppo', 'Find 7 X9070', 'Android', DeviceType::MOBILE ], 'http://ua.prof.oppo.com/resource/ua-PROF/OPPOX9076.xml' => [ 'Oppo', 'Find 7 X9076', 'Android', DeviceType::MOBILE ], 'http://www.oppo.com/resource/UA-PROF/OPPOX9077.xml' => [ 'Oppo', 'Find 7 X9077', 'Android', DeviceType::MOBILE ], @@ -4766,6 +4799,7 @@ 'http://www.oppo.com/resource/UA-PROF/OPPOR7.xml' => [ 'Oppo', 'R7', 'Android', DeviceType::MOBILE ], 'http://www.oppo.com/resource/UA-PROF/OPPOR7005.xml' => [ 'Oppo', 'R7005', 'Android', DeviceType::MOBILE ], 'http://www.oppo.com/resource/UA-PROF/OPPOR7c.xml' => [ 'Oppo', 'R7c', 'Android', DeviceType::MOBILE ], + 'http://www.oppo.com/resource/UA-PROF/OPPOR7s.xml' => [ 'Oppo', 'R7s', 'Android', DeviceType::MOBILE ], 'http://www.oppo.com/resource/UA-PROF/OPPOR7t.xml' => [ 'Oppo', 'R7t', 'Android', DeviceType::MOBILE ], 'http://www.oppo.com/resource/UA-PROF/OPPOR809T.xml' => [ 'Oppo', 'R809', 'Android', DeviceType::MOBILE ], 'http://www.oppo.com/resource/UA-PROF/OPPOR813T.xml' => [ 'Oppo', 'R813', 'Android', DeviceType::MOBILE ], @@ -4893,6 +4927,7 @@ 'http://www.pantech.co.kr/Uaprof/Gsm/S100J.xml' => [ 'Pantech', 'S100', null, DeviceType::MOBILE ], 'http://mobileuaprof.xtra.co.nz/h_tx215c.rdf' => [ 'Pantech', 'TX215', null, DeviceType::MOBILE ], 'http://uaprof.qma.com.tw/vega-ptl21.xml' => [ 'Pantech', 'Vega Nº6', 'Android', DeviceType::MOBILE ], + 'http://ota.phicomm.com.cn/MobileProfile/C630LwRU-UA-Profile.xml' => [ 'Phicomm', 'Clue L', 'Android', DeviceType::MOBILE ], 'http://www.consumer.philips.com/wbu/uap289.xml' => [ 'Philips', '289', null, DeviceType::MOBILE ], 'http://www.consumer.philips.com/wbu/uap330.xml' => [ 'Philips', '330', null, DeviceType::MOBILE ], 'http://www.consumer.philips.com/wbu/uap350.xml' => [ 'Philips', '350', null, DeviceType::MOBILE ], @@ -4937,6 +4972,7 @@ 'http://wap.dl.prestigio.com/uaprofile/tablets/PMT5777_3G_V1.xml' => [ 'Prestigio', 'Multipad Color 7.0 3G', 'Android', DeviceType::TABLET ], 'http://wap.dl.prestigio.com/uaprofile/tablets/PMT5887_3G_V1.xml' => [ 'Prestigio', 'Multipad Color 8.0 3G', 'Android', DeviceType::MOBILE ], 'http://wap.dl.prestigio.com/uaprofile/tablets/PMT5001_3G_V1.xml' => [ 'Prestigio', 'Multipad Muze 5001 3G', 'Android', DeviceType::TABLET ], + 'http://wap.dl.prestigio.com/uaprofile/tablets/PMT5008_3G_V1.xml' => [ 'Prestigio', 'Multipad Muze 5008 3G', 'Android', DeviceType::TABLET ], 'http://wap.dl.prestigio.com/uaprofile/tablets/PMT3277_3G_V1.xml' => [ 'Prestigio', 'Multipad Ranger 7.0 3G', 'Android', DeviceType::TABLET ], 'http://wap.dl.prestigio.com/uaprofile/tablets/PMT5287_4G_V1.xml' => [ 'Prestigio', 'Multipad Ranger 8.0 4G', 'Android', DeviceType::TABLET ], 'http://wap.dl.prestigio.com/uaprofile/tablets/PMT7077_4G_V1.xml' => [ 'Prestigio', 'Multipad Ranger 8.0 4G', 'Android', DeviceType::TABLET ], @@ -5327,6 +5363,7 @@ 'http://www.blackberry.net/go/mobile/profiles/uaprof/9520_gprs/5.0.0.rdf' => [ 'RIM', 'BlackBerry Storm2 9520', 'BlackBerry OS', DeviceType::MOBILE ], 'http://www.blackberry.net/go/mobile/profiles/uaprof/9520_umts/5.0.0.rdf' => [ 'RIM', 'BlackBerry Storm2 9520', 'BlackBerry OS', DeviceType::MOBILE ], 'http://device.sprintpcs.com/RIM/BlackBerry9670/6.0.0.706.rdf' => [ 'RIM', 'BlackBerry Style 9670', 'BlackBerry OS', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/RIM/BlackBerry9670/6.0.0.707.rdf' => [ 'RIM', 'BlackBerry Style 9670', 'BlackBerry OS', DeviceType::MOBILE ], 'http://www.blackberry.net/go/mobile/profiles/uaprof/9670/6.0.0.rdf' => [ 'RIM', 'BlackBerry Style 9670', 'BlackBerry OS', DeviceType::MOBILE ], 'http://www.blackberry.net/go/mobile/profiles/uaprof/9670_1x/6.0.0.rdf' => [ 'RIM', 'BlackBerry Style 9670', 'BlackBerry OS', DeviceType::MOBILE ], 'http://www.blackberry.net/go/mobile/profiles/uaprof/9670_80211b/6.0.0.rdf' => [ 'RIM', 'BlackBerry Style 9670', 'BlackBerry OS', DeviceType::MOBILE ], @@ -5433,6 +5470,7 @@ 'http://wap.samsungmobile.com/uaprof/SGH-A827.xml' => [ 'Samsung', 'Access', null, DeviceType::MOBILE ], 'http://uaprof.qma.com.tw/SAMSUNG-SCH-I619_CHN_BRI.xml' => [ 'Samsung', 'Ace A+', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-B6520.xml' => [ 'Samsung', 'B6520 OmniaPRO 5', 'Windows Mobile', DeviceType::MOBILE ], + 'http://wap.samsungmobile.com/uaprof/GT-B7330.xml' => [ 'Samsung', 'B7330 OmniaPRO', 'Windows Mobile', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-B7610.xml' => [ 'Samsung', 'B7610 OmniaPRO', 'Windows Mobile', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-B7610_2G.xml' => [ 'Samsung', 'B7610 OmniaPRO', 'Windows Mobile', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-B7610_3G.xml' => [ 'Samsung', 'B7610 OmniaPRO', 'Windows Mobile', DeviceType::MOBILE ], @@ -5509,6 +5547,7 @@ 'http://wap.samsungmobile.com/uaprof/GT-S3850.rdf' => [ 'Samsung', 'Corby II', 'Touchwiz', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-S3850.xml' => [ 'Samsung', 'Corby II', 'Touchwiz', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-S3850BR.xml' => [ 'Samsung', 'Corby II', 'Touchwiz', DeviceType::MOBILE ], + 'http://wap.samsungmobile.com/uaprof/GT-S3850_3G.rdf' => [ 'Samsung', 'Corby II', 'Touchwiz', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-B3313UAProf.xml' => [ 'Samsung', 'Corby Mate', null, DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-C3510T.rdf' => [ 'Samsung', 'Corby Pop', null, DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-B5310.rdf' => [ 'Samsung', 'Corby Pro', 'Touchwiz', DeviceType::MOBILE ], @@ -5691,6 +5730,7 @@ 'http://nmsc.ctvap.cn/uaprof/SCH/SCH_SM-E7009_1_20141208.xml' => [ 'Samsung', 'Galaxy E7', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-E700H.xml' => [ 'Samsung', 'Galaxy E7', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-E700M.xml' => [ 'Samsung', 'Galaxy E7', 'Android', DeviceType::MOBILE ], + 'http://wap.samsungmobile.com/uaprof/SGH-T599.xml' => [ 'Samsung', 'Galaxy Exhibit', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SGH-T599N.xml' => [ 'Samsung', 'Galaxy Exhibit', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SGH-T599V.xml' => [ 'Samsung', 'Galaxy Exhibit', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SGH-T679.xml' => [ 'Samsung', 'Galaxy Exhibit II', 'Android', DeviceType::MOBILE ], @@ -5744,6 +5784,7 @@ 'http://wap.samsungmobile.com/uaprof/GT-I9063T.xml' => [ 'Samsung', 'Galaxy Grand Neo Duos', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SM-G530P-SPRINT/OF8.rdf' => [ 'Samsung', 'Galaxy Grand Prime', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SM-G530P-SPRINT/OG2.rdf' => [ 'Samsung', 'Galaxy Grand Prime', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/Samsung/SM-G530P-SPRINT/OI1.rdf' => [ 'Samsung', 'Galaxy Grand Prime', 'Android', DeviceType::MOBILE ], 'http://nmsc.ctvap.cn/uaprof/SCH/SCH_SM-G5309W_1_20140909.xml' => [ 'Samsung', 'Galaxy Grand Prime', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-G530AZ.xml' => [ 'Samsung', 'Galaxy Grand Prime', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-G530BT.xml' => [ 'Samsung', 'Galaxy Grand Prime', 'Android', DeviceType::MOBILE ], @@ -5770,6 +5811,7 @@ 'http://wap.samsungmobile.com/uaprof/SM-J110M.xml' => [ 'Samsung', 'Galaxy J1 Ace', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-J200G.xml' => [ 'Samsung', 'Galaxy J2', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-J200GU.xml' => [ 'Samsung', 'Galaxy J2', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/Samsung/SM-J320P-Chameleon/latest' => [ 'Samsung', 'Galaxy J3', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-J500F.xml' => [ 'Samsung', 'Galaxy J5', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-J500G.xml' => [ 'Samsung', 'Galaxy J5', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-J500H.xml' => [ 'Samsung', 'Galaxy J5', 'Android', DeviceType::MOBILE ], @@ -5923,6 +5965,7 @@ 'http://device.sprintpcs.com/Samsung/SM-N915P-SPRINT/OF6.rdf' => [ 'Samsung', 'Galaxy Note Edge', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SM-N915P-SPRINT/OFE.rdf' => [ 'Samsung', 'Galaxy Note Edge', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SM-N915P-SPRINT/OG1.rdf' => [ 'Samsung', 'Galaxy Note Edge', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/Samsung/SM-N915P-SPRINT/OJ5.rdf' => [ 'Samsung', 'Galaxy Note Edge', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-N915A.xml' => [ 'Samsung', 'Galaxy Note Edge', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-N915F.xml' => [ 'Samsung', 'Galaxy Note Edge', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-N915FY.xml' => [ 'Samsung', 'Galaxy Note Edge', 'Android', DeviceType::MOBILE ], @@ -6000,8 +6043,10 @@ 'http://uaprof.vtext.com/sam/i110/i110.xml' => [ 'Samsung', 'Galaxy Proclaim', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-I9103.xml' => [ 'Samsung', 'Galaxy R', 'Android', DeviceType::MOBILE ], 'http://uaprof.vmobl.com/Samsung/SPH-M950-VMUB/1.0/UAProf.xml' => [ 'Samsung', 'Galaxy Reverb', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/Samsung/SPH-M840-6102952738/OI1.rdf' => [ 'Samsung', 'Galaxy Ring', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SPH-M840-BOOST/MH5.rdf' => [ 'Samsung', 'Galaxy Ring', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SPH-M840-BOOST/NK1.rdf' => [ 'Samsung', 'Galaxy Ring', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/Samsung/SPH-M840-BOOST/OI1.rdf' => [ 'Samsung', 'Galaxy Ring', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SPH-M840-Chameleon/MH5.rdf' => [ 'Samsung', 'Galaxy Ring', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SPH-M840-VIRGIN/ME3.rdf' => [ 'Samsung', 'Galaxy Ring', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SPH-M840-VIRGIN/MH5.rdf' => [ 'Samsung', 'Galaxy Ring', 'Android', DeviceType::MOBILE ], @@ -6153,6 +6198,7 @@ 'http://device.sprintpcs.com/Samsung/SPH-L710/NJ2.rdf' => [ 'Samsung', 'Galaxy S III', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SPH-L710/OH1.rdf' => [ 'Samsung', 'Galaxy S III', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SPH-L710T-2012071301/OF2.rdf' => [ 'Samsung', 'Galaxy S III', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/Samsung/SPH-L710T-2012071301/OH1.rdf' => [ 'Samsung', 'Galaxy S III', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SPH-L710T-BOOST/NE5.rdf' => [ 'Samsung', 'Galaxy S III', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SPH-L710T-BOOST/NF4.rdf' => [ 'Samsung', 'Galaxy S III', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SPH-L710T-BOOST/OA3.rdf' => [ 'Samsung', 'Galaxy S III', 'Android', DeviceType::MOBILE ], @@ -6409,6 +6455,7 @@ 'http://device.sprintpcs.com/Samsung/SM-G925P-SPRINT/OGA.rdf' => [ 'Samsung', 'Galaxy S6 Edge', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SM-G925P-SPRINT/OH1.rdf' => [ 'Samsung', 'Galaxy S6 Edge', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SM-G925P-SPRINT/OI1.rdf' => [ 'Samsung', 'Galaxy S6 Edge', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/Samsung/SM-G925P-SPRINT/OJ7.rdf' => [ 'Samsung', 'Galaxy S6 Edge', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-G925A.xml' => [ 'Samsung', 'Galaxy S6 Edge', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-G925F.xml' => [ 'Samsung', 'Galaxy S6 Edge', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-G925FPCL.xml' => [ 'Samsung', 'Galaxy S6 Edge', 'Android', DeviceType::MOBILE ], @@ -6418,6 +6465,7 @@ 'http://wap.samsungmobile.com/uaprof/SM-G925W8.xml' => [ 'Samsung', 'Galaxy S6 Edge', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SM-G928P-SPRINT/OGD.rdf' => [ 'Samsung', 'Galaxy S6 Edge+', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/Samsung/SM-G928P-SPRINT/OI6.rdf' => [ 'Samsung', 'Galaxy S6 Edge+', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/Samsung/SM-G928P-SPRINT/OJ6.rdf' => [ 'Samsung', 'Galaxy S6 Edge+', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SAMSUNGUAPROFA.xml' => [ 'Samsung', 'Galaxy S6 Edge+', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/SM-G928G.xml' => [ 'Samsung', 'Galaxy S6 Edge+', 'Android', DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-I9003.xml' => [ 'Samsung', 'Galaxy SL', 'Android', DeviceType::MOBILE ], @@ -6450,6 +6498,7 @@ 'http://wap.samsungmobile.com/uaprof/GT-P5100.xml' => [ 'Samsung', 'Galaxy Tab 2 (10.1)', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/GT-P5100BO.xml' => [ 'Samsung', 'Galaxy Tab 2 (10.1)', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/GT-P5110.xml' => [ 'Samsung', 'Galaxy Tab 2 (10.1)', 'Android', DeviceType::TABLET ], + 'http://wap.samsungmobile.com/uaprof/GT-P5113.xml' => [ 'Samsung', 'Galaxy Tab 2 (10.1)', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/SGH-I497.xml' => [ 'Samsung', 'Galaxy Tab 2 (10.1)', 'Android', DeviceType::TABLET ], 'http://uaprof.vtext.com/sam/SCH-i705/SCH-i705.xml' => [ 'Samsung', 'Galaxy Tab 2 (7.0)', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/GT-P3100.xml' => [ 'Samsung', 'Galaxy Tab 2 (7.0)', 'Android', DeviceType::TABLET ], @@ -6528,6 +6577,7 @@ 'http://wap.samsungmobile.com/uaprof/SHV-E140S.xml' => [ 'Samsung', 'Galaxy Tab 8.9', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/SM-T350.xml' => [ 'Samsung', 'Galaxy Tab A 8.0', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/SM-T355Y.xml' => [ 'Samsung', 'Galaxy Tab A 8.0', 'Android', DeviceType::TABLET ], + 'http://wap.samsungmobile.com/uaprof/SM-T357T.xml' => [ 'Samsung', 'Galaxy Tab A 8.0', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/SM-T357W.xml' => [ 'Samsung', 'Galaxy Tab A 8.0', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/SM-T365Y.xml' => [ 'Samsung', 'Galaxy Tab A 9.7', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/SM-T550.xml' => [ 'Samsung', 'Galaxy Tab A 9.7', 'Android', DeviceType::TABLET ], @@ -6565,6 +6615,7 @@ 'http://wap.samsungmobile.com/uaprof/SM-T715Y.xml' => [ 'Samsung', 'Galaxy Tab S2 8.0', 'Android', DeviceType::TABLET ], 'http://device.sprintpcs.com/Samsung/SM-T817P-Chameleon/latest' => [ 'Samsung', 'Galaxy Tab S2 9.7', 'Android', DeviceType::TABLET ], 'http://device.sprintpcs.com/Samsung/SM-T817P-SPRINT/OH6.rdf' => [ 'Samsung', 'Galaxy Tab S2 9.7', 'Android', DeviceType::TABLET ], + 'http://device.sprintpcs.com/Samsung/SM-T817P-SPRINT/OJ5.rdf' => [ 'Samsung', 'Galaxy Tab S2 9.7', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/SM-T810.xml' => [ 'Samsung', 'Galaxy Tab S2 9.7', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/SM-T815.xml' => [ 'Samsung', 'Galaxy Tab S2 9.7', 'Android', DeviceType::TABLET ], 'http://wap.samsungmobile.com/uaprof/SM-T815Y.xml' => [ 'Samsung', 'Galaxy Tab S2 9.7', 'Android', DeviceType::TABLET ], @@ -6670,6 +6721,7 @@ 'http://wap.samsungmobile.com/uaprof/GT-C3010UAProf.xml' => [ 'Samsung', 'GT-C3010', null, DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-C3011.xml' => [ 'Samsung', 'GT-C3011', null, DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-C3060UAProf.xml' => [ 'Samsung', 'GT-C3060', null, DeviceType::MOBILE ], + 'http://wap.samsungmobile.com/uaprof/GT-C3230_2G.rdf' => [ 'Samsung', 'GT-C3230', null, DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-C3313TBR.xml' => [ 'Samsung', 'GT-C3313', null, DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-C3322.xml' => [ 'Samsung', 'GT-C3322 Duos', null, DeviceType::MOBILE ], 'http://wap.samsungmobile.com/uaprof/GT-C3322iUAProf.xml' => [ 'Samsung', 'GT-C3322 Duos', null, DeviceType::MOBILE ], @@ -8409,6 +8461,7 @@ 'http://www.msai.in/uaprof/vivo/vivo_Y15S.xml' => [ 'Vivo', 'Y15S', 'Android', DeviceType::MOBILE ], 'http://download.api.vivoglobal.com/pro/UA/vivo_Y22.xml' => [ 'Vivo', 'Y22', 'Android', DeviceType::MOBILE ], 'http://www.msai.in/uaprof/vivo/vivo-Y22.xml' => [ 'Vivo', 'Y22', 'Android', DeviceType::MOBILE ], + 'http://www.msai.in/uaprof/vivo/vivo_Y27L.xml' => [ 'Vivo', 'Y27L', 'Android', DeviceType::MOBILE ], 'http://download.api.vivoglobal.com/pro/UA/vivo_Y28.xml' => [ 'Vivo', 'Y28', 'Android', DeviceType::MOBILE ], 'http://www.msai.in/uaprof/vivo/vivo_Y28.xml' => [ 'Vivo', 'Y28', 'Android', DeviceType::MOBILE ], 'http://download.api.vivoglobal.com/pro/UA/vivo_Y31.xml' => [ 'Vivo', 'Y31', 'Android', DeviceType::MOBILE ], @@ -8495,7 +8548,10 @@ 'http://apkupdate.miui.com/other/HM2014011_UAprofile.xml' => [ 'Xiaomi', 'Redmi Red Rice', 'Android', DeviceType::MOBILE ], 'http://apkupdate.miui.com/other/HM2014501_UAprofile.xml' => [ 'Xiaomi', 'Redmi Red Rice', 'Android', DeviceType::MOBILE ], 'http://nmsc.ctvap.cn/uaprof/YCT/YCT_TE600_1_20101228.xml' => [ 'YCT', 'TE600', 'Android', DeviceType::MOBILE ], + 'http://www.ddmbrands.com/uaprof/yezz/andy_5EI.xml' => [ 'Yezz', 'Andy 5EI', 'Android', DeviceType::MOBILE ], + 'http://www.ddmbrands.com/uaprof/yezz/andy_5EL.xml' => [ 'Yezz', 'Andy 5EL', 'Android', DeviceType::MOBILE ], 'http://www.lenovomobile.com/admin/module/product/DownFile/YUSUN LA2-T_UAprofile.xml' => [ 'YUSUN', 'LA2-T', 'Android', DeviceType::MOBILE ], + 'http://uaprof.zebra.com/mc36.xml' => [ 'Zebra', 'MC36', 'Android', DeviceType::MOBILE ], 'http://211.42.201.70/ua_profile/ZMEM1070.xml' => [ 'Zonda', 'ZMEM1070', null, DeviceType::MOBILE ], 'http://211.42.201.70/ua_profile/ZMEM1075.xml' => [ 'Zonda', 'ZMEM1075', null, DeviceType::MOBILE ], 'http://211.42.201.70/ua_profile/ZMEM1085.xml' => [ 'Zonda', 'ZMEM1085', null, DeviceType::MOBILE ], @@ -8536,6 +8592,7 @@ 'http://device.telusmobility.com/zte/ZTED90-0.rdf' => [ 'ZTE', 'D90', null, DeviceType::MOBILE ], 'http://www.zte.com.cn/mobile/uaprof/ZTE_N72_20090709.xml' => [ 'ZTE', 'E N72', 'Windows Mobile', DeviceType::MOBILE ], 'http://www.zte.com.cn/mobile/uaprof/ZTE-U-E850(Movilnet).xml' => [ 'ZTE', 'E850', null, DeviceType::MOBILE ], + 'http://www.zte.com.cn/mobile/uaprof/ZTE-F101(RDS).xml' => [ 'ZTE', 'F101', null, DeviceType::MOBILE ], 'http://www.zte.com.cn/mobile/uaprof/ZTE-F107(3UK).xml' => [ 'ZTE', 'F107', null, DeviceType::MOBILE ], 'http://www.zte.com.cn/mobile/uaprof/ZTE-F150.xml' => [ 'ZTE', 'F150', null, DeviceType::MOBILE ], 'http://www.zte.com.cn/mobile/uaprof/ZTE-F151.xml' => [ 'ZTE', 'F151', null, DeviceType::MOBILE ], @@ -8615,6 +8672,7 @@ 'http://www.zte.com.cn/mobile/uaprof/N799D.xml' => [ 'ZTE', 'N799', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/ZTE/N800-Chameleon/latest' => [ 'ZTE', 'N800 Awe', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/ZTE/N800-Chameleon/N800V1.0.0B06.rdf' => [ 'ZTE', 'N800 Awe', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/ZTE/N800-VIRGIN/AWE_Inspired_Moonshine_White_V2.9.rdf' => [ 'ZTE', 'N800 Awe', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/ZTE/N800-VIRGIN/N800V1.0.0B04.rdf' => [ 'ZTE', 'N800 Awe', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/ZTE/N800-VIRGIN/N800V1.0.0B05.rdf' => [ 'ZTE', 'N800 Awe', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/ZTE/N800-VIRGIN/N800V1.0.0B06.rdf' => [ 'ZTE', 'N800 Awe', 'Android', DeviceType::MOBILE ], @@ -8681,6 +8739,7 @@ 'http://device.sprintpcs.com/ZTE/N9520-BOOST/latest' => [ 'ZTE', 'N9520 Stormer', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/ZTE/N9520-BOOST/N9520V1.0.0B05.rdf' => [ 'ZTE', 'N9520 Stormer', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/ZTE/N9520-BOOST/N9520V1.0.0B06.rdf' => [ 'ZTE', 'N9520 Stormer', 'Android', DeviceType::MOBILE ], + 'http://device.sprintpcs.com/ZTE/N9520-BOOST/N9520V1.0.0B07.rdf' => [ 'ZTE', 'N9520 Stormer', 'Android', DeviceType::MOBILE ], 'http://device.sprintpcs.com/ZTE/N9520-Chameleon/latest' => [ 'ZTE', 'N9520 Stormer', 'Android', DeviceType::MOBILE ], 'http://www.zte.com.cn/mobile/uaprof/ZTE N901.xml' => [ 'ZTE', 'N960', 'Android', DeviceType::MOBILE ], 'http://www.zte.com.cn/mobile/uaprof/ZTE N970.xml' => [ 'ZTE', 'N970 Grand X', 'Android', DeviceType::MOBILE ], diff --git a/src/Analyser.php b/src/Analyser.php index ccb0ccc..238dace 100644 --- a/src/Analyser.php +++ b/src/Analyser.php @@ -11,6 +11,10 @@ class Analyser private $data; + private $options; + + private $headers = []; + public function __construct($options) { if (is_string($options)) { @@ -19,8 +23,6 @@ public function __construct($options) $this->options = (object) (isset($options['headers']) ? $options : [ 'headers' => $options ]); } - $this->headers = []; - if (isset($this->options->headers)) { $this->headers = $this->options->headers; } diff --git a/src/Analyser/Camouflage.php b/src/Analyser/Camouflage.php index 3ee77cd..0481aeb 100644 --- a/src/Analyser/Camouflage.php +++ b/src/Analyser/Camouflage.php @@ -8,245 +8,266 @@ trait Camouflage { private function &detectCamouflage() { - if (isset($this->options->useragent) && $this->options->useragent != '') { - if ($this->options->useragent == 'Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.2.3.4) Gecko/') { + if ($ua = $this->getHeader('User-Agent')) { - if ($this->data->browser->name != 'UC Browser') { - $this->data->browser->name = 'UC Browser'; - $this->data->browser->version = null; - $this->data->browser->stock = false; - } + $this + ->detectCamouflagedAndroidBrowser($ua) + ->detectCamouflagedAndroidAsusBrowser($ua) + ->detectCamouflagedAsSafari($ua) + ->detectCamouflagedAsChrome($ua); + } - if ($this->data->os->name == 'Windows') { - $this->data->os->name = ''; - $this->data->os->version = null; - } + if (!empty($this->options->useragent)) { + $this->detectCamouflagedUCBrowser($this->options->useragent); + } + + if (isset($this->options->engine)) { + $this->detectCamouflagedBasedOnEngines(); + } - $this->data->engine->name = 'Gecko'; - $this->data->engine->version = null; + if (isset($this->options->features)) { + $this->detectCamouflagedBasedOnFeatures(); + } - $this->data->device->type = 'mobile'; - } + return $this; + } + private function &detectCamouflagedAndroidBrowser($ua) + { + if (preg_match('/Mac OS X 10_6_3; ([^;]+); [a-z]{2}(?:-[a-z]{2})?\)/u', $ua, $match)) { + $this->data->browser->name = ''; + $this->data->browser->version = null; + $this->data->browser->mode = 'desktop'; - if (preg_match('/Mac OS X 10_6_3; ([^;]+); [a-z]{2}-(?:[a-z]{2})?\)/u', $this->options->useragent, $match)) { - $this->data->browser->name = ''; - $this->data->browser->version = null; - $this->data->browser->mode = 'desktop'; + $this->data->os->name = 'Android'; + $this->data->os->alias = null; + $this->data->os->version = null; + + $this->data->engine->name = 'Webkit'; + $this->data->engine->version = null; + + $this->data->device->type = 'mobile'; + + $this->data->features[] = 'foundDevice'; + } + + return $this; + } + + private function &detectCamouflagedAndroidAsusBrowser($ua) + { + if (preg_match('/Linux Ventana; [a-z]{2}(?:-[a-z]{2})?; (.+) Build/u', $ua, $match)) { + $this->data->browser->name = ''; + $this->data->browser->version = null; + $this->data->browser->mode = 'desktop'; + + $this->data->os->name = 'Android'; + $this->data->os->version = null; + + $this->data->engine->name = 'Webkit'; + $this->data->engine->version = null; - $this->data->os->name = 'Android'; - $this->data->os->alias = null; - $this->data->os->version = null; + $this->data->device->type = 'mobile'; - $this->data->engine->name = 'Webkit'; - $this->data->engine->version = null; + $this->data->features[] = 'foundDevice'; + } - $this->features[] = 'foundDevice'; + return $this; + } + + private function &detectCamouflagedAsSafari($ua) + { + if ($this->data->isBrowser('Safari') && !preg_match('/Darwin/u', $ua)) { + if ($this->data->isOs('iOS') && !preg_match('/^Mozilla/u', $ua)) { + $this->data->features[] = 'noMozillaPrefix'; + $this->data->camouflage = true; } - if (preg_match('/Linux Ventana; [a-z]{2}-[a-z]{2}; (.+) Build/u', $this->options->useragent, $match)) { - $this->data->browser->name = ''; - $this->data->browser->version = null; - $this->data->browser->mode = 'desktop'; + if (!preg_match('/Version\/[0-9\.]+/u', $ua)) { + $this->data->features[] = 'noVersion'; + $this->data->camouflage = true; + } + } - $this->data->os->name = 'Android'; - $this->data->os->version = null; + return $this; + } - $this->data->engine->name = 'Webkit'; - $this->data->engine->version = null; + private function &detectCamouflagedAsChrome($ua) + { + if ($this->data->isBrowser('Chrome')) { + if (preg_match('/(?:Chrome|CrMo|CriOS)\//u', $ua) + && !preg_match('/(?:Chrome|CrMo|CriOS)\/([0-9]{1,2}\.[0-9]\.[0-9]{3,4}\.[0-9]+)/u', $ua) + ) { - $this->features[] = 'foundDevice'; + $this->data->features[] = 'wrongVersion'; + $this->data->camouflage = true; } + } - if (isset($this->data->browser->name) && $this->data->browser->name == 'Safari') { - preg_match('/AppleWebKit\/([0-9]+.[0-9]+)/iu', $this->options->useragent, $webkitMatch); - preg_match('/Safari\/([0-9]+.[0-9]+)/iu', $this->options->useragent, $safariMatch); + return $this; + } - if ($this->data->os->name != 'iOS' && $webkitMatch[1] != $safariMatch[1]) { - $this->features[] = 'safariMismatch'; - $this->camouflage = true; - } + private function &detectCamouflagedUCBrowser($ua) + { + if ($ua == 'Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.2.3.4) Gecko/') { - if ($this->data->os->name == 'iOS' && !preg_match('/^Mozilla/u', $this->options->useragent)) { - $this->features[] = 'noMozillaPrefix'; - $this->camouflage = true; - } + if (!$this->data->isBrowser('UC Browser')) { + $this->data->browser->name = 'UC Browser'; + $this->data->browser->version = null; + $this->data->browser->stock = false; + } - if (!preg_match('/Version\/[0-9\.]+/u', $this->options->useragent)) { - $this->features[] = 'noVersion'; - $this->camouflage = true; - } + if ($this->data->isOs('Windows')) { + $this->data->os->reset(); } - if (isset($this->data->browser->name) && $this->data->browser->name == 'Chrome') { - if (!preg_match('/(?:Chrome|CrMo|CriOS)\/([0-9]{1,2}\.[0-9]\.[0-9]{3,4}\.[0-9]+)/u', $this->options->useragent)) { - $this->features[] = 'wrongVersion'; - $this->camouflage = true; + $this->data->engine->reset([ 'name' => 'Gecko' ]); + $this->data->device->type = 'mobile'; + } + + return $this; + } + + private function &detectCamouflagedBasedOnEngines() + { + if (isset($this->data->engine->name) && $this->data->browser->mode != 'proxy') { + + /* If it claims not to be Trident, but it is probably Trident running camouflage mode */ + if ($this->options->engine & Constants\EngineType::TRIDENT) { + $this->data->features[] = 'trident'; + + if ($this->data->engine->name && $this->data->engine->name != 'Trident') { + $this->data->camouflage = !isset($this->data->browser->name) || ($this->data->browser->name != 'Maxthon' && $this->data->browser->name != 'Motorola WebKit'); } } - } - if (isset($this->options->engine)) { - if (isset($this->data->engine->name) && $this->data->browser->mode != 'proxy') { + /* If it claims not to be Opera, but it is probably Opera running camouflage mode */ + if ($this->options->engine & Constants\EngineType::PRESTO) { + $this->data->features[] = 'presto'; - /* If it claims not to be Trident, but it is probably Trident running camouflage mode */ - if ($this->options->engine & Constants\EngineType::TRIDENT) { - $this->features[] = 'trident'; + if ($this->data->engine->name && $this->data->engine->name != 'Presto') { + $this->data->camouflage = true; + } - if ($this->data->engine->name && $this->data->engine->name != 'Trident') { - $this->camouflage = !isset($this->data->browser->name) || ($this->data->browser->name != 'Maxthon' && $this->data->browser->name != 'Motorola WebKit'); - } + if (isset($this->data->browser->name) && $this->data->browser->name == 'Internet Explorer') { + $this->data->camouflage = true; } + } - /* If it claims not to be Opera, but it is probably Opera running camouflage mode */ - if ($this->options->engine & Constants\EngineType::PRESTO) { - $this->features[] = 'presto'; + /* If it claims not to be Gecko, but it is probably Gecko running camouflage mode */ + if ($this->options->engine & Constants\EngineType::GECKO) { + $this->data->features[] = 'gecko'; - if ($this->data->engine->name && $this->data->engine->name != 'Presto') { - $this->camouflage = true; - } + if ($this->data->engine->name && $this->data->engine->name != 'Gecko') { + $this->data->camouflage = true; + } - if (isset($this->data->browser->name) && $this->data->browser->name == 'Internet Explorer') { - $this->camouflage = true; - } + if (isset($this->data->browser->name) && $this->data->browser->name == 'Internet Explorer') { + $this->data->camouflage = true; } + } - /* If it claims not to be Gecko, but it is probably Gecko running camouflage mode */ - if ($this->options->engine & Constants\EngineType::GECKO) { - $this->features[] = 'gecko'; + /* If it claims not to be Webkit, but it is probably Webkit running camouflage mode */ + if ($this->options->engine & Constants\EngineType::WEBKIT) { + $this->data->features[] = 'webkit'; - if ($this->data->engine->name && $this->data->engine->name != 'Gecko') { - $this->camouflage = true; - } + if ($this->data->engine->name && ($this->data->engine->name != 'Blink' && $this->data->engine->name != 'Webkit')) { + $this->data->camouflage = true; + } - if (isset($this->data->browser->name) && $this->data->browser->name == 'Internet Explorer') { - $this->camouflage = true; - } + if (isset($this->data->browser->name) && $this->data->browser->name == 'Internet Explorer') { + $this->data->camouflage = true; } - /* If it claims not to be Webkit, but it is probably Webkit running camouflage mode */ - if ($this->options->engine & Constants\EngineType::WEBKIT) { - $this->features[] = 'webkit'; - - if ($this->data->engine->name && ($this->data->engine->name != 'Blink' && $this->data->engine->name != 'Webkit')) { - $this->camouflage = true; - } - - if (isset($this->data->browser->name) && $this->data->browser->name == 'Internet Explorer') { - $this->camouflage = true; - } - - /* IE 11 on mobile now supports Webkit APIs */ - if (isset($this->data->browser->name) && $this->data->browser->name == 'Mobile Internet Explorer' && - isset($this->data->browser->version) && $this->data->browser->version->toFloat() >= 11 && - isset($this->data->os->name) && $this->data->os->name == 'Windows Phone') { - $this->camouflage = false; - } - - /* IE 11 Developer Preview now supports Webkit APIs */ - if (isset($this->data->browser->name) && $this->data->browser->name == 'Internet Explorer' && - isset($this->data->browser->version) && $this->data->browser->version->toFloat() >= 11 && - isset($this->data->os->name) && $this->data->os->name == 'Windows') { - $this->camouflage = false; - } - - /* EdgeHTML rendering engine also appears to be WebKit */ - if (isset($this->data->engine->name) && $this->data->engine->name == 'EdgeHTML') { - $this->camouflage = false; - } + /* IE 11 on mobile now supports Webkit APIs */ + if (isset($this->data->browser->name) && $this->data->browser->name == 'Mobile Internet Explorer' + && isset($this->data->browser->version) && $this->data->browser->version->toFloat() >= 11 + && isset($this->data->os->name) && $this->data->os->name == 'Windows Phone' + ) { + $this->data->camouflage = false; } - if ($this->options->engine & Constants\EngineType::CHROMIUM) { - $this->features[] = 'chrome'; + /* IE 11 Developer Preview now supports Webkit APIs */ + if (isset($this->data->browser->name) && $this->data->browser->name == 'Internet Explorer' + && isset($this->data->browser->version) && $this->data->browser->version->toFloat() >= 11 + && isset($this->data->os->name) && $this->data->os->name == 'Windows' + ) { + $this->data->camouflage = false; + } - if ($this->data->engine->name && ($this->data->engine->name != 'EdgeHTML' && $this->data->engine->name != 'Blink' && $this->data->engine->name != 'Webkit')) { - $this->camouflage = true; - } + /* EdgeHTML rendering engine also appears to be WebKit */ + if (isset($this->data->engine->name) && $this->data->engine->name == 'EdgeHTML') { + $this->data->camouflage = false; } + } - /* If it claims to be Safari and uses V8, it is probably an Android device running camouflage mode */ - if ($this->data->engine->name == 'Webkit' && $this->options->engine & Constants\EngineType::V8) { - $this->features[] = 'v8'; + if ($this->options->engine & Constants\EngineType::CHROMIUM) { + $this->data->features[] = 'chrome'; - if (isset($this->data->browser->name) && $this->data->browser->name == 'Safari') { - $this->camouflage = true; - } + if ($this->data->engine->name && ($this->data->engine->name != 'EdgeHTML' && $this->data->engine->name != 'Blink' && $this->data->engine->name != 'Webkit')) { + $this->data->camouflage = true; } + } + /* If it claims to be Safari and uses V8, it is probably an Android device running camouflage mode */ + if ($this->data->engine->name == 'Webkit' && $this->options->engine & Constants\EngineType::V8) { + $this->data->features[] = 'v8'; + + if (isset($this->data->browser->name) && $this->data->browser->name == 'Safari') { + $this->data->camouflage = true; + } } } - if (isset($this->options->width) && isset($this->options->height)) { - if (isset($this->data->device->model)) { - /* If we have an iPad that is not 768 x 1024, we have an imposter */ - if ($this->data->device->model == 'iPad') { - if (($this->options->width != 0 && $this->options->height != 0) && ($this->options->width != 768 && $this->options->height != 1024) && ($this->options->width != 1024 && $this->options->height != 768)) { - $this->features[] = 'sizeMismatch'; - $this->camouflage = true; - } + return $this; + } + + private function &detectCamouflagedBasedOnFeatures() + { + if (isset($this->data->browser->name) && isset($this->data->os->name)) { + if ($this->data->os->name == 'iOS' && $this->data->browser->name != 'Opera Mini' && $this->data->browser->name != 'UC Browser' && isset($this->data->os->version)) { + + if ($this->data->os->version->toFloat() < 4.0 && $this->options->features & Constants\Feature::SANDBOX) { + $this->data->features[] = 'foundSandbox'; + $this->data->camouflage = true; } - /* If we have an iPhone or iPod that is not 320 x 480, we have an imposter */ - /* - if ($this->data->device->model == 'iPhone' || $this->data->device->model == 'iPod') { - if (($this->options->width != 0 && $this->options->height != 0) && - ($this->options->width != 320 && $this->options->height != 480) && - ($this->options->width != 480 && $this->options->height != 320) - ) { - $this->features[] = 'sizeMismatch'; - $this->camouflage = true; - } + if ($this->data->os->version->toFloat() < 4.2 && $this->options->features & Constants\Feature::WEBSOCKET) { + $this->data->features[] = 'foundSockets'; + $this->data->camouflage = true; } - */ - } - } - if (isset($this->options->features)) { - if (isset($this->data->browser->name) && isset($this->data->os->name)) { - if ($this->data->os->name == 'iOS' && $this->data->browser->name != 'Opera Mini' && $this->data->browser->name != 'UC Browser' && isset($this->data->os->version)) { - - if ($this->data->os->version->toFloat() < 4.0 && $this->options->features & Constants\Feature::SANDBOX) { - $this->features[] = 'foundSandbox'; - $this->camouflage = true; - } - - if ($this->data->os->version->toFloat() < 4.2 && $this->options->features & Constants\Feature::WEBSOCKET) { - $this->features[] = 'foundSockets'; - $this->camouflage = true; - } - - if ($this->data->os->version->toFloat() < 5.0 && $this->options->features & Constants\Feature::WORKER) { - $this->features[] = 'foundWorker'; - $this->camouflage = true; - } - - if ($this->data->os->version->toFloat() > 2.1 && !$this->options->features & Constants\Feature::APPCACHE) { - $this->features[] = 'noAppCache'; - $this->camouflage = true; - } + if ($this->data->os->version->toFloat() < 5.0 && $this->options->features & Constants\Feature::WORKER) { + $this->data->features[] = 'foundWorker'; + $this->data->camouflage = true; } - if ($this->data->os->name != 'iOS' && $this->data->browser->name == 'Safari' && isset($this->data->browser->version)) { + if ($this->data->os->version->toFloat() > 2.1 && !$this->options->features & Constants\Feature::APPCACHE) { + $this->data->features[] = 'noAppCache'; + $this->data->camouflage = true; + } + } - if ($this->data->browser->version->toFloat() < 4.0 && $this->options->features & Constants\Feature::APPCACHE) { - $this->features[] = 'foundAppCache'; - $this->camouflage = true; - } + if ($this->data->os->name != 'iOS' && $this->data->browser->name == 'Safari' && isset($this->data->browser->version)) { - if ($this->data->browser->version->toFloat() < 4.1 && $this->options->features & Constants\Feature::HISTORY) { - $this->features[] = 'foundHistory'; - $this->camouflage = true; - } + if ($this->data->browser->version->toFloat() < 4.0 && $this->options->features & Constants\Feature::APPCACHE) { + $this->data->features[] = 'foundAppCache'; + $this->data->camouflage = true; + } + + if ($this->data->browser->version->toFloat() < 4.1 && $this->options->features & Constants\Feature::HISTORY) { + $this->data->features[] = 'foundHistory'; + $this->data->camouflage = true; + } - if ($this->data->browser->version->toFloat() < 5.1 && $this->options->features & Constants\Feature::FULLSCREEN) { - $this->features[] = 'foundFullscreen'; - $this->camouflage = true; - } + if ($this->data->browser->version->toFloat() < 5.1 && $this->options->features & Constants\Feature::FULLSCREEN) { + $this->data->features[] = 'foundFullscreen'; + $this->data->camouflage = true; + } - if ($this->data->browser->version->toFloat() < 5.2 && $this->options->features & Constants\Feature::FILEREADER) { - $this->features[] = 'foundFileReader'; - $this->camouflage = true; - } + if ($this->data->browser->version->toFloat() < 5.2 && $this->options->features & Constants\Feature::FILEREADER) { + $this->data->features[] = 'foundFileReader'; + $this->data->camouflage = true; } } } diff --git a/src/Analyser/Corrections.php b/src/Analyser/Corrections.php index ce68b72..ae8dc2a 100644 --- a/src/Analyser/Corrections.php +++ b/src/Analyser/Corrections.php @@ -3,8 +3,6 @@ namespace WhichBrowser\Analyser; use WhichBrowser\Constants; -use WhichBrowser\Model\Family; -use WhichBrowser\Model\Using; use WhichBrowser\Model\Version; trait Corrections @@ -35,6 +33,10 @@ private function &applyCorrections() $this->fixMidoriEngineName(); } + if (isset($this->data->browser->name) && isset($this->data->engine->name)) { + $this->fixNineSkyEngineName(); + } + if (isset($this->data->browser->name) && isset($this->data->browser->family)) { $this->hideFamilyIfEqualToBrowser(); } @@ -67,6 +69,14 @@ private function fixMidoriEngineName() } } + private function fixNineSkyEngineName() + { + if ($this->data->browser->name == 'NineSky' && $this->data->engine->name != 'Webkit') { + $this->data->engine->name = 'Webkit'; + $this->data->engine->version = null; + } + } + private function correctVersionOfMobileInternetExplorer() { if ($this->data->os->name == 'Windows Phone' && $this->data->browser->name == 'Mobile Internet Explorer') { diff --git a/src/Analyser/Header/BrowserId.php b/src/Analyser/Header/BrowserId.php index d6d129f..26d43da 100644 --- a/src/Analyser/Header/BrowserId.php +++ b/src/Analyser/Header/BrowserId.php @@ -24,7 +24,7 @@ public function __construct($header, &$data) /* Detect the correct browser based on the header */ - $browser = Data\BrowserIds::identify('android', $header); + $browser = Data\BrowserIds::identify($header); if ($browser) { if (!isset($this->data->browser->name)) { $this->data->browser->name = $browser; diff --git a/src/Analyser/Header/OperaMini.php b/src/Analyser/Header/OperaMini.php index 07111c4..20989e7 100644 --- a/src/Analyser/Header/OperaMini.php +++ b/src/Analyser/Header/OperaMini.php @@ -10,7 +10,9 @@ public function __construct($header, &$data) { $this->data =& $data; - @list($manufacturer, $model) = explode(' # ', $header); + $parts = explode(' # ', $header); + $manufacturer = isset($parts[0]) ? $parts[0] : ''; + $model = isset($parts[1]) ? $parts[1] : ''; if ($manufacturer != '?' && $model != '?') { if (!$this->data->device->identified && $this->data->os->name == 'Bada') { @@ -21,7 +23,7 @@ public function __construct($header, &$data) } } - if (!$this->data->device->identified && $this->data->os->name == 'Blackberry') { + if (!$this->data->device->identified && $this->data->os->name == 'BlackBerry OS') { $device = Data\DeviceModels::identify('blackberry', $model); if ($device->identified) { $device->identified |= $this->data->device->identified; diff --git a/src/Analyser/Header/UCBrowserNew.php b/src/Analyser/Header/UCBrowserNew.php index 0ace3eb..b2bf29b 100644 --- a/src/Analyser/Header/UCBrowserNew.php +++ b/src/Analyser/Header/UCBrowserNew.php @@ -2,7 +2,6 @@ namespace WhichBrowser\Analyser\Header; -use WhichBrowser\Constants; use WhichBrowser\Data; use WhichBrowser\Model\Version; @@ -19,15 +18,23 @@ public function __construct($header, &$data) } /* Find os */ - if (preg_match('/ov\(Android ([0-9\.]+)/u', $header, $match)) { + if (preg_match('/pf\(Java\)/u', $header)) { + if (preg_match('/dv\(([^\)]*)\)/u', $header, $match)) { + if ($this->identifyBasedOnModel($match[1])) { + return; + } + } + } + + if (preg_match('/pf\(Linux\)/u', $header) && preg_match('/ov\((?:Android )?([0-9\.]+)/u', $header, $match)) { $this->data->os->name = 'Android'; $this->data->os->version = new Version([ 'value' => $match[1] ]); } - if (preg_match('/pf\(Symbian\)/u', $header) && preg_match('/ov\(S60V5/u', $header)) { + if (preg_match('/pf\(Symbian\)/u', $header) && preg_match('/ov\(S60V([0-9])/u', $header, $match)) { if (!isset($this->data->os->name) || $this->data->os->name != 'Series60') { $this->data->os->name = 'Series60'; - $this->data->os->version = new Version([ 'value' => 5 ]); + $this->data->os->version = new Version([ 'value' => $match[1] ]); } } @@ -75,7 +82,7 @@ public function __construct($header, &$data) } if (isset($this->data->os->name) && $this->data->os->name == 'Series60') { - if (preg_match('/dv\((?:Nokia)?([^\)]*)\)/u', $header, $match)) { + if (preg_match('/dv\((?:Nokia)?([^\)]*)\)/iu', $header, $match)) { $device = Data\DeviceModels::identify('s60', $match[1]); if ($device) { @@ -104,4 +111,61 @@ public function __construct($header, &$data) } } } + + private function identifyBasedOnModel($model) + { + $model = preg_replace('/^Nokia/iu', '', $model); + + $device = Data\DeviceModels::identify('s60', $model); + if ($device->identified) { + $device->identified |= $this->data->device->identified; + $this->data->device = $device; + + if (!isset($this->data->os->name) || $this->data->os->name != 'Series60') { + $this->data->os->name = 'Series60'; + $this->data->os->version = null; + } + + return true; + } + + $device = Data\DeviceModels::identify('s40', $model); + if ($device->identified) { + $device->identified |= $this->data->device->identified; + $this->data->device = $device; + + if (!isset($this->data->os->name) || $this->data->os->name != 'Series40') { + $this->data->os->name = 'Series40'; + $this->data->os->version = null; + } + + return true; + } + + $device = Data\DeviceModels::identify('bada', $model); + if ($device->identified) { + $device->identified |= $this->data->device->identified; + $this->data->device = $device; + + if (!isset($this->data->os->name) || $this->data->os->name != 'Bada') { + $this->data->os->name = 'Bada'; + $this->data->os->version = null; + } + + return true; + } + + $device = Data\DeviceModels::identify('touchwiz', $model); + if ($device->identified) { + $device->identified |= $this->data->device->identified; + $this->data->device = $device; + + if (!isset($this->data->os->name) || $this->data->os->name != 'Touchwiz') { + $this->data->os->name = 'Touchwiz'; + $this->data->os->version = null; + } + + return true; + } + } } diff --git a/src/Analyser/Header/UCBrowserOld.php b/src/Analyser/Header/UCBrowserOld.php index 9dc177d..12caa9a 100644 --- a/src/Analyser/Header/UCBrowserOld.php +++ b/src/Analyser/Header/UCBrowserOld.php @@ -4,8 +4,6 @@ use WhichBrowser\Parser; use WhichBrowser\Constants; -use WhichBrowser\Data; -use WhichBrowser\Model\Version; class UCBrowserOld { @@ -16,8 +14,7 @@ public function __construct($header, &$data) if ($this->data->device->type == Constants\DeviceType::DESKTOP) { $this->data->device->type = Constants\DeviceType::MOBILE; - unset($this->data->os->name); - unset($this->data->os->version); + $this->data->os->reset(); } if (!isset($this->data->browser->name) || $this->data->browser->name != 'UC Browser') { @@ -25,10 +22,13 @@ public function __construct($header, &$data) $this->data->browser->version = null; } + $this->data->browser->mode = 'proxy'; + $this->data->engine->reset([ 'name' => 'Gecko' ]); + $extra = new Parser([ 'headers' => [ 'User-Agent' => $header ]]); if ($extra->device->type != Constants\DeviceType::DESKTOP) { - if (isset($extra->os->version)) { + if ($extra->os->getName() !== '' && ($this->data->os->getName() === '' || $extra->os->getVersion() !== '')) { $this->data->os = $extra->os; } if ($extra->device->identified) { diff --git a/src/Analyser/Header/Useragent/Browser.php b/src/Analyser/Header/Useragent/Browser.php index 4796872..29d1eb0 100644 --- a/src/Analyser/Header/Useragent/Browser.php +++ b/src/Analyser/Header/Useragent/Browser.php @@ -159,7 +159,7 @@ private function detectChrome($ua) /* Webview for Android 4.4 and higher */ - if (implode('.', array_slice(explode('.', $version), 1, 2)) == '0.0' && preg_match('/Version\//u', $ua)) { + if (implode('.', array_slice(explode('.', $version), 1, 2)) == '0.0' && (preg_match('/Version\//u', $ua) || preg_match('/Release\//u', $ua))) { $this->data->browser->using = new Using([ 'name' => 'Chromium WebView', 'version' => new Version([ 'value' => explode('.', $version)[0] ]) ]); $this->data->browser->stock = true; $this->data->browser->name = null; @@ -339,11 +339,11 @@ private function detectExplorer($ua) $this->data->engine->name = 'Tasman'; $this->data->device->type = Constants\DeviceType::DESKTOP; - if ($this->data->browser->version->toFloat() >= 5.11 && $this->data->browser->version->toFloat() <= 5.13) { + if ($this->data->browser->version->is('>=', '5.1.1') && $this->data->browser->version->is('<=', '5.1.3')) { $this->data->os->name = 'OS X'; } - if ($this->data->browser->version->toFloat() >= 5.2) { + if ($this->data->browser->version->is('>=', '5.2')) { $this->data->os->name = 'OS X'; } } @@ -414,15 +414,15 @@ private function detectOpera($ua) $this->data->browser->name = 'Opera'; $this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]); - if (preg_match('/Edition Developer/u', $ua)) { + if (preg_match('/Edition Developer/iu', $ua)) { $this->data->browser->channel = 'Developer'; } - if (preg_match('/Edition Next/u', $ua)) { + if (preg_match('/Edition Next/iu', $ua)) { $this->data->browser->channel = 'Next'; } - if (preg_match('/Edition beta/u', $ua)) { + if (preg_match('/Edition Beta/iu', $ua)) { $this->data->browser->channel = 'Beta'; } @@ -757,7 +757,7 @@ private function detectUC($ua) } if (isset($this->data->os->name) && $this->data->os->name == 'Linux') { - $this->data->os->name = ''; + $this->data->os->reset(); } if (preg_match('/^IUC ?\(U; ?iOS ([0-9\._]+);/u', $ua, $match)) { @@ -797,6 +797,27 @@ private function detectUC($ua) } } + if (preg_match('/\(Symbian;/u', $ua)) { + $this->data->os->name = 'Series60'; + $this->data->os->version = null; + + if (preg_match('/S60 V([0-9])/u', $ua, $match)) { + $this->data->os->version = new Version([ 'value' => $match[1] ]); + } + + if (preg_match('/; Nokia([^;]+)\)/iu', $ua, $match)) { + $this->data->device->model = $match[1]; + $this->data->device->identified |= Constants\Id::PATTERN; + + $device = Data\DeviceModels::identify('s60', $match[1]); + + if ($device->identified) { + $device->identified |= $this->data->device->identified; + $this->data->device = $device; + } + } + } + if (preg_match('/\(Windows;/u', $ua)) { $this->data->os->name = 'Windows Phone'; $this->data->os->version = null; @@ -922,13 +943,9 @@ private function detectUCEngine($ua) if ($this->data->browser->name == 'UC Browser') { if (!preg_match("/UBrowser\//", $ua) && ($this->data->device->type == 'desktop' || (isset($this->data->os->name) && ($this->data->os->name == 'Windows' || $this->data->os->name == 'OS X')))) { $this->data->device->type = Constants\DeviceType::MOBILE; - $this->data->browser->mode = 'desktop'; - - unset($this->data->engine->name); - unset($this->data->engine->version); - unset($this->data->os->name); - unset($this->data->os->version); + $this->data->engine->reset(); + $this->data->os->reset(); } elseif (!isset($this->data->os->name) || ($this->data->os->name != 'iOS' && $this->data->os->name != 'Windows Phone' && $this->data->os->name != 'Windows' && $this->data->os->name != 'Android' && (!isset($this->data->os->family) || $this->data->os->family->getName() != 'Android'))) { $this->data->engine->name = 'Gecko'; unset($this->data->engine->version); @@ -1093,20 +1110,21 @@ private function detectEspial($ua) private function detectIris($ua) { - if (preg_match('/Iris[ \/]/u', $ua)) { + if (preg_match('/Iris\//u', $ua)) { $this->data->browser->name = 'Iris'; - - $this->data->device->type = Constants\DeviceType::MOBILE; - $this->data->device->manufacturer = null; - $this->data->device->model = null; - - $this->data->os->name = 'Windows Mobile'; - $this->data->os->version = null; + $this->data->browser->hidden = false; + $this->data->browser->stock = false; if (preg_match('/Iris\/([0-9.]*)/u', $ua, $match)) { $this->data->browser->version = new Version([ 'value' => $match[1] ]); } + $this->data->device->reset(); + $this->data->device->type = Constants\DeviceType::MOBILE; + + $this->data->os->reset(); + $this->data->os->name = 'Windows Mobile'; + if (preg_match('/ WM([0-9]) /u', $ua, $match)) { $this->data->os->version = new Version([ 'value' => $match[1] . '.0' ]); } else { @@ -1380,20 +1398,20 @@ private function detectSpecficBrowsers($ua) /* NineSky */ if (preg_match('/Ninesky(?:-android-mobile(?:-cn)?)?\/([0-9.]*)/u', $ua, $match)) { + $this->data->browser->reset(); $this->data->browser->name = 'NineSky'; $this->data->browser->version = new Version([ 'value' => $match[1] ]); if (isset($this->data->device->manufacturer) && $this->data->device->manufacturer == 'Apple') { - unset($this->data->device->manufacturer); - unset($this->data->device->model); - unset($this->data->device->identifier); - $this->data->device->identified = Constants\Id::NONE; + $this->data->device->reset(); } - if (isset($this->data->os->name) && $this->data->os->name != 'Android') { + if (!$this->data->os->isFamily('Android')) { + $this->data->os->reset(); $this->data->os->name = 'Android'; - $this->data->os->version = null; } + + $this->data->device->type = Constants\DeviceType::MOBILE; } /* Skyfire */ @@ -1645,6 +1663,7 @@ private function detectRemainingBrowsers($ua) [ 'name' => 'Google Earth', 'regexp' => '/Google Earth\/([0-9.]*)/u' ], [ 'name' => 'Google Desktop', 'regexp' => '/Google Desktop\/([0-9.]*)/u', 'details' => 2 ], + [ 'name' => 'Google Search', 'regexp' => '/GSA\/([0-9.]*)/u', 'details' => 3 ], [ 'name' => 'EA Origin', 'regexp' => '/Origin\/([0-9.]*)/u' ], [ 'name' => 'SecondLife', 'regexp' => '/SecondLife\/([0-9.]*)/u' ], @@ -1739,7 +1758,6 @@ private function detectRemainingBrowsers($ua) [ 'name' => 'Baidu Hao123', 'regexp' => '/hao123\/([0-9.]*)/u', 'details' => 2 ], [ 'name' => 'Black Wren', 'regexp' => '/BlackWren\/([0-9.]*)/u', 'details' => 2 ], [ 'name' => 'Blazer', 'regexp' => '/Blazer\/([0-9.]*)/u' ], - [ 'name' => 'BrightSign', 'regexp' => '/BrightSign\/([0-9.]*)/u', 'type' => Constants\DeviceType::SIGNAGE ], [ 'name' => 'Bunjalloo', 'regexp' => '/Bunjalloo\/([0-9.]*)/u' ], // Browser for the Nintento DS [ 'name' => 'Byffox', 'regexp' => '/Byffox\/([0-9.]*)/u', 'type' => Constants\DeviceType::DESKTOP ], [ 'name' => 'Camino', 'regexp' => '/Camino\/([0-9.]*)/u', 'type' => Constants\DeviceType::DESKTOP ], @@ -1789,10 +1807,12 @@ private function detectRemainingBrowsers($ua) [ 'name' => 'Lbbrowser', 'regexp' => '/LBBROWSER/u' ], [ 'name' => 'Leechcraft', 'regexp' => '/Leechcraft(?:\/([0-9.]*))?/u', 'details' => 2 ], [ 'name' => 'LieBaoFast', 'regexp' => '/LieBaoFast\/([0-9.]*)/u' ], + [ 'name' => 'Links', 'regexp' => '/Links \(([0-9.]*)/u' ], [ 'name' => 'Lobo', 'regexp' => '/Lobo\/([0-9.]*)/u', 'type' => Constants\DeviceType::DESKTOP ], [ 'name' => 'Lotus Expeditor', 'regexp' => '/Gecko Expeditor ([0-9.]*)/u', 'details' => 3 ], [ 'name' => 'Lunascape', 'regexp' => '/Lunascape[\/| ]([0-9.]*)/u', 'details' => 3 ], [ 'name' => 'Lynx', 'regexp' => '/Lynx\/([0-9.]*)/u' ], + [ 'name' => 'Motorola Internet Browser', 'regexp' => '/MIB\/([0-9.]*)/u' ], [ 'name' => 'iLunascape', 'regexp' => '/iLunascape\/([0-9.]*)/u', 'details' => 3 ], [ 'name' => 'Intermec Browser', 'regexp' => '/Intermec\/([0-9.]*)/u', 'details' => 2 ], [ 'name' => 'Jig Browser', 'regexp' => '/jig browser(?: core|9i?)/u' ], @@ -1877,14 +1897,19 @@ private function detectRemainingBrowsers($ua) [ 'name' => 'Android Download Manager', 'regexp' => '/AndroidDownloadManager\/([0-9.]*)/u' ], [ 'name' => 'Open Sankoré', 'regexp' => '/Open-Sankore\/([0-9.]*)/u', 'type' => Constants\DeviceType::WHITEBOARD ], + + [ 'name' => 'Adapi', 'regexp' => '/ ADAPI\/([0-9.]*)/u', 'hidden' => true, 'type' => Constants\DeviceType::SIGNAGE ], + [ 'name' => 'BrightSign', 'regexp' => '/BrightSign\/([0-9.]*)/u', 'type' => Constants\DeviceType::SIGNAGE ], [ 'name' => 'Coship MMCP', 'regexp' => '/Coship_MMCP_([0-9.]*)/u', 'type' => Constants\DeviceType::SIGNAGE ], ]; - for ($b = 0; $b < count($browsers); $b++) { + + $count = count($browsers); + for ($b = 0; $b < $count; $b++) { if (preg_match($browsers[$b]['regexp'], $ua, $match)) { $this->data->browser->name = $browsers[$b]['name']; $this->data->browser->channel = ''; - $this->data->browser->hidden = false; + $this->data->browser->hidden = isset($browsers[$b]['hidden']) ? $browsers[$b]['hidden'] : false; $this->data->browser->stock = false; if (isset($match[1]) && $match[1]) { diff --git a/src/Analyser/Header/Useragent/Device/Cars.php b/src/Analyser/Header/Useragent/Device/Cars.php index db27fbe..b80368c 100644 --- a/src/Analyser/Header/Useragent/Device/Cars.php +++ b/src/Analyser/Header/Useragent/Device/Cars.php @@ -22,12 +22,12 @@ private function detectCars($ua) private function detectTesla($ua) { if (preg_match('/QtCarBrowser/u', $ua)) { - $this->data->os->name = ''; - - $this->data->device->manufacturer = 'Tesla'; - $this->data->device->model = 'Model S'; - $this->data->device->type = Constants\DeviceType::CAR; - $this->data->device->identified |= Constants\Id::MATCH_UA; + $this->data->os->reset(); + $this->data->device->setIdentification([ + 'manufacturer' => 'Tesla', + 'model' => 'Model S', + 'type' => Constants\DeviceType::CAR + ]); } } } diff --git a/src/Analyser/Header/Useragent/Device/Ereader.php b/src/Analyser/Header/Useragent/Device/Ereader.php index 3250804..03d9702 100644 --- a/src/Analyser/Header/Useragent/Device/Ereader.php +++ b/src/Analyser/Header/Useragent/Device/Ereader.php @@ -26,10 +26,11 @@ private function detectKindle($ua) { if (preg_match('/Kindle/u', $ua) && !preg_match('/Fire/u', $ua)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'Amazon'; - $this->data->device->series = 'Kindle'; - $this->data->device->type = Constants\DeviceType::EREADER; + $this->data->device->setIdentification([ + 'manufacturer' => 'Amazon', + 'series' => 'Kindle', + 'type' => Constants\DeviceType::EREADER + ]); if (preg_match('/Kindle SkipStone/u', $ua)) { $this->data->device->model = 'Kindle Touch or later'; @@ -46,10 +47,9 @@ private function detectKindle($ua) } if (!empty($this->data->device->model)) { + $this->data->device->generic = false; $this->data->device->series = null; } - - $this->data->device->identified |= Constants\Id::MATCH_UA; } } @@ -59,12 +59,12 @@ private function detectKindle($ua) private function detectNook($ua) { if (preg_match('/nook browser/u', $ua)) { - $this->data->os->name = 'Android'; - - $this->data->device->manufacturer = 'Barnes & Noble'; - $this->data->device->series = 'NOOK'; - $this->data->device->type = Constants\DeviceType::EREADER; - $this->data->device->identified |= Constants\Id::MATCH_UA; + $this->data->os->reset([ 'name' => 'Android' ]); + $this->data->device->setIdentification([ + 'manufacturer' => 'Barnes & Noble', + 'series' => 'NOOK', + 'type' => Constants\DeviceType::EREADER + ]); } } @@ -75,11 +75,11 @@ private function detectBookeen($ua) { if (preg_match('/bookeen\/cybook/u', $ua)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'Bookeen'; - $this->data->device->series = 'Cybook'; - $this->data->device->type = Constants\DeviceType::EREADER; - $this->data->device->identified |= Constants\Id::MATCH_UA; + $this->data->device->setIdentification([ + 'manufacturer' => 'Bookeen', + 'series' => 'Cybook', + 'type' => Constants\DeviceType::EREADER + ]); } } @@ -90,11 +90,11 @@ private function detectKobo($ua) { if (preg_match('/Kobo Touch/u', $ua, $match)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'Kobo'; - $this->data->device->series = 'eReader'; - $this->data->device->type = Constants\DeviceType::EREADER; - $this->data->device->identified |= Constants\Id::MATCH_UA; + $this->data->device->setIdentification([ + 'manufacturer' => 'Kobo', + 'series' => 'eReader', + 'type' => Constants\DeviceType::EREADER + ]); } } @@ -104,31 +104,31 @@ private function detectKobo($ua) private function detectSonyreader($ua) { if (preg_match('/EBRD([0-9]+)/u', $ua, $match)) { - $this->data->os->reset(); - - $this->data->device->manufacturer = 'Sony'; - $this->data->device->series = 'Reader'; - $this->data->device->type = Constants\DeviceType::EREADER; - $this->data->device->identified |= Constants\Id::MATCH_UA; - switch ($match[1]) { case '1101': - $this->data->device->model = 'PRS-T1'; - $this->data->device->generic = false; + $model = 'PRS-T1'; break; case '1102': - $this->data->device->model = 'PRS-T1'; - $this->data->device->generic = false; + $model = 'PRS-T1'; break; case '1201': - $this->data->device->model = 'PRS-T2'; - $this->data->device->generic = false; + $model = 'PRS-T2'; break; case '1301': - $this->data->device->model = 'PRS-T3'; - $this->data->device->generic = false; + $model = 'PRS-T3'; break; + default: + $model = null; } + + $this->data->os->reset(); + $this->data->device->setIdentification([ + 'manufacturer' => 'Sony', + 'model' => $model, + 'series' => 'Reader', + 'type' => Constants\DeviceType::EREADER + ]); + } } @@ -138,58 +138,50 @@ private function detectSonyreader($ua) private function detectPocketbook($ua) { if (preg_match('/PocketBook\/([0-9]+)/u', $ua, $match)) { - $this->data->os->reset(); - - $this->data->device->manufacturer = 'PocketBook'; - $this->data->device->type = Constants\DeviceType::EREADER; - $this->data->device->identified |= Constants\Id::MATCH_UA; - switch ($match[1]) { case '515': - $this->data->device->model = 'Mini'; - $this->data->device->generic = false; + $model = 'Mini'; break; case '614': - $this->data->device->model = 'Basic 2'; - $this->data->device->generic = false; + $model = 'Basic 2'; break; case '622': - $this->data->device->model = 'Touch'; - $this->data->device->generic = false; + $model = 'Touch'; break; case '623': - $this->data->device->model = 'Touch Lux'; - $this->data->device->generic = false; + $model = 'Touch Lux'; break; case '624': - $this->data->device->model = 'Basic Touch'; - $this->data->device->generic = false; + $model = 'Basic Touch'; break; case '626': - $this->data->device->model = 'Touch Lux 2'; - $this->data->device->generic = false; + $model = 'Touch Lux 2'; break; case '630': - $this->data->device->model = 'Sense'; - $this->data->device->generic = false; + $model = 'Sense'; break; case '640': - $this->data->device->model = 'Auqa'; - $this->data->device->generic = false; + $model = 'Auqa'; break; case '650': - $this->data->device->model = 'Ultra'; - $this->data->device->generic = false; + $model = 'Ultra'; break; case '801': - $this->data->device->model = 'Color Lux'; - $this->data->device->generic = false; + $model = 'Color Lux'; break; case '840': - $this->data->device->model = 'InkPad'; - $this->data->device->generic = false; + $model = 'InkPad'; break; + default: + $model = null; } + + $this->data->os->reset(); + $this->data->device->setIdentification([ + 'manufacturer' => 'PocketBook', + 'model' => $model, + 'type' => Constants\DeviceType::EREADER + ]); } } @@ -200,17 +192,16 @@ private function detectIriver($ua) { if (preg_match('/Iriver ;/u', $ua)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'iRiver'; - $this->data->device->series = 'Story'; - $this->data->device->type = Constants\DeviceType::EREADER; + $this->data->device->setIdentification([ + 'manufacturer' => 'iRiver', + 'series' => 'Story', + 'type' => Constants\DeviceType::EREADER + ]); if (preg_match('/EB07/u', $ua)) { $this->data->device->model = 'Story HD EB07'; $this->data->device->generic = false; } - - $this->data->device->identified |= Constants\Id::MATCH_UA; } } } diff --git a/src/Analyser/Header/Useragent/Device/Gaming.php b/src/Analyser/Header/Useragent/Device/Gaming.php index ac752fa..ff0b284 100644 --- a/src/Analyser/Header/Useragent/Device/Gaming.php +++ b/src/Analyser/Header/Useragent/Device/Gaming.php @@ -34,86 +34,76 @@ private function detectNintendo($ua) if (preg_match('/Nintendo Wii/u', $ua)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'Nintendo'; - $this->data->device->model = 'Wii'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::CONSOLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->device->setIdentification([ + 'manufacturer' => 'Nintendo', + 'model' => 'Wii', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::CONSOLE + ]); } /* Wii U */ if (preg_match('/Nintendo Wii ?U/u', $ua)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'Nintendo'; - $this->data->device->model = 'Wii U'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::CONSOLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->device->setIdentification([ + 'manufacturer' => 'Nintendo', + 'model' => 'Wii U', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::CONSOLE + ]); } /* DS */ if (preg_match('/Nintendo DS/u', $ua)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'Nintendo'; - $this->data->device->model = 'DS'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::PORTABLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->device->setIdentification([ + 'manufacturer' => 'Nintendo', + 'model' => 'DS', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::PORTABLE + ]); } /* DSi */ if (preg_match('/Nintendo DSi/u', $ua)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'Nintendo'; - $this->data->device->model = 'DSi'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::PORTABLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->device->setIdentification([ + 'manufacturer' => 'Nintendo', + 'model' => 'DSi', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::PORTABLE + ]); } /* 3DS */ if (preg_match('/Nintendo 3DS/u', $ua)) { $this->data->os->reset(); - - if (preg_match('/Version\/([0-9.]*)/u', $ua, $match)) { - $this->data->os->version = new Version([ 'value' => $match[1] ]); - } - - $this->data->device->manufacturer = 'Nintendo'; - $this->data->device->model = '3DS'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::PORTABLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->os->identifyVersion('/Version\/([0-9.]*)/u', $ua); + + $this->data->device->setIdentification([ + 'manufacturer' => 'Nintendo', + 'model' => '3DS', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::PORTABLE + ]); } /* New 3DS */ if (preg_match('/New Nintendo 3DS/u', $ua)) { $this->data->os->reset(); - - if (preg_match('/Version\/([0-9.]*)/u', $ua, $match)) { - $this->data->os->version = new Version([ 'value' => $match[1] ]); - } - - $this->data->device->manufacturer = 'Nintendo'; - $this->data->device->model = 'New 3DS'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::PORTABLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->os->identifyVersion('/Version\/([0-9.]*)/u', $ua); + + $this->data->device->setIdentification([ + 'manufacturer' => 'Nintendo', + 'model' => 'New 3DS', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::PORTABLE + ]); } } @@ -126,30 +116,26 @@ private function detectPlaystation($ua) if (preg_match('/PlayStation Portable/u', $ua)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'Sony'; - $this->data->device->model = 'Playstation Portable'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::PORTABLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->device->setIdentification([ + 'manufacturer' => 'Sony', + 'model' => 'Playstation Portable', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::PORTABLE + ]); } /* PlayStation Vita */ if (preg_match('/PlayStation Vita/u', $ua)) { $this->data->os->reset(); + $this->data->os->identifyVersion('/PlayStation Vita ([0-9.]*)/u', $ua); - if (preg_match('/PlayStation Vita ([0-9.]*)/u', $ua, $match)) { - $this->data->os->version = new Version([ 'value' => $match[1] ]); - } - - $this->data->device->manufacturer = 'Sony'; - $this->data->device->model = 'Playstation Vita'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::PORTABLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->device->setIdentification([ + 'manufacturer' => 'Sony', + 'model' => 'Playstation Vita', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::PORTABLE + ]); if (preg_match('/VTE\//u', $ua)) { $this->data->device->model = 'Playstation TV'; @@ -160,34 +146,28 @@ private function detectPlaystation($ua) if (preg_match('/PlayStation 3/ui', $ua)) { $this->data->os->reset(); - - if (preg_match('/PLAYSTATION 3;? ([0-9.]*)/u', $ua, $match)) { - $this->data->os->version = new Version([ 'value' => $match[1] ]); - } - - $this->data->device->manufacturer = 'Sony'; - $this->data->device->model = 'Playstation 3'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::CONSOLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->os->identifyVersion('/PLAYSTATION 3;? ([0-9.]*)/u', $ua); + + $this->data->device->setIdentification([ + 'manufacturer' => 'Sony', + 'model' => 'Playstation 3', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::CONSOLE + ]); } /* PlayStation 4 */ if (preg_match('/PlayStation 4/ui', $ua)) { $this->data->os->reset(); - - if (preg_match('/PlayStation 4 ([0-9.]*)/u', $ua, $match)) { - $this->data->os->version = new Version([ 'value' => $match[1] ]); - } - - $this->data->device->manufacturer = 'Sony'; - $this->data->device->model = 'Playstation 4'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::CONSOLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->os->identifyVersion('/PlayStation 4 ([0-9.]*)/u', $ua); + + $this->data->device->setIdentification([ + 'manufacturer' => 'Sony', + 'model' => 'Playstation 4', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::CONSOLE + ]); } } @@ -200,13 +180,12 @@ private function detectXbox($ua) if (preg_match('/Xbox\)$/u', $ua, $match)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'Microsoft'; - $this->data->device->model = 'Xbox 360'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::CONSOLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->device->setIdentification([ + 'manufacturer' => 'Microsoft', + 'model' => 'Xbox 360', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::CONSOLE + ]); } /* Xbox One */ @@ -221,12 +200,12 @@ private function detectXbox($ua) $this->data->os->reset(); } - $this->data->device->manufacturer = 'Microsoft'; - $this->data->device->model = 'Xbox One'; - $this->data->device->type = Constants\DeviceType::GAMING; - $this->data->device->subtype = Constants\DeviceSubType::CONSOLE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->device->setIdentification([ + 'manufacturer' => 'Microsoft', + 'model' => 'Xbox One', + 'type' => Constants\DeviceType::GAMING, + 'subtype' => Constants\DeviceSubType::CONSOLE + ]); } } } diff --git a/src/Analyser/Header/Useragent/Device/Media.php b/src/Analyser/Header/Useragent/Device/Media.php index b8bf640..a2584af 100644 --- a/src/Analyser/Header/Useragent/Device/Media.php +++ b/src/Analyser/Header/Useragent/Device/Media.php @@ -20,12 +20,11 @@ private function detectZune($ua) { if (preg_match('/Microsoft ZuneHD/u', $ua)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'Microsoft'; - $this->data->device->model = 'Zune HD'; - $this->data->device->type = Constants\DeviceType::MEDIA; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->device->setIdentification([ + 'manufacturer' => 'Microsoft', + 'model' => 'Zune HD', + 'type' => Constants\DeviceType::MEDIA + ]); } } } diff --git a/src/Analyser/Header/Useragent/Device/Mobile.php b/src/Analyser/Header/Useragent/Device/Mobile.php index 1520e4e..9ac5cf4 100644 --- a/src/Analyser/Header/Useragent/Device/Mobile.php +++ b/src/Analyser/Header/Useragent/Device/Mobile.php @@ -204,14 +204,10 @@ private function detectGenericMobileModels($ua) if (isset($this->data->os->name)) { for ($i = 0; $i < count($candidates); $i++) { - $result = false; - if (!isset($this->data->device->model) && !isset($this->data->device->manufacturer)) { if (isset($this->data->os->name) && ($this->data->os->name == 'Android' || $this->data->os->name == 'Linux')) { $device = Data\DeviceModels::identify('android', $candidates[$i]); if ($device->identified) { - $result = true; - $device->identified |= $this->data->device->identified; $this->data->device = $device; @@ -225,8 +221,6 @@ private function detectGenericMobileModels($ua) if (!isset($this->data->os->name) || $this->data->os->name == 'Windows' || $this->data->os->name == 'Windows Mobile' || $this->data->os->name == 'Windows CE') { $device = Data\DeviceModels::identify('wm', $candidates[$i]); if ($device->identified) { - $result = true; - $device->identified |= $this->data->device->identified; $this->data->device = $device; @@ -981,7 +975,7 @@ private function detectGenericMobileModels($ua) } - if (preg_match('/\(([A-Z][0-9]+[A-Z])[^;]*; ?FOMA/ui', $ua, $match)) { + if (preg_match('/\(([A-Z]+[0-9]+[A-Z])[^;]*; ?FOMA/ui', $ua, $match)) { $this->data->device->manufacturer = 'DoCoMo'; $this->data->device->model = Data\DeviceModels::cleanup($match[1]); $this->data->device->type = Constants\DeviceType::MOBILE; @@ -1005,7 +999,7 @@ private function detectGenericMobileModels($ua) $this->data->device->generic = false; } - if (preg_match('/J-PHONE\/[^\/]+\/([^\/]+)\//u', $ua, $match)) { + if (preg_match('/J-PHONE\/[^\/]+\/([^\/]+)(?:\/|$)/u', $ua, $match)) { $this->data->device->manufacturer = 'Softbank'; $this->data->device->model = Data\DeviceModels::cleanup($match[1]); $this->data->device->type = Constants\DeviceType::MOBILE; diff --git a/src/Analyser/Header/Useragent/Device/Signage.php b/src/Analyser/Header/Useragent/Device/Signage.php index fc5cc25..f2f13e9 100644 --- a/src/Analyser/Header/Useragent/Device/Signage.php +++ b/src/Analyser/Header/Useragent/Device/Signage.php @@ -12,25 +12,26 @@ private function detectSignage($ua) if (preg_match('/BrightSign\/[0-9\.]+(?:-[a-z0-9\-]+)? \(([^\)]+)/u', $ua, $match)) { $this->data->os->reset(); - - $this->data->device->manufacturer = 'BrightSign'; - $this->data->device->model = $match[1]; - $this->data->device->type = Constants\DeviceType::SIGNAGE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + $this->data->device->setIdentification([ + 'manufacturer' => 'BrightSign', + 'model' => $match[1], + 'type' => Constants\DeviceType::SIGNAGE + ]); } /* Iadea */ if (preg_match('/ADAPI/u', $ua) && preg_match('/\(MODEL:([^\)]+)\)/u', $ua, $match)) { - $this->data->os->reset(); - - $this->data->device->manufacturer = 'Iadea'; - $this->data->device->model = $match[1]; - $this->data->device->type = Constants\DeviceType::SIGNAGE; - $this->data->device->identified |= Constants\Id::MATCH_UA; - $this->data->device->generic = false; + if (!$this->data->isOs('Android')) { + $this->data->os->reset(); + } + + $this->data->device->setIdentification([ + 'manufacturer' => 'Iadea', + 'model' => $match[1], + 'type' => Constants\DeviceType::SIGNAGE + ]); } } } diff --git a/src/Analyser/Header/Useragent/Device/Television.php b/src/Analyser/Header/Useragent/Device/Television.php index 68cdc18..b3ba3ab 100644 --- a/src/Analyser/Header/Useragent/Device/Television.php +++ b/src/Analyser/Header/Useragent/Device/Television.php @@ -30,7 +30,7 @@ private function detectTelevision($ua) $this->detectSettopboxes($ua); /* Improve model names */ - $this->improveModelsOnDeviceTypeTelevision($ua); + $this->improveModelsOnDeviceTypeTelevision(); } @@ -142,7 +142,7 @@ private function detectLgTelevision($ua) if (preg_match('/webOS\.TV-([0-9]+)/u', $ua, $match)) { $this->data->device->manufacturer = 'LG'; - $this->data->device->series = 'webOS TV'; // . $match[1]; + $this->data->device->series = 'webOS TV'; $this->data->device->type = Constants\DeviceType::TELEVISION; $this->data->device->identified |= Constants\Id::MATCH_UA; @@ -607,6 +607,8 @@ private function detectGenericInettvBrowser($ua) if (preg_match('/(?:DTVNetBrowser|InettvBrowser|Hybridcast)\/[0-9\.]+[A-Z]? \(/u', $ua, $match)) { $this->data->device->type = Constants\DeviceType::TELEVISION; + $vendorName = null; + $modelName = null; $found = false; if (preg_match('/(?:DTVNetBrowser|InettvBrowser)\/[0-9\.]+[A-Z]? \(([^;]*)\s*;\s*([^;]*)\s*;/u', $ua, $match)) { @@ -683,6 +685,8 @@ private function detectGenericHbbTV($ua) if (preg_match('/(?:HbbTV|SmartTV)\/[0-9\.]+ \(/iu', $ua, $match)) { $this->data->device->type = Constants\DeviceType::TELEVISION; + $vendorName = null; + $modelName = null; $found = false; if (preg_match('/HbbTV\/[0-9\.]+ \(([^;]*);\s*([^;]*)\s*;\s*([^;]*)\s*;/u', $ua, $match)) { diff --git a/src/Analyser/Header/Useragent/Engine.php b/src/Analyser/Header/Useragent/Engine.php index 83c3ee3..d913bee 100644 --- a/src/Analyser/Header/Useragent/Engine.php +++ b/src/Analyser/Header/Useragent/Engine.php @@ -2,7 +2,6 @@ namespace WhichBrowser\Analyser\Header\Useragent; -use WhichBrowser\Constants; use WhichBrowser\Model\Version; trait Engine diff --git a/src/Analyser/Header/Useragent/Os.php b/src/Analyser/Header/Useragent/Os.php index 55e15bb..5794b50 100644 --- a/src/Analyser/Header/Useragent/Os.php +++ b/src/Analyser/Header/Useragent/Os.php @@ -431,7 +431,7 @@ private function determineAndroidVersionBasedOnBuild($ua) { if ((isset($this->data->os->name) && $this->data->os->name == 'Android') || isset($this->data->os->name) && $this->data->os->name == 'Android TV') { if (preg_match('/Build\/([^\);]+)/u', $ua, $match)) { - $version = Data\BuildIds::identify('android', $match[1]); + $version = Data\BuildIds::identify($match[1]); if ($version) { if (!isset($this->data->os->version) || $this->data->os->version == null || $this->data->os->version->value == null || $version->toFloat() < $this->data->os->version->toFloat()) { @@ -458,7 +458,7 @@ private function detectWindows($ua) $this->data->os->name = 'Windows'; $this->data->device->type = Constants\DeviceType::DESKTOP; - if (preg_match('/Windows NT ([0-9][0-9]?\.[0-9])/u', $ua, $match)) { + if (preg_match('/(?:Windows NT |WinNT)([0-9][0-9]?\.[0-9])/u', $ua, $match)) { $this->data->os->version = new Version([ 'value' => $match[1] ]); switch ($match[1]) { @@ -520,6 +520,10 @@ private function detectWindows($ua) $this->data->os->version = new Version([ 'value' => '5.1', 'alias' => 'XP' ]); } + if (preg_match('/Windows (3.[0-9\.]+)/u', $ua, $match)) { + $this->data->os->version = new Version([ 'value' => $match[1] ]); + } + if (preg_match('/WPDesktop/u', $ua)) { $this->data->os->name = 'Windows Phone'; $this->data->os->version = new Version([ 'value' => '8.0', 'details' => 1 ]); @@ -1509,7 +1513,7 @@ private function detectRemainingOperatingSystems($ua) [ 'name' => 'Grid OS', 'regexp' => [ '/Grid OS ([0-9.]*)/iu' ], 'type' => Constants\DeviceType::TABLET ], - [ 'name' => 'MAUI Runtime', 'regexp' => [ '/MAUI/u' ], 'type' => Constants\DeviceType::MOBILE ], + [ 'name' => 'MAUI Runtime', 'regexp' => [ '/MAUI/iu' ], 'type' => Constants\DeviceType::MOBILE ], [ 'name' => 'MTK', 'regexp' => [ '/\(MTK;/iu', '/\/MTK /iu' ], 'type' => Constants\DeviceType::MOBILE ], [ 'name' => 'QNX', 'regexp' => [ '/QNX/iu' ], 'type' => Constants\DeviceType::MOBILE ], [ 'name' => 'VRE', 'regexp' => [ '/\(VRE;/iu' ], 'type' => Constants\DeviceType::MOBILE ], @@ -1518,7 +1522,8 @@ private function detectRemainingOperatingSystems($ua) [ 'name' => 'ThreadX', 'regexp' => [ '/ThreadX(?:_OS)?\/([0-9.]*)/iu' ] ], ]; - for ($b = 0; $b < count($patterns); $b++) { + $count = count($patterns); + for ($b = 0; $b < $count; $b++) { for ($r = 0; $r < count($patterns[$b]['regexp']); $r++) { if (preg_match($patterns[$b]['regexp'][$r], $ua, $match)) { diff --git a/src/Data/BrowserIds.php b/src/Data/BrowserIds.php index 5dd03fd..d0d27e4 100644 --- a/src/Data/BrowserIds.php +++ b/src/Data/BrowserIds.php @@ -6,24 +6,12 @@ class BrowserIds { public static $ANDROID_BROWSERS = []; - public static function identify($type, $model) + public static function identify($model) { - require_once __DIR__ . '/../../data/id-' . $type . '.php'; + require_once __DIR__ . '/../../data/id-android.php'; - switch ($type) { - case 'android': - return self::identifyList(BrowserIds::$ANDROID_BROWSERS, $model); + if (isset(BrowserIds::$ANDROID_BROWSERS[$model])) { + return BrowserIds::$ANDROID_BROWSERS[$model]; } - - return false; - } - - public static function identifyList($list, $id) - { - if (isset($list[$id])) { - return $list[$id]; - } - - return false; } } diff --git a/src/Data/BuildIds.php b/src/Data/BuildIds.php index 2d43bab..7cc9bd6 100644 --- a/src/Data/BuildIds.php +++ b/src/Data/BuildIds.php @@ -8,28 +8,16 @@ class BuildIds { public static $ANDROID_BUILDS = []; - public static function identify($type, $id) + public static function identify($id) { - require_once __DIR__ . '/../../data/build-' . $type . '.php'; + require_once __DIR__ . '/../../data/build-android.php'; - switch ($type) { - case 'android': - return self::identifyList(BuildIds::$ANDROID_BUILDS, $id); - } - - return false; - } - - public static function identifyList($list, $id) - { - if (isset($list[$id])) { - if (is_array($list[$id])) { - return new Version($list[$id]); + if (isset(BuildIds::$ANDROID_BUILDS[$id])) { + if (is_array(BuildIds::$ANDROID_BUILDS[$id])) { + return new Version(BuildIds::$ANDROID_BUILDS[$id]); } else { - return new Version([ 'value' => $list[$id] ]); + return new Version([ 'value' => BuildIds::$ANDROID_BUILDS[$id] ]); } } - - return false; } } diff --git a/src/Data/DeviceModels.php b/src/Data/DeviceModels.php index 215b0ef..075efe6 100644 --- a/src/Data/DeviceModels.php +++ b/src/Data/DeviceModels.php @@ -63,8 +63,6 @@ public static function identify($type, $model) case 'feature': return self::identifyList(self::$FEATURE_MODELS, $model); } - - return (object) [ 'type' => '', 'model' => $model, 'identified' => Constants\Id::NONE ]; } public static function identifyIOS($model) diff --git a/src/Model/Browser.php b/src/Model/Browser.php index 7787da1..421fdd7 100644 --- a/src/Model/Browser.php +++ b/src/Model/Browser.php @@ -30,10 +30,12 @@ class Browser extends NameVersion /** * Set the properties to the default values * + * @param array|null $properties An optional array of properties to set after setting it to the default values + * * @internal */ - public function reset() + public function reset($properties = null) { parent::reset(); @@ -44,6 +46,10 @@ public function reset() $this->stock = true; $this->hidden = false; $this->mode = ''; + + if (is_array($properties)) { + $this->set($properties); + } } @@ -112,7 +118,7 @@ public function isUsing($name) public function toString() { - $result = trim(($this->hidden == false ? $this->getName() . ' ' : '') . $this->getVersion()); + $result = trim(($this->hidden === false ? $this->getName() . ' ' . $this->getVersion() : '')); if (empty($result) && isset($this->using)) { return $this->using->toString(); @@ -154,10 +160,6 @@ public function toArray() $result['version'] = $this->version->toArray(); } - if (isset($result['name']) && empty($result['name'])) { - unset($result['name']); - } - if (isset($result['version']) && !count($result['version'])) { unset($result['version']); } diff --git a/src/Model/Device.php b/src/Model/Device.php index 53b33f5..1b7063d 100644 --- a/src/Model/Device.php +++ b/src/Model/Device.php @@ -19,6 +19,9 @@ class Device extends Base /** @var int */ public $identifier; + /** @var mixed */ + public $flag; + /** @var string */ public $type = ''; @@ -36,10 +39,12 @@ class Device extends Base /** * Set the properties to the default values * + * @param array|null $properties An optional array of properties to set after setting it to the default values + * * @internal */ - public function reset() + public function reset($properties = null) { unset($this->manufacturer); unset($this->model); @@ -50,6 +55,30 @@ public function reset() $this->subtype = ''; $this->identified = Constants\Id::NONE; $this->generic = true; + + if (is_array($properties)) { + $this->set($properties); + } + } + + + /** + * Declare an positive identification + * + * @param array $properties An array, the key of an element determines the name of the property + * + * @return string + */ + + public function setIdentification($properties) + { + $this->reset($properties); + + if (!empty($this->model)) { + $this->generic = false; + } + + $this->identified |= Constants\Id::MATCH_UA; } diff --git a/src/Model/Engine.php b/src/Model/Engine.php index 04225ef..046964a 100644 --- a/src/Model/Engine.php +++ b/src/Model/Engine.php @@ -26,10 +26,6 @@ public function toArray() $result['version'] = $this->version->toArray(); } - if (isset($result['name']) && empty($result['name'])) { - unset($result['name']); - } - if (isset($result['version']) && !count($result['version'])) { unset($result['version']); } diff --git a/src/Model/Main.php b/src/Model/Main.php index b329289..7b9304c 100644 --- a/src/Model/Main.php +++ b/src/Model/Main.php @@ -58,10 +58,10 @@ public function __construct() * * @internal * - * @param string $property The name of the property, such as 'browser', 'engine' or 'os' - * @param string $name The name of the browser that is checked - * @param string $operator Optional, the operator, must be <, <=, =, >= or > - * @param mixed $value Optional, the value, can be an integer, float or string with a version number + * @param string The name of the property, such as 'browser', 'engine' or 'os' + * @param string The name of the browser that is checked + * @param string Optional, the operator, must be <, <=, =, >= or > + * @param mixed Optional, the value, can be an integer, float or string with a version number * * @return boolean */ @@ -70,30 +70,39 @@ private function isX() { $arguments = func_get_args(); $x = $arguments[0]; - $valid = true; - if (count($arguments) >= 2) { - $valid = $valid && $this->$x->name == $arguments[1]; - - if (count($arguments) >= 4 && !empty($this->$x->version) && $valid) { - $valid = $valid && $this->$x->version->is($arguments[2], $arguments[3]); + if (count($arguments) < 2) { + return false; + } + + if (empty($this->$x->name)) { + return false; + } + + if ($this->$x->name != $arguments[1]) { + return false; + } + + if (count($arguments) >= 4) { + if (empty($this->$x->version)) { + return false; } - if ($valid) { - return true; + if (!$this->$x->version->is($arguments[2], $arguments[3])) { + return false; } } - return $valid; + return true; } /** * Check the name of the browser and optionally is a specific version * - * @param string $name The name of the browser that is checked - * @param string $operator Optional, the operator, must be <, <=, =, >= or > - * @param mixed $value Optional, the value, can be an integer, float or string with a version number + * @param string The name of the browser that is checked + * @param string Optional, the operator, must be <, <=, =, >= or > + * @param mixed Optional, the value, can be an integer, float or string with a version number * * @return boolean */ @@ -109,9 +118,9 @@ public function isBrowser() /** * Check the name of the rendering engine and optionally is a specific version * - * @param string $name The name of the rendering engine that is checked - * @param string $operator Optional, the operator, must be <, <=, =, >= or > - * @param mixed $value Optional, the value, can be an integer, float or string with a version number + * @param string The name of the rendering engine that is checked + * @param string Optional, the operator, must be <, <=, =, >= or > + * @param mixed Optional, the value, can be an integer, float or string with a version number * * @return boolean */ @@ -127,9 +136,9 @@ public function isEngine() /** * Check the name of the operating system and optionally is a specific version * - * @param string $name The name of the operating system that is checked - * @param string $operator Optional, the operator, must be <, <=, =, >= or > - * @param mixed $value Optional, the value, can be an integer, float or string with a version number + * @param string The name of the operating system that is checked + * @param string Optional, the operator, must be <, <=, =, >= or > + * @param mixed Optional, the value, can be an integer, float or string with a version number * * @return boolean */ @@ -171,8 +180,8 @@ public function getType() /** * Check if the detected browser is of the specified type * - * @param string $type The type, or a combination of type and subtype joined with a semicolon. - * @param string $type,... Unlimited optional types to check + * @param string The type, or a combination of type and subtype joined with a semicolon. + * @param string Unlimited optional types to check * * @return boolean */ @@ -181,7 +190,8 @@ public function isType() { $arguments = func_get_args(); - for ($a = 0; $a < count($arguments); $a++) { + $count = count($arguments); + for ($a = 0; $a < $count; $a++) { if (strpos($arguments[$a], ':') !== false) { list($type, $subtype) = explode(':', $arguments[$a]); if ($type == $this->device->type && $subtype == $this->device->subtype) { @@ -275,7 +285,7 @@ public function toString() } if ($this->device->type == 'desktop' && !empty($os) && !empty($engine) && empty($device)) { - return 'an unknown browser based on ' . $engine + ' running on ' + $os; + return 'an unknown browser based on ' . $engine . ' running on ' . $os; } if ($this->browser->stock && !empty($os) && empty($device)) { @@ -338,6 +348,10 @@ public function toArray() unset($result['device']); } + if ($this->camouflage) { + $result['camouflage'] = true; + } + return $result; } } diff --git a/src/Model/Os.php b/src/Model/Os.php index 5bce7f5..e93214f 100644 --- a/src/Model/Os.php +++ b/src/Model/Os.php @@ -15,14 +15,20 @@ class Os extends NameVersion /** * Set the properties to the default values * + * @param array|null $properties An optional array of properties to set after setting it to the default values + * * @internal */ - public function reset() + public function reset($properties = null) { parent::reset(); unset($this->family); + + if (is_array($properties)) { + $this->set($properties); + } } @@ -78,11 +84,6 @@ public function toArray() $result['version'] = $this->version->toArray(); } - - if (isset($result['name']) && empty($result['name'])) { - unset($result['name']); - } - if (isset($result['version']) && !count($result['version'])) { unset($result['version']); } diff --git a/src/Model/Primitive/Base.php b/src/Model/Primitive/Base.php index 9a47a11..35247ed 100644 --- a/src/Model/Primitive/Base.php +++ b/src/Model/Primitive/Base.php @@ -16,9 +16,22 @@ class Base public function __construct($defaults = null) { if (is_array($defaults)) { - foreach ($defaults as $k => $v) { - $this->{$k} = $v; - } + $this->set($defaults); + } + } + + + /** + * Set the properties of the object the the values specified in the array + * + * @param array $properties An array, the key of an element determines the name of the property + * + * @internal + */ + public function set($properties) + { + foreach ($properties as $k => $v) { + $this->{$k} = $v; } } @@ -35,7 +48,7 @@ public function toJavaScript() { $lines = []; - foreach ($this as $key => $value) { + foreach (get_object_vars($this) as $key => $value) { if (!is_null($value)) { $line = $key . ": "; diff --git a/src/Model/Primitive/NameVersion.php b/src/Model/Primitive/NameVersion.php index f33c430..74e0b07 100644 --- a/src/Model/Primitive/NameVersion.php +++ b/src/Model/Primitive/NameVersion.php @@ -2,6 +2,8 @@ namespace WhichBrowser\Model\Primitive; +use WhichBrowser\Model\Version; + /** * @internal */ @@ -21,14 +23,52 @@ class NameVersion extends Base /** * Set the properties to the default values * + * @param array|null $properties An optional array of properties to set after setting it to the default values + * * @internal */ - public function reset() + public function reset($properties = null) { unset($this->name); unset($this->alias); unset($this->version); + + if (is_array($properties)) { + $this->set($properties); + } + } + + + /** + * Identify the version based on a pattern + * + * @param string $pattern The regular expression that defines the group that matches the version string + * @param string $subject The string the regular expression is matched with + * @param array|null $defaults An optional array of properties to set together with the value + * + * @return string + */ + + public function identifyVersion($pattern, $subject, $defaults = []) + { + if (preg_match($pattern, $subject, $match)) { + $version = $match[1]; + + if (isset($defaults['type'])) { + switch ($defaults['type']) { + case 'underscore': + $version = str_replace('_', '.', $version); + break; + case 'legacy': + $version = preg_replace("/([0-9])([0-9])/", '$1.$2', $version); + break; + } + } + + + $this->version = new Version(array_merge($defaults, [ 'value' => $version ])); + } } diff --git a/src/Model/Version.php b/src/Model/Version.php index e069a58..38c85d2 100644 --- a/src/Model/Version.php +++ b/src/Model/Version.php @@ -12,12 +12,25 @@ class Version extends Base /** @var boolean */ public $hidden = false; + /** @var string */ + public $nickname; + + /** @var string */ + public $alias; + + /** @var int */ + public $details; + + /** @var boolean */ + public $builds; + + /** * Determine if the version is lower, equal or higher than the specified value * - * @param string $operator The operator, must be <, <=, =, >= or > - * @param mixed $value The value, can be an integer, float or string with a version number + * @param string The operator, must be <, <=, =, >= or > + * @param mixed The value, can be an integer, float or string with a version number * * @return boolean */ @@ -113,14 +126,14 @@ public function getMinor() /** - * Return the build number as an integer + * Return the patch number as an integer * * @return integer */ - public function getBuild() + public function getPatch() { - return $this->getParts()->build; + return $this->getParts()->patch; } @@ -129,8 +142,8 @@ public function getBuild() * * @internal * - * @param string $vaiue Version string, with elements seperated by a dot - * @param int $count The maximum precision + * @param string Version string, with elements seperated by a dot + * @param int The maximum precision * * @return float */ @@ -151,7 +164,8 @@ private function toValue($value = null, $count = null) if (count($parts) > 1) { $result .= '.'; - for ($p = 1; $p < count($parts); $p++) { + $count = count($parts); + for ($p = 1; $p < $count; $p++) { $result .= substr('0000' . $parts[$p], -4); } } @@ -229,7 +243,8 @@ public function toString() } if (isset($this->builds) && !$this->builds) { - for ($i = 0; $i < count($v); $i++) { + $count = count($v); + for ($i = 0; $i < $count; $i++) { if ($v[$i] > 999) { array_splice($v, $i, 1); }