Файл: vendor/whichbrowser/parser/src/Analyser/Header/Useragent/Browser.php
Строк: 2249
<?php
namespace WhichBrowserAnalyserHeaderUseragent;
use WhichBrowserConstants;
use WhichBrowserData;
use WhichBrowserModelFamily;
use WhichBrowserModelUsing;
use WhichBrowserModelVersion;
trait Browser
{
private function &detectBrowser($ua)
{
/* Detect major browsers */
$this->detectSafari($ua);
$this->detectExplorer($ua);
$this->detectChrome($ua);
$this->detectFirefox($ua);
$this->detectEdge($ua);
$this->detectOpera($ua);
/* Detect WAP browsers */
$this->detectWapBrowsers($ua);
/* Detect other various mobile browsers */
$this->detectNokiaBrowser($ua);
$this->detectSilk($ua);
$this->detectSailfishBrowser($ua);
$this->detectWebOSBrowser($ua);
$this->detectDolfin($ua);
$this->detectIris($ua);
/* Detect other browsers */
$this->detectUC($ua);
$this->detectObigo($ua);
$this->detectNetfront($ua);
/* Detect other specific desktop browsers */
$this->detectSeamonkey($ua);
$this->detectModernNetscape($ua);
$this->detectMosaic($ua);
$this->detectKonqueror($ua);
$this->detectOmniWeb($ua);
/* Detect other various television browsers */
$this->detectEspial($ua);
$this->detectMachBlue($ua);
$this->detectAnt($ua);
$this->detectSraf($ua);
/* Detect other browsers */
$this->detectDesktopBrowsers($ua);
$this->detectMobileBrowsers($ua);
$this->detectTelevisionBrowsers($ua);
$this->detectRemainingBrowsers($ua);
return $this;
}
private function &refineBrowser($ua)
{
$this->detectUCEngine($ua);
$this->detectLegacyNetscape($ua);
return $this;
}
/* Safari */
private function detectSafari($ua)
{
if (preg_match('/Safari/u', $ua)) {
$falsepositive = false;
if (preg_match('/Qt/u', $ua)) {
$falsepositive = true;
}
if (!$falsepositive) {
if (isset($this->data->os->name) && $this->data->os->name == 'iOS') {
$this->data->browser->name = 'Safari';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->version = null;
$this->data->browser->stock = true;
if (preg_match('/Version/([0-9.]+)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'hidden' => true ]);
}
}
if (isset($this->data->os->name) && ($this->data->os->name == 'OS X' || $this->data->os->name == 'Windows')) {
$this->data->browser->name = 'Safari';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = $this->data->os->name == 'OS X';
if (preg_match('/Version/([0-9.]+)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
if (preg_match('/AppleWebKit/[0-9.]++/u', $ua)) {
$this->data->browser->name = 'WebKit Nightly Build';
$this->data->browser->version = null;
}
}
}
}
if (preg_match('/(?:Apple-PubSub|AppleSyndication)//u', $ua)) {
$this->data->browser->name = 'Safari RSS';
$this->data->browser->type = ConstantsBrowserType::APP_FEEDREADER;
$this->data->browser->version = null;
$this->data->browser->stock = true;
$this->data->os->name = 'OS X';
$this->data->os->version = null;
$this->data->device->type = ConstantsDeviceType::DESKTOP;
}
}
/* Chrome */
private function detectChrome($ua)
{
if (preg_match('/(?:Chrome|CrMo|CriOS)/[0-9]/u', $ua) || preg_match('/Browser/Chrome[0-9]/u', $ua)) {
$this->data->browser->name = 'Chrome';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
$reduced = false;
$version = '';
if (preg_match('/(?:Chrome|CrMo|CriOS)/([0-9.]*)/u', $ua, $match)) {
$version = $match[1];
}
if (preg_match('/Browser/Chrome([0-9.]*)/u', $ua, $match)) {
$version = $match[1];
}
if (preg_match('/Chrome/([789][0-9]|[1-9][0-9][0-9]).0.0.0 /u', $ua)) {
$reduced = true;
}
$this->data->browser->version = new Version([ 'value' => $version ]);
if (isset($this->data->os->name) && $this->data->os->name == 'Android') {
if ($reduced) {
$this->data->browser->version->details = 1;
} else {
$channel = DataChrome::getChannel('mobile', $this->data->browser->version->value);
if ($channel == 'stable') {
$this->data->browser->version->details = 1;
} elseif ($channel == 'beta') {
$this->data->browser->channel = 'Beta';
} else {
$this->data->browser->channel = 'Dev';
}
}
/* Webview for Android 4.4 and higher */
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->type = ConstantsBrowserType::UNKNOWN;
$this->data->browser->stock = true;
$this->data->browser->name = null;
$this->data->browser->version = null;
$this->data->browser->channel = null;
}
/* Webview for Android 5 */
if (preg_match('/; wv)/u', $ua)) {
$this->data->browser->using = new Using([ 'name' => 'Chromium WebView', 'version' => new Version([ 'value' => explode('.', $version)[0] ]) ]);
$this->data->browser->type = ConstantsBrowserType::UNKNOWN;
$this->data->browser->stock = true;
$this->data->browser->name = null;
$this->data->browser->version = null;
$this->data->browser->channel = null;
}
/* LG Chromium based browsers */
if (isset($this->data->device->manufacturer) && $this->data->device->manufacturer == 'LG') {
if (in_array($version, [ '30.0.1599.103', '34.0.1847.118', '38.0.2125.0', '38.0.2125.102' ]) && preg_match('/Version/4/u', $ua) && !preg_match('/; wv)/u', $ua)) {
$this->data->browser->name = "LG Browser";
$this->data->browser->channel = null;
$this->data->browser->stock = true;
$this->data->browser->version = null;
}
}
/* Samsung Chromium based browsers */
if (isset($this->data->device->manufacturer) && $this->data->device->manufacturer == 'Samsung') {
/* Version 1.0 */
if ($version == '18.0.1025.308' && preg_match('/Version/1.0/u', $ua)) {
$this->data->browser->name = "Samsung Internet";
$this->data->browser->channel = null;
$this->data->browser->stock = true;
$this->data->browser->version = new Version([ 'value' => '1.0' ]);
}
/* Version 1.5 */
if ($version == '28.0.1500.94' && preg_match('/Version/1.5/u', $ua)) {
$this->data->browser->name = "Samsung Internet";
$this->data->browser->channel = null;
$this->data->browser->stock = true;
$this->data->browser->version = new Version([ 'value' => '1.5' ]);
}
/* Version 1.6 */
if ($version == '28.0.1500.94' && preg_match('/Version/1.6/u', $ua)) {
$this->data->browser->name = "Samsung Internet";
$this->data->browser->channel = null;
$this->data->browser->stock = true;
$this->data->browser->version = new Version([ 'value' => '1.6' ]);
}
/* Version 2.0 */
if ($version == '34.0.1847.76' && preg_match('/Version/2.0/u', $ua)) {
$this->data->browser->name = "Samsung Internet";
$this->data->browser->channel = null;
$this->data->browser->stock = true;
$this->data->browser->version = new Version([ 'value' => '2.0' ]);
}
/* Version 2.1 */
if ($version == '34.0.1847.76' && preg_match('/Version/2.1/u', $ua)) {
$this->data->browser->name = "Samsung Internet";
$this->data->browser->channel = null;
$this->data->browser->stock = true;
$this->data->browser->version = new Version([ 'value' => '2.1' ]);
}
}
/* Samsung Chromium based browsers */
if (preg_match('/SamsungBrowser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = "Samsung Internet";
$this->data->browser->channel = null;
$this->data->browser->stock = true;
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
if (preg_match('/Mobile VR/', $ua)) {
$this->data->device->manufacturer = 'Samsung';
$this->data->device->model = 'Gear VR';
$this->data->device->type = ConstantsDeviceType::HEADSET;
}
}
/* Oculus Chromium based browsers */
if (preg_match('/OculusBrowser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = "Oculus Browser";
$this->data->browser->channel = null;
$this->data->browser->stock = true;
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
if (preg_match('/Mobile VR/', $ua)) {
$this->data->device->manufacturer = 'Samsung';
$this->data->device->model = 'Gear VR';
$this->data->device->type = ConstantsDeviceType::HEADSET;
}
if (preg_match('/Pacific/', $ua)) {
$this->data->device->manufacturer = 'Oculus';
$this->data->device->model = 'Go';
$this->data->device->type = ConstantsDeviceType::HEADSET;
}
}
} elseif (isset($this->data->os->name) && $this->data->os->name == 'Linux' && preg_match('/SamsungBrowser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = "Samsung Internet";
$this->data->browser->channel = null;
$this->data->browser->stock = true;
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->os->name = 'Android';
$this->data->os->version = null;
$this->data->device->manufacturer = 'Samsung';
$this->data->device->model = 'DeX';
$this->data->device->identifier = '';
$this->data->device->identified |= ConstantsId::PATTERN;
$this->data->device->type = ConstantsDeviceType::DESKTOP;
} else {
if ($reduced) {
$this->data->browser->version->details = 1;
} else {
$channel = DataChrome::getChannel('desktop', $version);
if ($channel == 'stable') {
if (explode('.', $version)[1] == '0') {
$this->data->browser->version->details = 1;
} else {
$this->data->browser->version->details = 2;
}
} elseif ($channel == 'beta') {
$this->data->browser->channel = 'Beta';
} else {
$this->data->browser->channel = 'Dev';
}
}
}
if ($this->data->device->type == '') {
$this->data->device->type = ConstantsDeviceType::DESKTOP;
}
}
/* Google Chromium */
if (preg_match('/Chromium/u', $ua)) {
$this->data->browser->stock = false;
$this->data->browser->channel = '';
$this->data->browser->name = 'Chromium';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Chromium/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
if ($this->data->device->type == '') {
$this->data->device->type = ConstantsDeviceType::DESKTOP;
}
}
/* Chrome Content Shell */
if (preg_match('/Chrome/[0-9]+.77.34.5/u', $ua)) {
$this->data->browser->using = new Using([ 'name' => 'Chrome Content Shell' ]);
$this->data->browser->type = ConstantsBrowserType::UNKNOWN;
$this->data->browser->stock = false;
$this->data->browser->name = null;
$this->data->browser->version = null;
$this->data->browser->channel = null;
}
/* Chromium WebView by Amazon */
if (preg_match('/AmazonWebAppPlatform//u', $ua)) {
$this->data->browser->using = new Using([ 'name' => 'Amazon WebView' ]);
$this->data->browser->type = ConstantsBrowserType::UNKNOWN;
$this->data->browser->stock = false;
$this->data->browser->name = null;
$this->data->browser->version = null;
$this->data->browser->channel = null;
}
/* Chromium WebView by Crosswalk */
if (preg_match('/Crosswalk/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->using = new Using([ 'name' => 'Crosswalk WebView', 'version' => new Version([ 'value' => $match[1], 'details' => 1 ]) ]);
$this->data->browser->type = ConstantsBrowserType::UNKNOWN;
$this->data->browser->stock = false;
$this->data->browser->name = null;
$this->data->browser->version = null;
$this->data->browser->channel = null;
}
/* Set the browser family */
if ($this->data->isBrowser('Chrome') || $this->data->isBrowser('Chromium')) {
$this->data->browser->family = new Family([
'name' => 'Chrome',
'version' => !empty($this->data->browser->version) ? new Version([ 'value' => $this->data->browser->version->getMajor() ]) : null
]);
}
}
/* Internet Explorer */
private function detectExplorer($ua)
{
if (preg_match('/(IE ([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Internet Explorer';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/Browser/IE([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Internet Explorer';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/MSIE/u', $ua)) {
$this->data->browser->name = 'Internet Explorer';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/IEMobile/u', $ua) || preg_match('/Windows CE/u', $ua) || preg_match('/Windows Phone/u', $ua) || preg_match('/WP7/u', $ua) || preg_match('/WPDesktop/u', $ua)) {
$this->data->browser->name = 'Mobile Internet Explorer';
if (isset($this->data->device->model) && ($this->data->device->model == 'Xbox 360' || $this->data->device->model == 'Xbox One' || $this->data->device->model == 'Xbox Series X')) {
$this->data->browser->name = 'Internet Explorer';
}
}
if (preg_match('/MSIE ([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => preg_replace("/.([0-9])([0-9])/", '.$1.$2', $match[1]) ]);
}
if (preg_match('/Mac_/u', $ua)) {
$this->data->os->name = 'Mac OS';
$this->data->engine->name = 'Tasman';
$this->data->device->type = ConstantsDeviceType::DESKTOP;
if (!empty($this->data->browser->version)) {
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->is('>=', '5.2')) {
$this->data->os->name = 'OS X';
}
}
}
}
if (preg_match('/Trident/[789][^)]+; rv:([0-9.]*))/u', $ua, $match)) {
$this->data->browser->name = 'Internet Explorer';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/Trident/[789][^)]+; Touch; rv:([0-9.]*);s+IEMobile//u', $ua, $match)) {
$this->data->browser->name = 'Mobile Internet Explorer';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/Trident/[789][^)]+; Touch; rv:([0-9.]*); WPDesktop/u', $ua, $match)) {
$this->data->browser->mode = 'desktop';
$this->data->browser->name = 'Mobile Internet Explorer';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
/* Old versions of Pocket Internet Explorer */
if ($this->data->isBrowser('Mobile Internet Explorer', '<', 6)) {
$this->data->browser->name = 'Pocket Internet Explorer';
}
if (preg_match('/Microsoft Pocket Internet Explorer//u', $ua)) {
$this->data->browser->name = 'Pocket Internet Explorer';
$this->data->browser->version = new Version([ 'value' => '1.0' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
if (preg_match('/MSPIE ([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Pocket Internet Explorer2';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
/* Microsoft Mobile Explorer */
if (preg_match('/MMEF([0-9])([0-9])/u', $ua, $match)) {
$this->data->browser->name = 'Microsoft Mobile Explorer';
$this->data->browser->version = new Version([ 'value' => $match[1] . '.' . $match[2] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::MOBILE;
if (preg_match('/MMEF[0-9]+; ([^;]+); ([^)/]+)/u', $ua, $match)) {
$device = DataDeviceModels::identify('feature', $match[1] == 'CellPhone' ? $match[2] : $match[1] . ' ' . $match[2]);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
}
}
}
/* Microsoft Open Live Writer */
if (preg_match('/Open Live Writer ([0-9.]*)/u', $ua, $match)) {
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
$this->data->browser->name = 'Open Live Writer';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->channel = null;
if (preg_match('/MSIE ([0-9.]*)/u', $ua, $match)) {
$this->data->browser->using = new Using([ 'name' => 'Internet Explorer', 'version' => new Version([ 'value' => $match[1] ]) ]);
}
}
/* Set the browser family */
if ($this->data->isBrowser('Internet Explorer') || $this->data->isBrowser('Mobile Internet Explorer') || $this->data->isBrowser('Pocket Internet Explorer')) {
unset($this->data->browser->family);
}
}
/* Edge */
private function detectEdge($ua)
{
if (preg_match('/Edge/([0-9]+)/u', $ua, $match)) {
$this->data->browser->name = 'Edge';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->channel = '';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 1 ]);
unset($this->data->browser->family);
}
if (preg_match('/Edg(iOS|A)/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Edge';
$this->data->browser->version = new Version([ 'value' => $match[2], 'details' => 1, 'hidden' => true ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/Edg/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Edge';
$this->data->browser->channel = '';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 1 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
}
/* Opera */
private function detectOpera($ua)
{
if (!preg_match('/(OPR|OMI|Opera|OPiOS|OPT|Coast|Oupeng|OPRGX|MMS)/ui', $ua)) {
return;
}
if (preg_match('/OPR/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->channel = '';
$this->data->browser->name = 'Opera';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Edition Developer/iu', $ua)) {
$this->data->browser->channel = 'Developer';
}
if (preg_match('/Edition Next/iu', $ua)) {
$this->data->browser->channel = 'Next';
}
if (preg_match('/Edition Beta/iu', $ua)) {
$this->data->browser->channel = 'Beta';
}
if ($this->data->device->type == ConstantsDeviceType::MOBILE) {
$this->data->browser->name = 'Opera Mobile';
}
}
if (preg_match('/OMI/([0-9]+.[0-9]+)/u', $ua, $match)) {
$this->data->browser->name = 'Opera Devices';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::TELEVISION;
if (!$this->data->isOs('Android')) {
unset($this->data->os->name);
unset($this->data->os->version);
}
}
if ((preg_match('/Opera[/-s]/iu', $ua) || preg_match('/Browser/Opera/iu', $ua)) && !preg_match('/Opera Software/iu', $ua)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Opera';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Opera[/| ]?([0-9.]+)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
if (preg_match('/Version/([0-9.]+)/u', $ua, $match)) {
if (floatval($match[1]) >= 10) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
}
if (isset($this->data->browser->version) && preg_match('/Edition Labs/u', $ua)) {
$this->data->browser->channel = 'Labs';
}
if (isset($this->data->browser->version) && preg_match('/Edition Next/u', $ua)) {
$this->data->browser->channel = 'Next';
}
if (preg_match('/Opera Tablet/u', $ua)) {
$this->data->browser->name = 'Opera Mobile';
$this->data->device->type = ConstantsDeviceType::TABLET;
}
if (preg_match('/Opera Mobi/u', $ua)) {
$this->data->browser->name = 'Opera Mobile';
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
if (preg_match('/Opera Mini;/u', $ua)) {
$this->data->browser->name = 'Opera Mini';
$this->data->browser->version = null;
$this->data->browser->mode = 'proxy';
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
if (preg_match('/Opera Mini/(?:att/)?([0-9.]+)/u', $ua, $match)) {
$this->data->browser->name = 'Opera Mini';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => (intval(substr(strrchr($match[1], '.'), 1)) > 99 ? -1 : null) ]);
$this->data->browser->mode = 'proxy';
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
if ($this->data->browser->name == 'Opera' && $this->data->device->type == ConstantsDeviceType::MOBILE) {
$this->data->browser->name = 'Opera Mobile';
}
if (preg_match('/InettvBrowser/u', $ua)) {
$this->data->device->type = ConstantsDeviceType::TELEVISION;
}
if (preg_match('/Opera[ -]TV/u', $ua)) {
$this->data->browser->name = 'Opera';
$this->data->device->type = ConstantsDeviceType::TELEVISION;
}
if (preg_match('/Linux zbov/u', $ua)) {
$this->data->browser->name = 'Opera Mobile';
$this->data->browser->mode = 'desktop';
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->os->name = null;
$this->data->os->version = null;
}
if (preg_match('/Linux zvav/u', $ua)) {
$this->data->browser->name = 'Opera Mini';
$this->data->browser->version = null;
$this->data->browser->mode = 'desktop';
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->os->name = null;
$this->data->os->version = null;
}
if ($this->data->device->type == '') {
$this->data->device->type = ConstantsDeviceType::DESKTOP;
}
if (isset($this->data->browser->family)) {
unset($this->data->browser->family);
}
}
if (preg_match('/OPiOS/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Opera Mini';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/OPT/([0-9].[0-9.]+)?/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Opera Touch';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (isset($match[1])) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
}
}
if (preg_match('/Coast/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Coast by Opera';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/Oupeng(?:HD)?[/-]([0-9.]*)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Opera Oupeng';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/sMMS/([0-9.]*)$/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Opera Neon';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/OPRGX/([0-9.]*)$/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Opera GX';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
}
/* Firefox */
private function detectFirefox($ua)
{
if (!preg_match('/(Firefox|Lorentz|GranParadiso|Namoroka|Shiretoko|Minefield|BonEcho|Fennec|Phoenix|Firebird|Minimo|FxiOS|Focus)/ui', $ua)) {
return;
}
if (preg_match('/Firefox/u', $ua)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Firefox';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Firefox/([0-9ab.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
if (preg_match('/a/u', $match[1])) {
$this->data->browser->channel = 'Aurora';
}
if (preg_match('/b/u', $match[1])) {
$this->data->browser->channel = 'Beta';
}
}
if (preg_match('/Aurora/([0-9ab.]*)/u', $ua, $match)) {
$this->data->browser->channel = 'Aurora';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
if (preg_match('/Fennec/u', $ua)) {
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
if (preg_match('/Mobile;(?: ([^;]+);)? rv/u', $ua, $match)) {
$this->data->device->type = ConstantsDeviceType::MOBILE;
if (isset($match[1])) {
$device = DataDeviceModels::identify('firefoxos', $match[1]);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
if (!$this->data->isOs('KaiOS')) {
$this->data->os->reset([ 'name' => 'Firefox OS' ]);
}
}
}
}
if (preg_match('/Tablet;(?: ([^;]+);)? rv/u', $ua, $match)) {
$this->data->device->type = ConstantsDeviceType::TABLET;
}
if (preg_match('/Viera;(?: ([^;]+);)? rv/u', $ua, $match)) {
$this->data->device->type = ConstantsDeviceType::TELEVISION;
$this->data->os->reset([ 'name' => 'Firefox OS' ]);
}
if ($this->data->device->type == ConstantsDeviceType::MOBILE || $this->data->device->type == ConstantsDeviceType::TABLET) {
$this->data->browser->name = 'Firefox Mobile';
}
if ($this->data->device->type == '') {
$this->data->device->type = ConstantsDeviceType::DESKTOP;
}
}
if (preg_match('/(Lorentz|GranParadiso|Namoroka|Shiretoko|Minefield|BonEcho)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Firefox';
$this->data->browser->channel = str_replace('GranParadiso', 'Gran Paradiso', $match[1]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/' . $match[1] . '/([0-9ab.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
}
if (preg_match('/Fennec/u', $ua)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Firefox Mobile';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Fennec/([0-9ab.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
$this->data->browser->channel = 'Fennec';
}
if (preg_match('/(Phoenix|Firebird|Minimo)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = $match[1];
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/' . $match[1] . '/([0-9ab.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
}
if (preg_match('/FxiOS/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Firefox';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/Focus/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Firefox Focus';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/Servo/1.0 Firefox//u', $ua)) {
$this->data->browser->name = 'Servo Nightly Build';
$this->data->browser->version = null;
}
/* Set the browser family */
if ($this->data->isBrowser('Firefox') || $this->data->isBrowser('Firefox Mobile') || $this->data->isBrowser('Firebird')) {
$this->data->browser->family = new Family([ 'name' => 'Firefox', 'version' => $this->data->browser->version ]);
}
if ($this->data->isBrowser('Minimo')) {
$this->data->browser->family = new Family([ 'name' => 'Firefox' ]);
}
}
/* Seamonkey */
private function detectSeamonkey($ua)
{
if (preg_match('/SeaMonkey/u', $ua)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'SeaMonkey';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/SeaMonkey/([0-9ab.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
}
if (preg_match('/PmWFx/([0-9ab.]*)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'SeaMonkey';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
}
/* Netscape */
private function detectLegacyNetscape($ua)
{
if ($this->data->device->type == ConstantsDeviceType::DESKTOP && $this->data->browser->getName() == '') {
if (!preg_match('/compatible;/u', $ua)) {
if (preg_match('/Mozilla/([123].[0-9]+)/u', $ua, $match)) {
$this->data->browser->name = 'Netscape Navigator';
$this->data->browser->version = new Version([ 'value' => preg_replace("/([0-9])([0-9])/", '$1.$2', $match[1]) ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/Mozilla/(4.[0-9]+)/u', $ua, $match)) {
$this->data->browser->name = 'Netscape Communicator';
$this->data->browser->version = new Version([ 'value' => preg_replace("/([0-9])([0-9])/", '$1.$2', $match[1]) ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Nav)/u', $ua)) {
$this->data->browser->name = 'Netscape Navigator';
}
}
}
}
}
private function detectModernNetscape($ua)
{
if (preg_match('/Netscape/u', $ua)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Netscape';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Netscape[0-9]?/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
}
if (preg_match('/ Navigator/(9.[0-9.]*)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'Netscape Navigator';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
}
}
/* Mosaic */
private function detectMosaic($ua)
{
if (!preg_match('/Mosaic/ui', $ua)) {
return;
}
if (preg_match('/(?:NCSA[ _])?Mosaic(?:(tm))?(?: for the X Window System| for Windows)?/(?:Version )?([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'NCSA Mosaic';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
}
if (preg_match('/AIR_Mosaic(?:(16bit))?/v([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'AIR Mosaic';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
}
if (preg_match('/(?:MosaicView|Spyglass[ _]Mosaic)/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Spyglass Mosaic';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
}
if (preg_match('/SPRY_Mosaic(?:(16bit))?/v([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'SPRY Mosaic';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
}
if (preg_match('/DCL SuperMosaic/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'SuperMosaic';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
}
if (preg_match('/VMS_Mosaic/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'VMS Mosaic';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
}
if (preg_match('/mMosaic/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'mMosaic';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
}
if (preg_match('/Quarterdeck Mosaic Version ([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Quarterdeck Mosaic';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
}
if (preg_match('/WinMosaic/Version ([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'WinMosaic';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
}
if (preg_match('/Device Mosaic ([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Device Mosaic';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->family = new Family([ 'name' => 'Mosaic' ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->stock = false;
$this->data->device->type = ConstantsDeviceType::TELEVISION;
}
}
/* UC Browser */
private function detectUC($ua)
{
if (!preg_match('/(UC|UBrowser)/ui', $ua)) {
return;
}
if (preg_match('/UCWEB/u', $ua)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'UC Browser';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
unset($this->data->browser->channel);
if (preg_match('/UCWEB/?([0-9]*[.][0-9]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
}
if (!$this->data->device->type) {
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
if (isset($this->data->os->name) && $this->data->os->name == 'Linux') {
$this->data->os->reset();
}
if (preg_match('/^IUC ?(U; ?iOS ([0-9._]+);/u', $ua, $match)) {
$this->data->os->name = 'iOS';
$this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);
}
if (preg_match('/^JUC ?(Linux; ?U; ?(?:Android)? ?([0-9.]+)[^;]*; ?[^;]+; ?([^;]*[^s])s*; ?[0-9]+*[0-9]+;?)/u', $ua, $match)) {
$this->data->os->name = 'Android';
$this->data->os->version = new Version([ 'value' => $match[1] ]);
$this->data->device = DataDeviceModels::identify('android', $match[2]);
}
if (preg_match('/(MIDP-2.0; U; [^;]+; ([^;]*[^s]))/u', $ua, $match)) {
$this->data->os->name = 'Android';
$this->data->device->model = $match[1];
$this->data->device->identified |= ConstantsId::PATTERN;
$device = DataDeviceModels::identify('android', $match[1]);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
}
}
if (preg_match('/((?:Linux|MIDP-2.0); U; Adr ([0-9.]+)(?:-update[0-9])?; [^;]+; ([^;]*[^s]))/u', $ua, $match)) {
$this->data->os->name = 'Android';
$this->data->os->version = new Version([ 'value' => $match[1] ]);
$this->data->device->model = $match[2];
$this->data->device->identified |= ConstantsId::PATTERN;
$device = DataDeviceModels::identify('android', $match[2]);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
}
}
if (preg_match('/((?:iOS|iPhone);/u', $ua)) {
$this->data->os->name = 'iOS';
$this->data->os->version = new Version([ 'value' => '1.0' ]);
if (preg_match('/OS[_ ]([0-9_]*);/u', $ua, $match)) {
$this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);
}
if (preg_match('/; ([^;]+))/u', $ua, $match)) {
$device = DataDeviceModels::identify('ios', $match[1]);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
}
}
}
if (preg_match('/(Symbian;/u', $ua)) {
$this->data->os->name = 'Series60';
$this->data->os->version = null;
$this->data->os->family = new Family([ 'name' => 'Symbian' ]);
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 |= ConstantsId::PATTERN;
$device = DataDeviceModels::identify('symbian', $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;
if (preg_match('/wds ([0-9]+.[0-9])/u', $ua, $match)) {
switch ($match[1]) {
case '7.1':
$this->data->os->version = new Version([ 'value' => '7.5' ]);
break;
case '8.0':
$this->data->os->version = new Version([ 'value' => '8.0' ]);
break;
case '8.1':
$this->data->os->version = new Version([ 'value' => '8.1' ]);
break;
case '10.0':
$this->data->os->version = new Version([ 'value' => '10.0' ]);
break;
}
}
if (preg_match('/; ([^;]+); ([^;]+))/u', $ua, $match)) {
$this->data->device->manufacturer = $match[1];
$this->data->device->model = $match[2];
$this->data->device->identified |= ConstantsId::PATTERN;
$device = DataDeviceModels::identify('wp', $match[2]);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
}
}
}
}
if (preg_match('/Ucweb/([0-9]*[.][0-9]*)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'UC Browser';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/ucweb-squid/u', $ua)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'UC Browser';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
unset($this->data->browser->channel);
}
if (preg_match('/) ?UC /u', $ua)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'UC Browser';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
unset($this->data->browser->version);
unset($this->data->browser->channel);
unset($this->data->browser->mode);
if ($this->data->device->type == ConstantsDeviceType::DESKTOP) {
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->browser->mode = 'desktop';
}
}
if (preg_match('/UC ?Browser/?([0-9.]*)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'UC Browser';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
unset($this->data->browser->channel);
if (!$this->data->device->type) {
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
}
if (preg_match('/UBrowser/?([0-9.]*)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'UC Browser';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
unset($this->data->browser->channel);
}
if (preg_match('/UCLite/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'UC Browser';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
unset($this->data->browser->channel);
}
/* U2 is the Proxy service used by UC Browser on low-end phones */
if (preg_match('/U2//u', $ua)) {
$this->data->browser->stock = false;
$this->data->browser->name = 'UC Browser';
$this->data->browser->mode = 'proxy';
$this->data->engine->name = 'Gecko';
/* UC Browser running on Windows 8 is identifing itself as U2, but instead its a Trident Webview */
if (isset($this->data->os->name) && isset($this->data->os->version)) {
if ($this->data->os->name == 'Windows Phone' && $this->data->os->version->toFloat() >= 8) {
$this->data->engine->name = 'Trident';
$this->data->browser->mode = '';
}
}
if ($this->data->device->identified < ConstantsId::MATCH_UA && preg_match('/; ([^;]*)) U2//u', $ua, $match)) {
$device = DataDeviceModels::identify('android', $match[1]);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
if (!isset($this->data->os->name) || ($this->data->os->name != 'Android' && (!isset($this->data->os->family) || $this->data->os->family->getName() != 'Android'))) {
$this->data->os->name = 'Android';
}
}
}
}
/* U3 is the Webkit based Webview used on Android phones */
if (preg_match('/U3//u', $ua)) {
$this->data->engine->name = 'Webkit';
}
}
private function detectUCEngine($ua)
{
if (isset($this->data->browser->name)) {
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 = ConstantsDeviceType::MOBILE;
$this->data->browser->mode = 'desktop';
$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);
$this->data->browser->mode = 'proxy';
}
if (isset($this->data->engine->name) && $this->data->engine->name == 'Presto') {
$this->data->engine->name = 'Webkit';
unset($this->data->engine->version);
}
}
}
}
/* Netfront */
private function detectNetfront($ua)
{
if (!preg_match('/(CNF|NF|NetFront|NX|Ave|COM2)/ui', $ua)) {
return;
}
/* Compact NetFront */
if (preg_match('/CNF/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Compact NetFront';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
/* NetFront */
if (preg_match('/Net[fF]ront/u', $ua) && !preg_match('/NetFrontNX/u', $ua)) {
$this->data->browser->name = 'NetFront';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
unset($this->data->browser->channel);
if (preg_match('/NetFront[ /]?([0-9.]*)/ui', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
/* Detect device type based on NetFront identifier */
if (preg_match('/MobilePhone/u', $ua)) {
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
if (preg_match('/DigitalMediaPlayer/u', $ua)) {
$this->data->device->type = ConstantsDeviceType::MEDIA;
}
if (preg_match('/PDA/u', $ua)) {
$this->data->device->type = ConstantsDeviceType::PDA;
}
if (preg_match('/MFP/u', $ua)) {
$this->data->device->type = ConstantsDeviceType::PRINTER;
}
if (preg_match('/(InettvBrowser|HbbTV|DTV|NetworkAVTV|BDPlayer)/u', $ua)) {
$this->data->device->type = ConstantsDeviceType::TELEVISION;
}
if (preg_match('/VCC/u', $ua)) {
$this->data->device->type = ConstantsDeviceType::CAR;
}
if (preg_match('/Kindle/u', $ua)) {
$this->data->device->type = ConstantsDeviceType::EREADER;
}
if (empty($this->data->device->type)) {
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
/* Detect OS based on NetFront identifier */
if (preg_match('/NF[0-9][0-9](?:WMPRO|PPC)//ui', $ua, $match)) {
if (!$this->data->isOs('Windows Mobile')) {
$this->data->os->reset([
'name' => 'Windows Mobile'
]);
}
}
}
if (preg_match('/(?:Browser/(?:NF|NetFr?ont-)|NF-Browser/|ACS-NF/|NetFront FullBrowser/)([0-9.]*)/ui', $ua, $match)) {
$this->data->browser->name = 'NetFront';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
unset($this->data->browser->channel);
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
/* AVE-Front */
if (preg_match('/(?:AVE-Front|AveFront)/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'NetFront';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Category=([^);]+)[);]/u', $ua, $match)) {
switch ($match[1]) {
case 'WebPhone':
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->device->subtype = ConstantsDeviceSubType::DESKTOP;
break;
case 'WP':
case 'Home Mail Tool':
case 'PDA':
$this->data->device->type = ConstantsDeviceType::PDA;
break;
case 'STB':
$this->data->device->type = ConstantsDeviceType::TELEVISION;
break;
case 'GAME':
$this->data->device->type = ConstantsDeviceType::GAMING;
$this->data->device->subtype = ConstantsDeviceSubType::CONSOLE;
break;
}
}
if (preg_match('/Product=([^);]+)[);]/u', $ua, $match)) {
if (in_array($match[1], [ 'ACCESS/NFPS', 'SUNSOFT/EnjoyMagic' ])) {
$this->data->device->setIdentification([
'manufacturer' => 'Sony',
'model' => 'PlayStation 2',
'type' => ConstantsDeviceType::GAMING,
'subtype' => ConstantsDeviceSubType::CONSOLE
]);
}
}
}
/* Netfront NX */
if (preg_match('/NX[/ ]([0-9.]+)/u', $ua, $match)) {
$this->data->browser->name = 'NetFront NX';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
unset($this->data->browser->channel);
if (empty($this->data->device->type) || $this->data->isType('desktop')) {
if (preg_match('/(DTV|HbbTV)/iu', $ua)) {
$this->data->device->type = ConstantsDeviceType::TELEVISION;
} else {
$this->data->device->type = ConstantsDeviceType::DESKTOP;
}
}
$this->data->os->reset();
}
/* The Sony Mylo 2 identifies as Firefox 2, but is NetFront */
if (preg_match('/Sony/COM2/u', $ua, $match)) {
$this->data->browser->reset([
'name' => 'NetFront',
'type' => ConstantsBrowserType::BROWSER
]);
}
}
/* Obigo */
private function detectObigo($ua)
{
$processObigoVersion = function ($version) {
$result = [
'value' => $version
];
if (preg_match('/[0-9.]+/', $version, $match)) {
$result['details'] = 2;
}
if (preg_match('/([0-9])[A-Z]/', $version, $match)) {
$result['value'] = intval($match[1]);
$result['alias'] = $version;
}
return $result;
};
if (preg_match('/(?:Obigo|Teleca|AU-MIC|MIC/)/ui', $ua)) {
$this->data->browser->name = 'Obigo';
$this->data->browser->version = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Obigo/0?([0-9.]+)/iu', $ua, $match)) {
$this->data->browser->version = new Version($processObigoVersion($match[1]));
} elseif (preg_match('/(?:MIC|TelecaBrowser)/(WAP|[A-Z])?0?([0-9.]+[A-Z]?)/iu', $ua, $match)) {
$this->data->browser->version = new Version($processObigoVersion($match[2]));
if (!empty($match[1])) {
$this->data->browser->name = 'Obigo ' . strtoupper($match[1]);
}
} elseif (preg_match('/(?:Obigo(?:InternetBrowser|[- ]Browser)?|Teleca)/(WAP|[A-Z])?[0O]?([0-9.]+[A-Z]?)/ui', $ua, $match)) {
$this->data->browser->version = new Version($processObigoVersion($match[2]));
if (!empty($match[1])) {
$this->data->browser->name = 'Obigo ' . strtoupper($match[1]);
}
} elseif (preg_match('/(?:Obigo|Teleca)[- ]([WAP|[A-Z])?0?([0-9.]+[A-Z]?)(?:[0-9])?(?:[/;]|$)/ui', $ua, $match)) {
$this->data->browser->version = new Version($processObigoVersion($match[2]));
if (!empty($match[1])) {
$this->data->browser->name = 'Obigo ' . strtoupper($match[1]);
}
} elseif (preg_match('/Browser/(?:Obigo|Teleca)[_-]?(?:Browser/)?(WAP|[A-Z])?0?([0-9.]+[A-Z]?)/ui', $ua, $match)) {
$this->data->browser->version = new Version($processObigoVersion($match[2]));
if (!empty($match[1])) {
$this->data->browser->name = 'Obigo ' . strtoupper($match[1]);
}
} elseif (preg_match('/Obigo Browser (WAP|[A-Z])?0?([0-9.]+[A-Z]?)/ui', $ua, $match)) {
$this->data->browser->version = new Version($processObigoVersion($match[2]));
if (!empty($match[1])) {
$this->data->browser->name = 'Obigo ' . strtoupper($match[1]);
}
}
}
if (preg_match('/[^A-Z](Q)0?([0-9][A-Z])/u', $ua, $match)) {
$this->data->browser->name = 'Obigo ' . $match[1];
$this->data->browser->version = new Version($processObigoVersion($match[2]));
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
}
/* ANT Galio and ANT Fresco */
private function detectAnt($ua)
{
if (preg_match('/ANTFresco/([0-9.]+)/iu', $ua, $match)) {
$this->data->browser->name = 'ANT Fresco';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/ANTGalio/([0-9.]+)/iu', $ua, $match)) {
$this->data->browser->name = 'ANT Galio';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
}
/* Seraphic Sraf */
private function detectSraf($ua)
{
if (preg_match('/sraf_tv_browser/u', $ua)) {
$this->data->browser->name = 'Seraphic Sraf';
$this->data->browser->version = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::TELEVISION;
}
if (preg_match('/SRAF/([0-9.]+)/iu', $ua, $match)) {
$this->data->browser->name = 'Seraphic Sraf';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::TELEVISION;
}
}
/* MachBlue */
private function detectMachBlue($ua)
{
if (preg_match('/mbxtWebKit/([0-9.]*)/u', $ua, $match)) {
$this->data->os->name = '';
$this->data->browser->name = 'MachBlue XT';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::TELEVISION;
}
if ($ua == 'MachBlue') {
$this->data->os->name = '';
$this->data->browser->name = 'MachBlue XT';
$this->data->device->type = ConstantsDeviceType::TELEVISION;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
}
/* Espial */
private function detectEspial($ua)
{
if (preg_match('/Espial/u', $ua)) {
$this->data->browser->name = 'Espial';
$this->data->browser->channel = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->os->name = '';
$this->data->os->version = null;
if ($this->data->device->type != ConstantsDeviceType::TELEVISION) {
$this->data->device->type = ConstantsDeviceType::TELEVISION;
$this->data->device->manufacturer = null;
$this->data->device->model = null;
}
if (preg_match('/Espial(?: Browser|TVBrowser)?/(?:sig)?([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
if (preg_match('/;(L6200|L7200)/u', $ua, $match)) {
$this->data->device->manufacturer = 'Toshiba';
$this->data->device->model = 'Regza ' . $match[1];
$this->data->device->series = 'Smart TV';
$this->data->device->identified |= ConstantsId::MATCH_UA;
$this->data->device->generic = false;
}
}
}
/* Iris */
private function detectIris($ua)
{
if (preg_match('/Iris//u', $ua)) {
$this->data->browser->name = 'Iris';
$this->data->browser->hidden = false;
$this->data->browser->stock = false;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Iris/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
if (preg_match('/ WM([0-9]) /u', $ua, $match)) {
$this->data->device->reset();
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->os->reset();
$this->data->os->name = 'Windows Mobile';
$this->data->os->version = new Version([ 'value' => $match[1] . '.0' ]);
}
if (preg_match('/Windows NT/u', $ua, $match)) {
$this->data->browser->mode = 'desktop';
$this->data->device->reset();
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->os->reset();
$this->data->os->name = 'Windows Mobile';
}
}
}
/* Dolfin */
private function detectDolfin($ua)
{
if (preg_match('/(Dolfin|Jasmine)/u', $ua)) {
$this->data->browser->name = 'Dolfin';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/(?:Dolfin|Jasmine)/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
if (preg_match('/Browser/Dolfin([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
}
}
/* WebOS */
private function detectWebOSBrowser($ua)
{
if (preg_match('/wOSBrowser/u', $ua)) {
$this->data->browser->name = 'webOS Browser';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if ($this->data->os->name != 'webOS') {
$this->data->os->name = 'webOS';
}
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 = ConstantsId::NONE;
}
}
}
/* Sailfish */
private function detectSailfishBrowser($ua)
{
if (preg_match('/Sailfish ?Browser/u', $ua)) {
$this->data->browser->name = 'Sailfish Browser';
$this->data->browser->stock = true;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Sailfish ?Browser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
}
}
}
/* Silk */
private function detectSilk($ua)
{
if (preg_match('/Silk/u', $ua)) {
if (preg_match('/Silk-Accelerated/u', $ua) || !preg_match('/PlayStation/u', $ua)) {
$this->data->browser->name = 'Silk';
$this->data->browser->channel = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Silk/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
}
if (preg_match('/; ([^;]*[^;s])s+Build/u', $ua, $match)) {
$this->data->device = DataDeviceModels::identify('android', $match[1]);
}
if (!$this->data->device->identified) {
$this->data->device->manufacturer = 'Amazon';
$this->data->device->model = 'Kindle Fire';
$this->data->device->type = ConstantsDeviceType::TABLET;
$this->data->device->identified |= ConstantsId::INFER;
if (isset($this->data->os->name) && ($this->data->os->name != 'Android' || $this->data->os->name != 'FireOS')) {
$this->data->os->name = 'FireOS';
$this->data->os->family = new Family([ 'name' => 'Android' ]);
$this->data->os->alias = null;
$this->data->os->version = null;
}
}
}
}
}
/* Nokia */
private function detectNokiaBrowser($ua)
{
if (!preg_match('/(BrowserNG|Nokia|OSRE|Ovi|Maemo)/ui', $ua)) {
return;
}
/* Nokia Browser */
if (preg_match('/BrowserNG/u', $ua)) {
$this->data->browser->name = 'Nokia Browser';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/BrowserNG/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3, 'builds' => false ]);
}
}
if (preg_match('/NokiaBrowser/u', $ua)) {
$this->data->browser->name = 'Nokia Browser';
$this->data->browser->channel = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/NokiaBrowser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
}
}
if (preg_match('/Nokia-Communicator-WWW-Browser/u', $ua)) {
$this->data->browser->name = 'Nokia Browser';
$this->data->browser->channel = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Nokia-Communicator-WWW-Browser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
}
}
/* Nokia Xpress for S30+, S40 and Windows Phone */
if (preg_match('/OSRE/u', $ua)) {
$this->data->browser->name = 'Nokia Xpress';
$this->data->browser->mode = 'proxy';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->os->name = null;
$this->data->os->version = null;
}
if (preg_match('/S40OviBrowser/u', $ua)) {
$this->data->browser->name = 'Nokia Xpress';
$this->data->browser->mode = 'proxy';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/S40OviBrowser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
}
if (preg_match('/Nokia([^/]+)//u', $ua, $match)) {
$this->data->device->manufacturer = 'Nokia';
$this->data->device->model = $match[1];
$this->data->device->identified |= ConstantsId::PATTERN;
if (isset($this->data->device->model)) {
$device = DataDeviceModels::identify('s40', $this->data->device->model);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
}
}
if (isset($this->data->device->model)) {
$device = DataDeviceModels::identify('asha', $this->data->device->model);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->os->name = 'Nokia Asha Platform';
$this->data->os->version = new Version([ 'value' => '1.0' ]);
$this->data->device = $device;
if (preg_match('/java_runtime_version=Nokia_Asha_([0-9_]+);/u', $ua, $match)) {
$this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);
}
}
}
}
if (preg_match('/NOKIALumia([0-9]+)/u', $ua, $match)) {
$this->data->device->manufacturer = 'Nokia';
$this->data->device->model = $match[1];
$this->data->device->identified |= ConstantsId::PATTERN;
$device = DataDeviceModels::identify('wp', $this->data->device->model);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
$this->data->os->name = 'Windows Phone';
}
}
}
/* MicroB - the default browser for maemo */
if (preg_match('/Maemo[ |_]Browser/u', $ua)) {
$this->data->browser->name = 'MicroB';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Maemo[ |_]Browser[ |_]([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
}
}
}
/* Konqueror */
private function detectKonqueror($ua)
{
if (preg_match('/[k|K]onqueror//u', $ua)) {
$this->data->browser->name = 'Konqueror';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/[k|K]onqueror/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
if ($this->data->device->type == '') {
$this->data->device->type = ConstantsDeviceType::DESKTOP;
}
}
}
/* OmniWeb */
private function detectOmniWeb($ua)
{
if (preg_match('/OmniWeb/u', $ua)) {
$this->data->browser->name = 'OmniWeb';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->version = null;
if (preg_match('/OmniWeb/v?([0-9])[0-9][0-9]/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 1 ]);
}
if (preg_match('/OmniWeb/([0-9].[0-9.]+)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
}
$this->data->device->reset([
'type' => ConstantsDeviceType::DESKTOP
]);
if (!empty($this->data->browser->version)) {
if ($this->data->browser->version->is('<', 3)) {
$this->data->os->name = 'NextStep';
$this->data->os->version = null;
}
if ($this->data->browser->version->is('>=', 4)) {
if (empty($this->data->os->name) || $this->data->os->name != 'OS X') {
$this->data->os->name = 'OS X';
$this->data->os->version = null;
}
}
}
}
}
/* Other browsers */
private function detectDesktopBrowsers($ua)
{
if (!preg_match('/(WebPositive|WebExplorer|WorldWideweb|Midori|Maxthon|Browse|Flow)/ui', $ua)) {
return;
}
/* WebPositive */
if (preg_match('/WebPositive/u', $ua, $match)) {
$this->data->browser->name = 'WebPositive';
$this->data->browser->channel = '';
$this->data->browser->version = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/WebPositive/([0-9].[0-9.]+)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
}
}
/* IBM WebExplorer */
if (preg_match('/IBM[- ]WebExplorer[ -]?(DLL ?|Window API ?)?/u', $ua)) {
$this->data->browser->name = 'IBM WebExplorer';
$this->data->browser->channel = '';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/IBM[- ]WebExplorer[ -]?(?:DLL ?|Window API ?)?/v([0-9].[0-9.]+)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
$this->data->os->name = 'OS/2';
$this->data->device->type = 'desktop';
}
/* WorldWideweb */
if (preg_match('/WorldWideweb (NEXT)/u', $ua, $match)) {
$this->data->browser->name = 'WorldWideWeb';
$this->data->browser->channel = '';
$this->data->browser->version = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->os->name = 'NextStep';
$this->data->device->type = 'desktop';
}
/* Midori */
if (preg_match('/Midori/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Midori';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->manufacturer = null;
$this->data->device->model = null;
$this->data->device->type = ConstantsDeviceType::DESKTOP;
if (isset($this->data->os->name) && $this->data->os->name == 'OS X') {
$this->data->os->name = null;
$this->data->os->version = null;
}
}
if (preg_match('/midori(?:/[0-9.]*)?$/u', $ua)) {
$this->data->browser->name = 'Midori';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::DESKTOP;
if (preg_match('/midori/([0-9.]*)$/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
}
/* Maxthon */
if (preg_match('/Maxthon/iu', $ua, $match)) {
$this->data->browser->name = 'Maxthon';
$this->data->browser->channel = '';
$this->data->browser->version = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Maxthon[/' ](?([0-9.]*))?/iu', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
}
if (isset($this->data->os->name) && $this->data->browser->version && $this->data->os->name == 'Windows' && $this->data->browser->version->toFloat() < 4) {
$this->data->browser->version->details = 1;
}
}
/* Browse for Remix OS */
if (preg_match('/^Browse/([0-9.]+)/u', $ua, $match)) {
$this->data->browser->name = 'Browse';
$this->data->browser->channel = '';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
/* Browse for Flow */
if (preg_match('/ Flow/([0-9.]+)/u', $ua, $match)) {
$this->data->browser->name = 'Flow';
$this->data->browser->channel = '';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
unset($this->data->browser->family);
if (preg_match('/EkiohFlow/[0-9.]+M/u', $ua)) {
$this->data->browser->name = 'Flow Nightly Build';
$this->data->browser->version = null;
}
}
}
private function detectMobileBrowsers($ua)
{
if (!preg_match('/(Huawei|Ninesky|Skyfire|Dolphin|QQ|360|QHBrowser|Mercury|iBrowser|Puffin|MiniB|MxNitro|Sogou|Xiino|Palmscape|WebPro|Vision|MiuiBrowser)/ui', $ua)) {
return;
}
/* Huawei Browser */
if (preg_match('/HuaweiBrowser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Huawei Browser';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
/* Xiaomi MIUI Browser */
if (preg_match('/MiuiBrowser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'MIUI Browser';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (!$this->data->os->isFamily('Android')) {
$this->data->os->reset();
$this->data->os->name = 'Android';
$this->data->device->manufacturer = 'Xiaomi';
$this->data->device->model = null;
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
}
/* 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] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (isset($this->data->device->manufacturer) && $this->data->device->manufacturer == 'Apple') {
$this->data->device->reset();
}
if (!$this->data->os->isFamily('Android')) {
$this->data->os->reset();
$this->data->os->name = 'Android';
}
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
/* Skyfire */
if (preg_match('/Skyfire/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Skyfire';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->os->name = 'Android';
$this->data->os->version = null;
}
/* Dolphin HD */
if (preg_match('/Dolphin(?:HD|Browser)?(?:INT|CN)?/(?:INT|CN)?-?([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Dolphin';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
/* QQ Browser */
if (preg_match('/(M?QQBrowser)/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'QQ Browser';
$version = $match[2];
if (preg_match('/^[0-9][0-9]$/u', $version)) {
$version = $version[0] . '.' . $version[1];
}
$this->data->browser->version = new Version([ 'value' => $version, 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->channel = '';
if (!isset($this->data->os->name) && $match[1] == 'QQBrowser') {
$this->data->os->name = 'Windows';
}
if (preg_match('/MQQBrowser/[0-9.]+/Adr (Linux; U; ([0-9.]+); [^;]+; (.+) Build/u', $ua, $match)) {
$this->data->os->reset([
'name' => 'Android',
'version' => new Version([ 'value' => $match[1] ])
]);
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->device->model = $match[2];
$this->data->device->identified |= ConstantsId::PATTERN;
$device = DataDeviceModels::identify('android', $match[2]);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
}
}
if (preg_match('/MQQBrowser/[0-9.]+/WP7 ([^;]+;WPOS:([0-9].[0-9])[0-9.]*;([^;]+); ([^)]+))/u', $ua, $match)) {
$this->data->os->reset([
'name' => 'Windows Phone',
'version' => new Version([ 'value' => $match[1] ])
]);
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->device->manufacturer = $match[2];
$this->data->device->model = $match[3];
$this->data->device->identified |= ConstantsId::PATTERN;
$device = DataDeviceModels::identify('wp', $match[3]);
if ($device->identified) {
$device->identified |= $this->data->device->identified;
$this->data->device = $device;
}
}
}
if (preg_match('/MQQBrowser/Mini([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'QQ Browser Mini';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->channel = '';
}
if (preg_match('/QQ/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'QQ Browser';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->channel = '';
}
/* 360 Phone Browser */
if (preg_match('/360 (?:Aphone|Android Phone) Browser/u', $ua, $match)) {
$this->data->browser->name = 'Qihoo 360 Browser';
$this->data->browser->family = null;
$this->data->browser->channel = '';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/360 (?:Aphone|Android Phone) Browser ((?:Version |V)?([0-9.]*)(?:beta)?)/u', $ua, $match)) {
$this->data->browser->name = 'Qihoo 360 Browser';
$this->data->browser->family = null;
$this->data->browser->channel = '';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (!$this->data->os->isFamily('Android')) {
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->os->reset([
'name' => 'Android'
]);
}
}
if (preg_match('/360%20(?:Browser|Lite)/([0-9.]+)/u', $ua, $match)) {
$this->data->browser->name = 'Qihoo 360 Browser';
$this->data->browser->family = null;
$this->data->browser->channel = '';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/QHBrowser/([0-9.]+)/u', $ua, $match)) {
$version = $match[1];
if (preg_match('/^[0-9][0-9][0-9]$/u', $version)) {
$version = $version[0] . '.' . $version[1] . '.' . $version[2];
}
$this->data->browser->name = 'Qihoo 360 Browser';
$this->data->browser->channel = '';
$this->data->browser->version = new Version([ 'value' => $version ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (!$this->data->isOs('iOS')) {
$this->data->device->type = ConstantsDeviceType::MOBILE;
$this->data->os->reset([
'name' => 'iOS'
]);
}
}
/* Mercury */
if (preg_match('/(?:^| )Mercury/([0-9.]+)/u', $ua, $match)) {
$version = $match[1];
if (preg_match('/^[0-9][0-9][0-9]$/u', $version)) {
$version = $version[0] . '.' . $version[1] . '.' . $version[2];
}
$this->data->browser->name = 'Mercury Browser';
$this->data->browser->channel = '';
$this->data->browser->version = new Version([ 'value' => $version ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
/* iBrowser */
if (preg_match('/(?:^| )iBrowser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'iBrowser';
$version = $match[1];
if (preg_match('/^[0-9][0-9]$/u', $version)) {
$version = $version[0] . '.' . $version[1];
}
$this->data->browser->version = new Version([ 'value' => $version, 'details' => 2 ]);
$this->data->browser->channel = '';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
if (preg_match('/iBrowser/Mini([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'iBrowser Mini';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->channel = '';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
/* Puffin */
if (preg_match('/Puffin/([0-9.]+)([IA])?([PT])?/u', $ua, $match)) {
$this->data->browser->name = 'Puffin';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => (intval(substr(strrchr($match[1], '.'), 1)) > 99 ? -1 : null) ]);
$this->data->browser->mode = 'proxy';
$this->data->browser->channel = '';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (isset($match[2])) {
switch ($match[2]) {
case 'A':
if (!$this->data->isOs('Android')) {
$this->data->os->reset([ 'name' => 'Android' ]);
}
break;
case 'I':
if (!$this->data->isOs('iOS')) {
$this->data->os->reset([ 'name' => 'iOS' ]);
}
break;
}
}
if (isset($match[3])) {
switch ($match[3]) {
case 'P':
$this->data->device->type = ConstantsDeviceType::MOBILE;
if ($this->data->os->name == 'iOS' && empty($this->data->device->model)) {
$this->data->device->manufacturer = 'Apple';
$this->data->device->model = 'iPhone';
$this->data->device->identified = ConstantsId::MATCH_UA;
}
break;
case 'T':
$this->data->device->type = ConstantsDeviceType::TABLET;
if ($this->data->os->name == 'iOS' && empty($this->data->device->model)) {
$this->data->device->manufacturer = 'Apple';
$this->data->device->model = 'iPad';
$this->data->device->identified = ConstantsId::MATCH_UA;
}
break;
}
}
}
/* MiniBrowser Mobile */
if (preg_match('/MiniBr?owserM(?:obile)?/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'MiniBrowser';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::MOBILE;
if (!$this->data->isOs('Series60')) {
$this->data->os->name = 'Series60';
$this->data->os->version = null;
}
}
/* Maxthon */
if (preg_match('/MxNitro/iu', $ua, $match)) {
$this->data->browser->name = 'Maxthon Nitro';
$this->data->browser->channel = '';
$this->data->browser->version = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/MxNitro/([0-9.]*)/iu', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 3 ]);
}
}
/* Sogou Mobile */
if (preg_match('/SogouAndroidBrowser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Sogou Mobile';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
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 = ConstantsId::NONE;
}
}
/* Xiino */
if (preg_match('/Xiino/([0-9.]+)/u', $ua, $match)) {
$this->data->browser->name = 'Xiino';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::PDA;
$this->data->os->name = 'Palm OS';
if (preg_match('/(v. ([0-9.]+)/u', $ua, $match)) {
$this->data->os->version = new Version([ 'value' => $match[1] ]);
}
}
/* Palmscape */
if (preg_match('/Palmscape/(?:PR)?([0-9.]+)/u', $ua, $match)) {
$this->data->browser->name = 'Palmscape';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::PDA;
$this->data->os->name = 'Palm OS';
if (preg_match('/(v. ([0-9.]+)/u', $ua, $match)) {
$this->data->os->version = new Version([ 'value' => $match[1] ]);
}
}
/* Novarra WebPro */
if (preg_match('/WebPro/u', $ua) && preg_match('/PalmOS/u', $ua)) {
$this->data->browser->name = 'WebPro';
$this->data->browser->version = null;
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/WebPro/?([0-9.]*)/u', $ua, $match)) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
}
/* Novarra Vision */
if (preg_match('/(?:Vision-Browser|Novarra-Vision)/?([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Novarra Vision';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->family = null;
$this->data->browser->mode = 'proxy';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if ($this->data->device->type != ConstantsDeviceType::MOBILE) {
$this->data->os->reset();
$this->data->device->type = ConstantsDeviceType::MOBILE;
}
}
}
private function detectTelevisionBrowsers($ua)
{
if (!preg_match('/(Roku|LG Browser|NetCast|SonyBrowserCore|Dream|Planetweb)/ui', $ua)) {
return;
}
/* Web on Roku */
if (preg_match('/Roku/u', $ua) && preg_match('/Web/([0-9.]+)/u', $ua, $match)) {
$this->data->browser->name = 'Web';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
/* LG Browser */
if (preg_match('/LG Browser/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'LG Browser';
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->type = ConstantsDeviceType::TELEVISION;
}
if (preg_match('/NetCast/u', $ua) && preg_match('/SmartTV//u', $ua)) {
unset($this->data->browser->name);
unset($this->data->browser->version);
}
/* Sony Browser */
if (preg_match('/SonyBrowserCore/([0-9.]*)/u', $ua, $match)) {
unset($this->data->browser->name);
unset($this->data->browser->version);
$this->data->device->type = ConstantsDeviceType::TELEVISION;
}
/* Dreamkey */
if (preg_match('/DreamKey/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Dreamkey';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->setIdentification([
'manufacturer' => 'Sega',
'model' => 'Dreamcast',
'type' => ConstantsDeviceType::GAMING,
'subtype' => ConstantsDeviceSubType::CONSOLE
]);
}
/* Dream Passport */
if (preg_match('/DreamPassport/([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Dream Passport';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->device->setIdentification([
'manufacturer' => 'Sega',
'model' => 'Dreamcast',
'type' => ConstantsDeviceType::GAMING,
'subtype' => ConstantsDeviceSubType::CONSOLE
]);
}
/* Planetweb */
if (preg_match('/Planetweb/v?([0-9.]*)/u', $ua, $match)) {
$this->data->browser->name = 'Planetweb';
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (preg_match('/Dreamcast/u', $ua, $match)) {
$this->data->device->setIdentification([
'manufacturer' => 'Sega',
'model' => 'Dreamcast',
'type' => ConstantsDeviceType::GAMING,
'subtype' => ConstantsDeviceSubType::CONSOLE
]);
}
if (preg_match('/SPS/u', $ua, $match)) {
$this->data->device->setIdentification([
'manufacturer' => 'Sony',
'model' => 'PlayStation 2',
'type' => ConstantsDeviceType::GAMING,
'subtype' => ConstantsDeviceSubType::CONSOLE
]);
}
}
}
private function detectRemainingBrowsers($ua)
{
if ($data = DataApplications::identifyBrowser($ua)) {
$this->data->browser->set($data['browser']);
if (!empty($data['device'])) {
$this->data->device->set($data['device']);
}
}
}
private function detectWapBrowsers($ua)
{
if (!preg_match('/(Dorado|MAUI)/ui', $ua, $match)) {
return;
}
if (preg_match('/Browser/Dorado([0-9.]*)/ui', $ua, $match)) {
$this->data->browser->name = 'Dorado WAP';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
}
if (preg_match('/Dorado WAP-Browser/([0-9.]*)/ui', $ua, $match)) {
$this->data->browser->name = 'Dorado WAP';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
$this->data->browser->version = new Version([ 'value' => $match[1], 'details' => 2 ]);
}
if (preg_match('/MAUI[ _]WAP[ _]Browser(?:/([0-9.]*))?/ui', $ua, $match)) {
$this->data->browser->name = 'MAUI WAP';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
if (isset($match[1])) {
$this->data->browser->version = new Version([ 'value' => $match[1] ]);
}
}
if (preg_match('/WAP Browser/MAUI/ui', $ua, $match)) {
$this->data->browser->name = 'MAUI WAP';
$this->data->browser->type = ConstantsBrowserType::BROWSER;
}
}
}