$this->data->os->name = 'Series40'; $this->data->os->version = null; } } } if (!($this->data->device->identified & Constants\Id::MATCH_UA)) { $device = Data\DeviceModels::identify('symbian', $this->data->device->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; $this->data->os->family = new Family([ 'name' => 'Symbian' ]); } } } $this->identifyBasedOnIdentifier(); } } /* Samsung */ private function detectSamsung($ua) { if (isset($this->data->device->manufacturer)) { return; } if (preg_match('/(?:SAMSUNG; )?SAMSUNG ?[-\/]?([^;\/\)_,]+)/ui', $ua, $match)) { if ($match[1] === 'Browser') { return; } $this->data->device->manufacturer = 'Samsung'; $this->data->device->model = Data\DeviceModels::cleanup($match[1]); $this->data->device->identifier = $match[0]; $this->data->device->identified |= Constants\Id::PATTERN; $this->data->device->generic = false; $this->data->device->type = Constants\DeviceType::MOBILE; if ($this->data->isOS('Bada')) { $device = Data\DeviceModels::identify('bada', $this->data->device->model); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; } } if ($this->data->isOS('Series60')) { $device = Data\DeviceModels::identify('symbian', $this->data->device->model); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; } } if (!$this->data->os->isDetected()) { if (preg_match('/Jasmine\/([0-9.]*)/u', $ua, $match)) { $version = $match[1]; $device = Data\DeviceModels::identify('touchwiz', $this->data->device->model); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; $this->data->os->name = 'Touchwiz'; switch ($version) { case '0.8': $this->data->os->version = new Version([ 'value' => '1.0' ]); break; case '1.0': $this->data->os->version = new Version([ 'value' => '2.0', 'alias' => '2.0 or earlier' ]); break; } } } if (preg_match('/(?:Dolfin\/([0-9.]*)|Browser\/Dolfin([0-9.]*))/u', $ua, $match)) { $version = !empty($match[1]) ? $match[1] : $match[2]; $device = Data\DeviceModels::identify('bada', $this->data->device->model); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; $this->data->os->name = 'Bada'; switch ($version) { case '2.0': $this->data->os->version = new Version([ 'value' => '1.0' ]); break; case '2.2': $this->data->os->version = new Version([ 'value' => '1.2' ]); break; } } else { $device = Data\DeviceModels::identify('touchwiz', $this->data->device->model); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; $this->data->os->name = 'Touchwiz'; switch ($version) { case '1.0': $this->data->os->version = new Version([ 'value' => '2.0', 'alias' => '2.0 or earlier' ]); break; case '1.5': $this->data->os->version = new Version([ 'value' => '2.0' ]); break; case '2.0': $this->data->os->version = new Version([ 'value' => '3.0' ]); break; } } } } } $this->identifyBasedOnIdentifier(); } } /* Generic models */ private function detectGenericMobileModels($ua) { if ($this->data->device->identified & Constants\Id::PATTERN) { return; } if (isset($this->data->device->manufacturer)) { return; } if (!preg_match('/(T-Mobile|Danger|HPiPAQ|Acer|Amoi|AIRNESS|ASUS|BenQ|maui|ALCATEL|Bird|COOLPAD|CELKON|Coship|Cricket|DESAY|Diamond|dopod|Ericsson|FLY|GIONEE|GT-|Haier|HIKe|Hisense|HS|HTC|T[0-9]{4,4}|HUAWEI|Karbonn|KWC|KONKA|KTOUCH|K-Touch|Lenovo|Lephone|LG|Micromax|MOT|Nexian|NEC|NGM|OPPO|Panasonic|Pantech|Philips|Sagem|Sanyo|Sam|SEC|SGH|SCH|SIE|Sony|SE|SHARP|Spice|Tecno|T-smart|TCL|Tiphone|Toshiba|UTStar|Videocon|vk|Vodafone|VSUN|Wynncom|Xiaomi|YUANDA|Zen|Ziox|ZTE|WAP)/ui', $ua)) { return; } $this->data->device->identifyModel('/T-Mobile[_ ]([^\/;]+)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'T-Mobile' ]); $this->data->device->identifyModel('/Danger hiptop ([0-9.]+)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Danger', 'model' => 'Hiptop' ]); $this->data->device->identifyModel('/HP(iPAQ[0-9A-Za-z]+)\//u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'HP' ]); $this->data->device->identifyModel('/Acer[_-]?([^\s\/_]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Acer' ]); $this->data->device->identifyModel('/Amoi[ -]([^\s\/_]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Amoi' ]); $this->data->device->identifyModel('/AIRNESS-([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Airness' ]); $this->data->device->identifyModel('/ASUS-([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Asus' ]); $this->data->device->identifyModel('/BenQ[ -]([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'BenQ' ]); $this->data->device->identifyModel('/ maui ([a-z0-9]+)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'BenQ', 'model' => function ($model) { return 'Maui ' . strtoupper($model); } ]); $this->data->device->identifyModel('/ALCATEL[_-]([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Alcatel', 'model' => function ($model) { if (preg_match('/^TRIBE ([^\s]+)/ui', $model, $match)) { $model = 'One Touch Tribe ' . $match[1]; } elseif (preg_match('/^ONE TOUCH ([^\s]*)/ui', $model, $match)) { $model = 'One Touch ' . $match[1]; } elseif (preg_match('/^OT[-\s]*([^\s]*)/ui', $model, $match)) { $model = 'One Touch ' . $match[1]; } return $model; } ]); $this->data->device->identifyModel('/Bird[ _\-\.]([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Bird' ]); $this->data->device->identifyModel('/(?:YL-|YuLong-)?COOLPAD([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Coolpad' ]); $this->data->device->identifyModel('/CELKON\.([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Celkon' ]); $this->data->device->identifyModel('/Coship ([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Coship' ]); $this->data->device->identifyModel('/Cricket-([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Cricket' ]); $this->data->device->identifyModel('/DESAY[ _]([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'DESAY' ]); $this->data->device->identifyModel('/Diamond_([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Diamond' ]); $this->data->device->identifyModel('/dopod[-_]?([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Dopod' ]); $this->data->device->identifyModel('/^Ericsson([^\/]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Ericsson' ]); $this->data->device->identifyModel('/^(R[0-9]{3,3}) [0-9\.]+ WAP/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Ericsson' ]); $this->data->device->identifyModel('/FLY_]?([^\s\/]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Fly' ]); $this->data->device->identifyModel('/GIONEE[-_ ]([^\s\/;]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Gionee' ]); $this->data->device->identifyModel('/GIONEE([A-Z0-9]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Gionee' ]); $this->data->device->identifyModel('/HIKe_([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'HIKe' ]); $this->data->device->identifyModel('/HAIER-([A-Z][0-9]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Haier' ]); $this->data->device->identifyModel('/Hisense[ -](?:HS-)?([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Hisense' ]); $this->data->device->identifyModel('/HS-([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Hisense' ]); $this->data->device->identifyModel('/HTC[\s_-]?([^\s\/\(\);][^\/\(\);]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'HTC' ]); $this->data->device->identifyModel('/(?:HTC_)?([A-Z0-9_]+_T[0-9]{4,4})/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'HTC' ]); $this->data->device->identifyModel('/HUAWEI[\s_-]?([^\/\)\()]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Huawei' ]); $this->data->device->identifyModel('/Karbonn ([a-z0-9]+(?: ?Star| ?Plus|\+)?)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Karbonn' ]); $this->data->device->identifyModel('/KWC-([^\s\/]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Kyocera' ]); $this->data->device->identifyModel('/KONKA[-_]?([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Konka' ]); $this->data->device->identifyModel('/TIANYU-KTOUCH\/([^\/]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'K-Touch' ]); $this->data->device->identifyModel('/K-Touch_?([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'K-Touch' ]); $this->data->device->identifyModel('/Lenovo[_-]?([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Lenovo' ]); $this->data->device->identifyModel('/Lephone_([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Lephone' ]); $this->data->device->identifyModel('/LGE?([A-Z]{2,2}[0-9]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'LG' ]); $this->data->device->identifyModel('/LGE?(?:\/|-|_)([^\s\)\-\[\/]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'LG' ]); $this->data->device->identifyModel('/LGE? ?([A-Z]*[0-9]+[A-Z]?)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'LG' ]); $this->data->device->identifyModel('/Micromax([^\)]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Micromax' ]); $this->data->device->identifyModel('/^MOTO-?([^\/_]+)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Motorola' ]); $this->data->device->identifyModel('/MOT-([^\/_\.]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Motorola' ]); $this->data->device->identifyModel('/Motorola-([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Motorola', 'model' => function ($model) { return strtoupper($model); } ]); $this->data->device->identifyModel('/Motorola[_ ]([^\/_;\)]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Motorola' ]); $this->data->device->identifyModel('/Moto([^\/\s_;r][^\/\s_;]*)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Motorola' ]); $this->data->device->identifyModel('/Nexian([^\/_]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Nexian' ]); $this->data->device->identifyModel('/NEC-([^\/_]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'NEC' ]); $this->data->device->identifyModel('/NGM_([^\/_]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'NGM' ]); $this->data->device->identifyModel('/OPPO_([^\/_]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Oppo' ]); $this->data->device->identifyModel('/Panasonic-([^\/_]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Panasonic' ]); $this->data->device->identifyModel('/Pantech[-_]?([^\/_]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Pantech' ]); $this->data->device->identifyModel('/Philips ?([A-Z]?[0-9@]+[a-z]?)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Philips' ]); $this->data->device->identifyModel('/PHILIPS-([a-zA-Z0-9@]+(?: [0-9]+)?)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Philips', 'model' => function ($model) { if (preg_match('/Az@lis([0-9]{3,3})/ui', $model, $match)) { return 'Az@lis ' . $match[1]; } if (preg_match('/Fisio ?([0-9]{3,3})/ui', $model, $match)) { return 'Fisio ' . $match[1]; } return $model; } ]); $this->data->device->identifyModel('/SAGEM-([A-Z0-9\-]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Sagem' ]); $this->data->device->identifyModel('/Sanyo-([A-Z0-9]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Sanyo' ]); $this->data->device->identifyModel('/sam-([A-Z][0-9]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Samsung' ]); $this->data->device->identifyModel('/SEC-(SGH[A-Z][0-9]+)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Samsung', 'model' => function ($model) { return str_replace('SGH', 'SGH-', $model); } ]); $this->data->device->identifyModel('/((?:SGH|SCH)-[A-Z][0-9]+)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Samsung' ]); $this->data->device->identifyModel('/(GT-[A-Z][0-9]+[A-Z]?)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Samsung' ]); $this->data->device->identifyModel('/(?:Siemens |SIE-)([A-Z]+[0-9]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Siemens' ]); $this->data->device->identifyModel('/SIE-([0-9]{4,4}|[A-Z]{4,4})/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Siemens' ]); $this->data->device->identifyModel('/Sony ([A-Z0-9\-]+)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Sony' ]); $this->data->device->identifyModel('/SE([A-Z][0-9]+[a-z])/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Sony Ericsson' ]); $this->data->device->identifyModel('/sony-ericsson ([A-Z][0-9]+[a-z])/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Sony Ericsson' ]); $this->data->device->identifyModel('/SonyE?ricsson ?([^\/\);]+)/iu', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Sony Ericsson', 'model' => function ($model) { if (preg_match('/^([A-Z]) ([0-9]+)$/u', $model, $match)) { $model = $match[1] . $match[2]; } if (preg_match('/^[a-z][0-9]+/u', $model)) { $model[0] = strtoupper($model[0]); } return $model; } ]); $this->data->device->identifyModel('/SHARP[-_\/]([^\/\;]*)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Sharp' ]); $this->data->device->identifyModel('/Spice\s([^\s]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Spice' ]); $this->data->device->identifyModel('/Spice\s?([A-Z][0-9]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Spice' ]); $this->data->device->identifyModel('/Tecno([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Tecno' ]); $this->data->device->identifyModel('/T-smart_([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'T-smart' ]); $this->data->device->identifyModel('/TCL[-_ ]([^\/\;\)]*)/ui', $ua, [ 'manufacturer' => 'TCL' ]); $this->data->device->identifyModel('/Tiphone ([^\/]*)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'TiPhone' ]); $this->data->device->identifyModel('/Toshiba[-\/]([^\/-]*)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Toshiba' ]); $this->data->device->identifyModel('/UTStar(?:com)?-([^\s\.\/;]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'UTStarcom' ]); $this->data->device->identifyModel('/vk-(vk[0-9]+)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'VK Mobile', 'model' => function ($model) { return strtoupper($model); } ]); $this->data->device->identifyModel('/Videocon[-_ \/]([A-Z0-9\.]+)/iu', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Videocon' ]); $this->data->device->identifyModel('/Vodafone(?:[ _-]Chat)?[ _-]?([0-9]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Vodafone' ]); $this->data->device->identifyModel('/Vodafone\/[0-9.]+\/(v[0-9]+)[^\/]*\//u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Vodafone' ]); $this->data->device->identifyModel('/^VSUN([0-9]+[A-Z]?)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Vsun' ]); $this->data->device->identifyModel('/Wynncom[\-\s]([A-Z0-9\s]+\+?)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Wynncom' ]); $this->data->device->identifyModel('/^YUANDA([0-9]+[A-Z]?)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Yuanda' ]); $this->data->device->identifyModel('/^ZEN[_\s]([A-Z0-9\s\+]+)\*?[\s_]?($|\/|-|;|Dorado|MAUI|WAP|R2AE|Q03C)/uiU', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Zen' ]); $this->data->device->identifyModel('/^(?:Ziox[_\s])?Ziox[_\s](ZX?[0-9]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'Ziox' ]); $this->data->device->identifyModel('/ZTE[-_\s]?([^\s\/\(\);,]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'manufacturer' => 'ZTE', 'model' => function ($model) { return preg_match('/[A-Z]+[0-9]+/iu', $model) ? strtoupper($model) : $model; } ]); $this->identifyBasedOnIdentifier(); } /* Japanese models */ private function detectJapaneseMobileModels($ua) { if (isset($this->data->device->manufacturer)) { return; } if ($this->data->os->isFamily('Android')) { return; } /* Sometimes DoCoMo UA strings are (partially) encoded */ if (preg_match('/^DoCoMo/u', $ua)) { $ua = preg_replace_callback( "#\\\x([0-9A-Fa-f]{2})#", function ($m) { return chr(hexdec($m[1])); }, $ua ); } /* First identify it based on id */ $model = null; $manufacturer = null; $carrier = null; $falsepositive = false; $ids = [ 'CA' => 'Casio', 'DL' => 'Dell', 'ER' => 'Ericsson', 'HT' => 'HTC', 'HW' => 'Huawei', 'IA' => 'Inventec', 'JR' => 'JRC', 'KO' => 'Kokusai', 'LC' => 'Longcheer', 'NK' => 'Nokia', 'NM' => 'Nokia', 'KE' => 'KES', 'SA' => 'Sanyo', 'SC' => 'Samsung', 'SS' => 'Samsung', 'SH' => 'Sharp', 'SE' => 'Sony Ericsson', 'SO' => 'Sony', 'ZT' => 'ZTE', 'F' => 'Fujitsu', 'D' => 'Mitsubishi', 'J' => 'JRC', 'K' => 'Kyocera', 'L' => 'LG', 'M' => 'Motorola', 'N' => 'NEC', 'P' => 'Panasonic', 'R' => 'JRC', 'T' => 'Toshiba', 'Z' => 'ZTE', ]; if (preg_match('/(?:^|[\s\/\-\(;])((' . implode('|', array_keys($ids)) . ')[0-9]{3,3}[a-z]+[A-Z]*)/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $carrier = 'DoCoMo'; } if (preg_match('/(?:; |\()((' . implode('|', array_keys($ids)) . ')[0-9]{2,2}[A-Z][0-9]?)[\);]/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $carrier = 'DoCoMo'; } if (preg_match('/DoCoMo\/[0-9].0 ((' . implode('|', array_keys($ids)) . ')[0-9]{2,2}[A-Z][0-9]?)(?:\s?\(|$)/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $carrier = 'DoCoMo'; } if (preg_match('/DoCoMo\/[0-9].0[\/\s](?:MST_v_)?((' . implode('|', array_keys($ids)) . ')[1-9][0-9]{3,3}[A-Z]?)/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $carrier = 'DoCoMo'; } if (preg_match('/[\/\(]([SHW][0-9]{2,2}(' . implode('|', array_keys($ids)) . '))[\/;]/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $carrier = 'EMOBILE'; } if (preg_match('/\) ([SHW][0-9]{2,2}(' . implode('|', array_keys($ids)) . '))$/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $carrier = 'EMOBILE'; } if (preg_match('/[\s\/\-\(;](J-(' . implode('|', array_keys($ids)) . ')[0-9]{2,2})/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $carrier = 'Softbank'; } if (preg_match('/(?:^|; |\/)([0-9]{3,3}(' . implode('|', array_keys($ids)) . '))[eps]?[\/\)]/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $carrier = 'Softbank'; } if (preg_match('/\(([0-9]{3,3}(' . implode('|', array_keys($ids)) . ')[eps]?);SoftBank/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $carrier = 'Softbank'; } if (preg_match('/(?:^|[\s\/\(;])((V|DM|W|WS|WX)[0-9]{2,3}(' . implode('|', array_keys($ids)) . '))/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[3]; switch ($match[2]) { case 'V': $carrier = 'Softbank'; break; case 'DM': $carrier = 'Disney Mobile'; break; case 'W': case 'WS': case 'WX': $carrier = 'Willcom'; break; } } if (preg_match('/(AH-(' . implode('|', array_keys($ids)) . ')[1-9][0-9]{3,3}[A-Z]?)/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $carrier = 'Willcom'; } if (in_array($model, [ '360SE' ])) { $falsepositive = true; } if (!$falsepositive && !empty($model) && !empty($manufacturer)) { $this->data->device->reset([ 'type' => Constants\DeviceType::MOBILE, 'model' => $model, 'carrier' => $carrier ]); if (array_key_exists($manufacturer, $ids)) { $this->data->device->manufacturer = $ids[$manufacturer]; } $this->data->device->identified |= Constants\Id::PATTERN; /* Set flags for MOAP */ switch ($model) { case 'F06B': case 'F07B': case 'F08B': case 'SH07B': $this->data->os->reset([ 'family' => new Family([ 'name' => 'Symbian' ]) ]); $this->data->device->flag = Constants\Flag::MOAPS; break; } return; } /* Then KDDI model number */ $ids = [ 'CA' => 'Casio', 'DE' => 'Denso', 'PT' => 'Pantech', 'SA' => 'Sanyo', 'ST' => 'Sanyo', 'SH' => 'Sharp', 'H' => 'Hitachi', 'K' => 'Kyocera', 'P' => 'Panasonic', 'S' => 'Sony Ericsson', 'T' => 'Toshiba' ]; if (preg_match('/(?:^|KDDI-)(W[0-9]{2,2}(' . implode('|', array_keys($ids)) . '))[;\)\s\/]/u', $ua, $match)) { $model = $match[1]; $manufacturer = $match[2]; $this->data->device->reset([ 'type' => Constants\DeviceType::MOBILE, 'model' => $model, 'carrier' => 'au' ]); if (array_key_exists($manufacturer, $ids)) { $this->data->device->manufacturer = $ids[$manufacturer]; } $this->data->device->identified |= Constants\Id::PATTERN; return; } /* Then identify it based on KDDI id */ $ids = [ 'CA' => 'Casio', 'DN' => 'Denso', 'ER' => 'Ericsson', 'FJ' => 'Fujitsu', 'HI' => 'Hitachi', 'KC' => 'Kyocera', 'MA' => 'Panasonic', 'MI' => 'Mitsubishi', 'PT' => 'Pantech', 'SA' => 'Sanyo', 'ST' => 'Sanyo', 'SY' => 'Sanyo', 'SH' => 'Sharp', 'SN' => 'Sony Ericsson', 'TS' => 'Toshiba' ]; if (preg_match('/(?:^|KDDI-|UP\. ?Browser\/[0-9\.]+-|; )((' . implode('|', array_keys($ids)) . ')(?:[0-9][0-9]|[A-Z][0-9]|[0-9][A-Z]))($|[;\)\s])/ui', $ua, $match)) { $model = strtoupper($match[1]); $manufacturer = strtoupper($match[2]); $falsepositive = false; if (in_array($model, [ 'MAM2', 'MAM3' ])) { $falsepositive = true; } if (!$falsepositive) { $this->data->device->reset([ 'type' => Constants\DeviceType::MOBILE, 'model' => $model, 'carrier' => 'au' ]); if (array_key_exists($manufacturer, $ids)) { $this->data->device->manufacturer = $ids[$manufacturer]; $device = Data\DeviceModels::identify('kddi', $model); if ($device->identified) { $device->identified |= $this->data->device->identified; $device->carrier = 'au'; $this->data->device = $device; } } $this->data->device->identified |= Constants\Id::PATTERN; return; } } /* Finally identify it based on carrier */ $this->data->device->identifyModel('/\(([A-Z]+[0-9]+[A-Z])[^;]*; ?FOMA/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'carrier' => 'DoCoMo' ]); $this->data->device->identifyModel('/\(FOMA ([^;]+)+;/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'carrier' => 'DoCoMo' ]); $this->data->device->identifyModel('/DoCoMo\/[0-9].0[\/\s]([0-9A-Z]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'carrier' => 'DoCoMo' ]); $this->data->device->identifyModel('/NTTDoCoMo ([0-9A-Z]+)/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'carrier' => 'DoCoMo' ]); $this->data->device->identifyModel('/J-PHONE\/[^\/]+\/([^\/_]+)/u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'carrier' => 'Softbank' ]); $this->data->device->identifyModel('/SoftBank\/[^\/]+\/([^\/]+)\//u', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'carrier' => 'Softbank' ]); $this->data->device->identifyModel('/Vodafone\/[0-9.]+\/V([0-9]+[A-Z]+)[^\/]*\//ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'carrier' => 'Softbank' ]); $this->data->device->identifyModel('/(KDDI-[^\s\)\.;]{4,})/ui', $ua, [ 'type' => Constants\DeviceType::MOBILE, 'carrier' => 'au' ]); if (!empty($this->data->device->model)) { $this->identifyBasedOnId($this->data->device->model); } } /* Device models not identified by a prefix */ private function detectGenericMobileLocations($ua) { if ($this->data->device->identified & Constants\Id::PATTERN) { return; } $candidates = []; if (preg_match('/^([a-z0-9\.\_\+\/ ]+)_TD\//iu', $ua, $match)) { array_push($candidates, $match[1]); } if (preg_match('/^([a-z0-9\_]+)/iu', $ua, $match)) { array_push($candidates, $match[1]); } if (preg_match('/[; ]\(?([^\s\)\/;]+)[^\s;]*$/u', $ua, $match)) { array_push($candidates, $match[1]); } if (preg_match('/^([^\/\)]+)/u', $ua, $match)) { array_push($candidates, $match[1]); } if (preg_match('/MobilePhone ([^\/\)]+)/u', $ua, $match)) { array_push($candidates, $match[1]); } $candidates = array_diff($candidates, [ 'Mobile', 'Safari', 'Version', 'GoogleTV', 'WebKit', 'NetFront', 'Microsoft', 'ZuneWP7', 'Firefox', 'UCBrowser', 'IEMobile', 'Touch', 'Fennec', 'Minimo', 'Gecko', 'TizenBrowser', 'Browser', 'sdk', 'Mini', 'Fennec', 'Darwin', 'Puffin', 'Tanggula', 'Edge', 'QHBrowser', 'BonEcho', 'Iceweasel', 'Midori', 'BeOS', 'UBrowser', 'SeaMonkey', 'Model', 'Silk-Accelerated=true', 'Configuration', 'UNTRUSTED', 'OSRE', 'Dolfin', 'Surf', 'Epiphany', 'Konqueror', 'Presto', 'OWB', 'PmWFx', 'Netscape', 'Netscape6', 'Navigator', 'Opera', 'Mozilla', 'BrightSign', 'Motorola', 'UCWEB', 'NativeOperaMini', 'OperaMini', 'SogouMobileBrowser', 'iLunascape', 'Sleipnir', 'MobileSafari', 'MQQBrowser', 'BREW', '?', 'Maxthon', '360%20Browser', 'OPR', 'CFNetwork', 'JUC', 'Skyfire', 'UP.Browser', 'DolphinHDCN', 'NintendoBrowser', 'NCSA', 'NCSA Mosaic', 'NCSA_Mosaic', 'U', 'NetFrontNX', 'QtWebKit', 'HtmlRenderer', 'HbbTV', 'WebAppManager', 'SmartTV', 'UPLUSTVBROWSER', 'LG Browser', 'LG', 'LGSmartTV', 'OBIGO-T10', 'Linux', 'DLNADOC', 'Aplix_SANYO_browser', 'Japanese', 'WebBrowser', 'Freetime', 'OreganMediaBrowser', 'NETRANGEMMH', 'http:', 'bxapi', 'Kodi', 'XBMC', 'KreaTVWebKit', 'MachBlue', 'Espial', 'TouchPad', 'sharp', 'sharp wd browser', 'sharp pda browser', 'browser', 'Palmscape', 'CorePlayer', 'Xiino', 'SONY', 'WorldTALK', 'TOPS', 'Windows', 'Microsoft Pocket Internet Explorer', 'Explorer', 'CE', 'Desktop', 'Maemo Browser', 'Maemo', 'baidubrowser', 'Mercury', 'BREW-Applet', 'ucweb-squid', 'iSurf', '3gpp-gba', 'InfoPath.2', 'UC', 'J2ME', 'IUC', 'AveFront', 'MMP', 'BaiduHD', '360%20Lite', '360', 'AppleWebKit', 'Instagram', 'FBOP', 'Nuanti', 'NuantiMeta', 'Silk', 'VTE', 'DreamKey', 'DreamPassport', 'Aplix_SEGASATURN_browser', 'NWF', 'Bunjalloo', 'libwww', 'Inferno', 'NEXT', 'I', 'Microsoft Internet Explorer', 'MAM3', 'MAM2', '360SE', 'Ziepod', 'Vista', 'XP', 'Links', 'Syllable', 'sun4m', 'sun4c', 'sun4u', 'i86pc', 'X11', 'NaenaraBrowser', 'QuickTime', 'IBM', 'QQBrowser', 'x86_64', 'i686', 'i386', 'Chrome', 'TenFourFox', 'Swing', 'NetFrontBrowserNX', 'Mac_PowerPC', 'NetCast.TV-2012', 'NetCast.TV-2011', 'NetCast.Media-2011', 'PaleMoon', 'Fedora', 'SUSE', 'iCab', 'Googlebot', 'Pixi', 'Pre', 'ELinks', 'developer', 'beta', 'BingPreview', 'IBrowse', '+http:' ]); $candidates = array_unique($candidates); foreach ($candidates as $i => $id) { if (preg_match('/^[0-9\.]+$/u', $id)) { unset($candidates[$i]); continue; } if (preg_match('/^[0-9]+[xX][0-9]+$/u', $id)) { unset($candidates[$i]); continue; } if (preg_match('/^\[?[a-z]{2,2}(\-[a-z]{2,2})?\]?$/ui', $id)) { unset($candidates[$i]); continue; } if (strlen($id) < 4) { unset($candidates[$i]); continue; } } foreach ($candidates as $i => $id) { $this->identifyBasedOnIdUsingOs($id); if ($this->data->device->identified & Constants\Id::MATCH_UA) { return; } } } function identifyBasedOnIdentifier() { if ($this->data->device->identified & Constants\Id::MATCH_UA) { return; } $ids = []; if (!empty($this->data->device->identifier)) { $ids[] = $this->data->device->identifier; } if (!empty($this->data->device->model)) { $ids[] = $this->data->device->model; } foreach ($ids as $i => $id) { $this->identifyBasedOnIdUsingOs($id); if ($this->data->device->identified & Constants\Id::MATCH_UA) { return; } } foreach ($ids as $i => $id) { $this->identifyBasedOnId($id); if ($this->data->device->identified & Constants\Id::MATCH_UA) { return; } } } function identifyBasedOnIdUsingOs($id) { switch ($this->data->os->getFamily()) { case 'Android': $device = Data\DeviceModels::identify('android', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; } break; case 'Brew': $device = Data\DeviceModels::identify('brew', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; } break; case 'Symbian': $device = Data\DeviceModels::identify('symbian', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; } break; case 'Windows': case 'Windows CE': case 'Windows Mobile': $device = Data\DeviceModels::identify('wm', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; if (!$this->data->isOs('Windows Mobile')) { $this->data->os->reset([ 'name' => 'Windows Mobile' ]); } } break; default: $device = Data\DeviceModels::identify('feature', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; } break; } } function identifyBasedOnId($id) { if ($this->data->device->type != 'mobile') { return; } if (!($this->data->device->identified & Constants\Id::MATCH_UA)) { $device = Data\DeviceModels::identify('brew', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; if (!in_array($this->data->os->name, [ 'Brew', 'Brew MP' ])) { $this->data->os->name = 'Brew'; } } } if (!($this->data->device->identified & Constants\Id::MATCH_UA)) { $device = Data\DeviceModels::identify('bada', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; $this->data->os->name = 'Bada'; } } if (!($this->data->device->identified & Constants\Id::MATCH_UA)) { $device = Data\DeviceModels::identify('touchwiz', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; $this->data->os->name = 'Touchwiz'; } } if (!($this->data->device->identified & Constants\Id::MATCH_UA)) { $device = Data\DeviceModels::identify('symbian', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; $this->data->os->reset([ 'family' => new Family([ 'name' => 'Symbian' ]) ]); } } if (!($this->data->device->identified & Constants\Id::MATCH_UA)) { $device = Data\DeviceModels::identify('wm', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; $this->data->os->name = 'Windows Mobile'; } } if (!($this->data->device->identified & Constants\Id::MATCH_UA)) { $device = Data\DeviceModels::identify('feature', $id); if ($device->identified) { $device->identified |= $this->data->device->identified; $this->data->device = $device; } } } }