Mobile.php 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  1. <?php
  2. namespace WhichBrowser\Analyser\Header\Useragent\Device;
  3. use WhichBrowser\Constants;
  4. use WhichBrowser\Data;
  5. use WhichBrowser\Model\Family;
  6. use WhichBrowser\Model\Version;
  7. trait Mobile
  8. {
  9. private function detectMobile($ua)
  10. {
  11. /* Detect the type based on some common markers */
  12. $this->detectGenericMobile($ua);
  13. /* Look for specific manufacturers and models */
  14. $this->detectKin($ua);
  15. $this->detectNokia($ua);
  16. $this->detectSamsung($ua);
  17. /* Try to parse some generic methods to store device information */
  18. $this->detectGenericMobileModels($ua);
  19. $this->detectJapaneseMobileModels($ua);
  20. /* Try to find the model names based on id */
  21. $this->detectGenericMobileLocations($ua);
  22. }
  23. /* Generic markers */
  24. private function detectGenericMobile($ua)
  25. {
  26. if (preg_match('/(MIDP|CLDC|UNTRUSTED\/|3gpp-gba|[Ww][Aa][Pp]2.0|[Ww][Aa][Pp][ _-]?[Bb]rowser)/u', $ua)) {
  27. $this->data->device->type = Constants\DeviceType::MOBILE;
  28. }
  29. }
  30. /* Microsoft KIN */
  31. private function detectKin($ua)
  32. {
  33. if (preg_match('/KIN\.(One|Two) ([0-9.]*)/ui', $ua, $match)) {
  34. $this->data->os->name = 'Kin OS';
  35. $this->data->os->version = new Version([ 'value' => $match[2], 'details' => 2 ]);
  36. switch ($match[1]) {
  37. case 'One':
  38. $this->data->device->manufacturer = 'Microsoft';
  39. $this->data->device->model = 'Kin ONE';
  40. $this->data->device->identified |= Constants\Id::MATCH_UA;
  41. $this->data->device->generic = false;
  42. break;
  43. case 'Two':
  44. $this->data->device->manufacturer = 'Microsoft';
  45. $this->data->device->model = 'Kin TWO';
  46. $this->data->device->identified |= Constants\Id::MATCH_UA;
  47. $this->data->device->generic = false;
  48. break;
  49. }
  50. }
  51. }
  52. /* Nokia */
  53. private function detectNokia($ua)
  54. {
  55. if (isset($this->data->device->manufacturer)) {
  56. return;
  57. }
  58. if (preg_match('/Nokia[- \/]?([^\/\);]+)/ui', $ua, $match)) {
  59. if ($match[1] == 'Browser') {
  60. return;
  61. }
  62. $this->data->device->manufacturer = 'Nokia';
  63. $this->data->device->model = Data\DeviceModels::cleanup($match[1]);
  64. $this->data->device->identifier = $match[0];
  65. $this->data->device->identified |= Constants\Id::PATTERN;
  66. $this->data->device->generic = false;
  67. $this->data->device->type = Constants\DeviceType::MOBILE;
  68. if (!($this->data->device->identified & Constants\Id::MATCH_UA)) {
  69. $device = Data\DeviceModels::identify('asha', $this->data->device->model);
  70. if ($device->identified) {
  71. $device->identified |= $this->data->device->identified;
  72. $this->data->device = $device;
  73. if (!isset($this->data->os->name) || $this->data->os->name != 'Nokia Asha Platform') {
  74. $this->data->os->name = 'Nokia Asha Platform';
  75. $this->data->os->version = new Version([ 'value' => '1.0' ]);
  76. if (preg_match('/java_runtime_version=Nokia_Asha_([0-9_]+)[;\)]/u', $ua, $match)) {
  77. $this->data->os->version = new Version([ 'value' => str_replace('_', '.', $match[1]) ]);
  78. }
  79. }
  80. }
  81. }
  82. if (!($this->data->device->identified & Constants\Id::MATCH_UA)) {
  83. $device = Data\DeviceModels::identify('s40', $this->data->device->model);
  84. if ($device->identified) {
  85. $device->identified |= $this->data->device->identified;
  86. $this->data->device = $device;
  87. if (!isset($this->data->os->name) || $this->data->os->name != 'Series40') {
  88. $this->data->os->name = 'Series40';
  89. $this->data->os->version = null;
  90. }
  91. }
  92. }
  93. if (!($this->data->device->identified & Constants\Id::MATCH_UA)) {
  94. $device = Data\DeviceModels::identify('symbian', $this->data->device->model);
  95. if ($device->identified) {
  96. $device->identified |= $this->data->device->identified;
  97. $this->data->device = $device;
  98. if (!isset($this->data->os->name) || $this->data->os->name != 'Series60') {
  99. $this->data->os->name = 'Series60';
  100. $this->data->os->version = null;
  101. $this->data->os->family = new Family([ 'name' => 'Symbian' ]);
  102. }
  103. }
  104. }
  105. $this->identifyBasedOnIdentifier();
  106. }
  107. }
  108. /* Samsung */
  109. private function detectSamsung($ua)
  110. {
  111. if (isset($this->data->device->manufacturer)) {
  112. return;
  113. }
  114. if (preg_match('/(?:SAMSUNG; )?SAMSUNG ?[-\/]?([^;\/\)_,]+)/ui', $ua, $match)) {
  115. $this->data->device->manufacturer = 'Samsung';
  116. $this->data->device->model = Data\DeviceModels::cleanup($match[1]);
  117. $this->data->device->identifier = $match[0];
  118. $this->data->device->identified |= Constants\Id::PATTERN;
  119. $this->data->device->generic = false;
  120. $this->data->device->type = Constants\DeviceType::MOBILE;
  121. if ($this->data->isOS('Bada')) {
  122. $device = Data\DeviceModels::identify('bada', $this->data->device->model);
  123. if ($device->identified) {
  124. $device->identified |= $this->data->device->identified;
  125. $this->data->device = $device;
  126. }
  127. }
  128. if ($this->data->isOS('Series60')) {
  129. $device = Data\DeviceModels::identify('symbian', $this->data->device->model);
  130. if ($device->identified) {
  131. $device->identified |= $this->data->device->identified;
  132. $this->data->device = $device;
  133. }
  134. }
  135. if (!$this->data->os->isDetected()) {
  136. if (preg_match('/Jasmine\/([0-9.]*)/u', $ua, $match)) {
  137. $version = $match[1];
  138. $device = Data\DeviceModels::identify('touchwiz', $this->data->device->model);
  139. if ($device->identified) {
  140. $device->identified |= $this->data->device->identified;
  141. $this->data->device = $device;
  142. $this->data->os->name = 'Touchwiz';
  143. switch ($version) {
  144. case '0.8':
  145. $this->data->os->version = new Version([ 'value' => '1.0' ]);
  146. break;
  147. case '1.0':
  148. $this->data->os->version = new Version([ 'value' => '2.0', 'alias' => '2.0 or earlier' ]);
  149. break;
  150. }
  151. }
  152. }
  153. if (preg_match('/(?:Dolfin\/([0-9.]*)|Browser\/Dolfin([0-9.]*))/u', $ua, $match)) {
  154. $version = !empty($match[1]) ? $match[1] : $match[2];
  155. $device = Data\DeviceModels::identify('bada', $this->data->device->model);
  156. if ($device->identified) {
  157. $device->identified |= $this->data->device->identified;
  158. $this->data->device = $device;
  159. $this->data->os->name = 'Bada';
  160. switch ($version) {
  161. case '2.0':
  162. $this->data->os->version = new Version([ 'value' => '1.0' ]);
  163. break;
  164. case '2.2':
  165. $this->data->os->version = new Version([ 'value' => '1.2' ]);
  166. break;
  167. }
  168. } else {
  169. $device = Data\DeviceModels::identify('touchwiz', $this->data->device->model);
  170. if ($device->identified) {
  171. $device->identified |= $this->data->device->identified;
  172. $this->data->device = $device;
  173. $this->data->os->name = 'Touchwiz';
  174. switch ($version) {
  175. case '1.0':
  176. $this->data->os->version = new Version([ 'value' => '2.0', 'alias' => '2.0 or earlier' ]);
  177. break;
  178. case '1.5':
  179. $this->data->os->version = new Version([ 'value' => '2.0' ]);
  180. break;
  181. case '2.0':
  182. $this->data->os->version = new Version([ 'value' => '3.0' ]);
  183. break;
  184. }
  185. }
  186. }
  187. }
  188. }
  189. $this->identifyBasedOnIdentifier();
  190. }
  191. }
  192. /* Generic models */
  193. private function detectGenericMobileModels($ua)
  194. {
  195. if ($this->data->device->identified & Constants\Id::PATTERN) {
  196. return;
  197. }
  198. if (isset($this->data->device->manufacturer)) {
  199. return;
  200. }
  201. 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|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|Xiaomi|ZTE|WAP)/ui', $ua)) {
  202. return;
  203. }
  204. $this->data->device->identifyModel('/T-Mobile[_ ]([^\/;]+)/u', $ua, [
  205. 'type' => Constants\DeviceType::MOBILE,
  206. 'manufacturer' => 'T-Mobile'
  207. ]);
  208. $this->data->device->identifyModel('/Danger hiptop ([0-9.]+)/u', $ua, [
  209. 'type' => Constants\DeviceType::MOBILE,
  210. 'manufacturer' => 'Danger',
  211. 'model' => 'Hiptop'
  212. ]);
  213. $this->data->device->identifyModel('/HP(iPAQ[0-9A-Za-z]+)\//u', $ua, [
  214. 'type' => Constants\DeviceType::MOBILE,
  215. 'manufacturer' => 'HP'
  216. ]);
  217. $this->data->device->identifyModel('/Acer[_-]?([^\s\/_]*)/ui', $ua, [
  218. 'type' => Constants\DeviceType::MOBILE,
  219. 'manufacturer' => 'Acer'
  220. ]);
  221. $this->data->device->identifyModel('/Amoi[ -]([^\s\/_]*)/ui', $ua, [
  222. 'type' => Constants\DeviceType::MOBILE,
  223. 'manufacturer' => 'Amoi'
  224. ]);
  225. $this->data->device->identifyModel('/AIRNESS-([^\/]*)/ui', $ua, [
  226. 'type' => Constants\DeviceType::MOBILE,
  227. 'manufacturer' => 'Airness'
  228. ]);
  229. $this->data->device->identifyModel('/ASUS-([^\/]*)/ui', $ua, [
  230. 'type' => Constants\DeviceType::MOBILE,
  231. 'manufacturer' => 'Asus'
  232. ]);
  233. $this->data->device->identifyModel('/BenQ[ -]([^\/]*)/ui', $ua, [
  234. 'type' => Constants\DeviceType::MOBILE,
  235. 'manufacturer' => 'BenQ'
  236. ]);
  237. $this->data->device->identifyModel('/ maui ([a-z0-9]+)/u', $ua, [
  238. 'type' => Constants\DeviceType::MOBILE,
  239. 'manufacturer' => 'BenQ',
  240. 'model' => function ($model) {
  241. return 'Maui ' . strtoupper($model);
  242. }
  243. ]);
  244. $this->data->device->identifyModel('/ALCATEL[_-]([^\/]*)/ui', $ua, [
  245. 'type' => Constants\DeviceType::MOBILE,
  246. 'manufacturer' => 'Alcatel',
  247. 'model' => function ($model) {
  248. if (preg_match('/^TRIBE ([^\s]+)/ui', $model, $match)) {
  249. $model = 'One Touch Tribe ' . $match[1];
  250. } elseif (preg_match('/^ONE TOUCH ([^\s]*)/ui', $model, $match)) {
  251. $model = 'One Touch ' . $match[1];
  252. } elseif (preg_match('/^OT[-\s]*([^\s]*)/ui', $model, $match)) {
  253. $model = 'One Touch ' . $match[1];
  254. }
  255. return $model;
  256. }
  257. ]);
  258. $this->data->device->identifyModel('/Bird[ _\-\.]([^\/]*)/ui', $ua, [
  259. 'type' => Constants\DeviceType::MOBILE,
  260. 'manufacturer' => 'Bird'
  261. ]);
  262. $this->data->device->identifyModel('/(?:YL-|YuLong-)?COOLPAD([^\s]+)/ui', $ua, [
  263. 'type' => Constants\DeviceType::MOBILE,
  264. 'manufacturer' => 'Coolpad'
  265. ]);
  266. $this->data->device->identifyModel('/CELKON\.([^\s]+)/ui', $ua, [
  267. 'type' => Constants\DeviceType::MOBILE,
  268. 'manufacturer' => 'Celkon'
  269. ]);
  270. $this->data->device->identifyModel('/Coship ([^\s]+)/ui', $ua, [
  271. 'type' => Constants\DeviceType::MOBILE,
  272. 'manufacturer' => 'Coship'
  273. ]);
  274. $this->data->device->identifyModel('/Cricket-([^\s]+)/ui', $ua, [
  275. 'type' => Constants\DeviceType::MOBILE,
  276. 'manufacturer' => 'Cricket'
  277. ]);
  278. $this->data->device->identifyModel('/DESAY[ _]([^\s]+)/ui', $ua, [
  279. 'type' => Constants\DeviceType::MOBILE,
  280. 'manufacturer' => 'DESAY'
  281. ]);
  282. $this->data->device->identifyModel('/Diamond_([^\s]+)/ui', $ua, [
  283. 'type' => Constants\DeviceType::MOBILE,
  284. 'manufacturer' => 'Diamond'
  285. ]);
  286. $this->data->device->identifyModel('/dopod[-_]?([^\s]+)/ui', $ua, [
  287. 'type' => Constants\DeviceType::MOBILE,
  288. 'manufacturer' => 'Dopod'
  289. ]);
  290. $this->data->device->identifyModel('/^Ericsson([^\/]+)/ui', $ua, [
  291. 'type' => Constants\DeviceType::MOBILE,
  292. 'manufacturer' => 'Ericsson'
  293. ]);
  294. $this->data->device->identifyModel('/^(R[0-9]{3,3}) [0-9\.]+ WAP/ui', $ua, [
  295. 'type' => Constants\DeviceType::MOBILE,
  296. 'manufacturer' => 'Ericsson'
  297. ]);
  298. $this->data->device->identifyModel('/FLY_]?([^\s\/]+)/ui', $ua, [
  299. 'type' => Constants\DeviceType::MOBILE,
  300. 'manufacturer' => 'Fly'
  301. ]);
  302. $this->data->device->identifyModel('/GIONEE[-_ ]([^\s\/;]+)/ui', $ua, [
  303. 'type' => Constants\DeviceType::MOBILE,
  304. 'manufacturer' => 'Gionee'
  305. ]);
  306. $this->data->device->identifyModel('/GIONEE([A-Z0-9]+)/ui', $ua, [
  307. 'type' => Constants\DeviceType::MOBILE,
  308. 'manufacturer' => 'Gionee'
  309. ]);
  310. $this->data->device->identifyModel('/HIKe_([^\s]+)/ui', $ua, [
  311. 'type' => Constants\DeviceType::MOBILE,
  312. 'manufacturer' => 'HIKe'
  313. ]);
  314. $this->data->device->identifyModel('/HAIER-([A-Z][0-9]+)/ui', $ua, [
  315. 'type' => Constants\DeviceType::MOBILE,
  316. 'manufacturer' => 'Haier'
  317. ]);
  318. $this->data->device->identifyModel('/Hisense[ -](?:HS-)?([^\s]+)/ui', $ua, [
  319. 'type' => Constants\DeviceType::MOBILE,
  320. 'manufacturer' => 'Hisense'
  321. ]);
  322. $this->data->device->identifyModel('/HS-([^\s]+)/ui', $ua, [
  323. 'type' => Constants\DeviceType::MOBILE,
  324. 'manufacturer' => 'Hisense'
  325. ]);
  326. $this->data->device->identifyModel('/HTC[\s_-]?([^\s\/\(\);][^\/\(\);]+)/ui', $ua, [
  327. 'type' => Constants\DeviceType::MOBILE,
  328. 'manufacturer' => 'HTC'
  329. ]);
  330. $this->data->device->identifyModel('/(?:HTC_)?([A-Z0-9_]+_T[0-9]{4,4})/ui', $ua, [
  331. 'type' => Constants\DeviceType::MOBILE,
  332. 'manufacturer' => 'HTC'
  333. ]);
  334. $this->data->device->identifyModel('/HUAWEI[\s_-]?([^\/\)\()]+)/ui', $ua, [
  335. 'type' => Constants\DeviceType::MOBILE,
  336. 'manufacturer' => 'Huawei'
  337. ]);
  338. $this->data->device->identifyModel('/Karbonn ([a-z0-9]+(?: ?Star| ?Plus|\+)?)/ui', $ua, [
  339. 'type' => Constants\DeviceType::MOBILE,
  340. 'manufacturer' => 'Karbonn'
  341. ]);
  342. $this->data->device->identifyModel('/KWC-([^\s\/]+)/ui', $ua, [
  343. 'type' => Constants\DeviceType::MOBILE,
  344. 'manufacturer' => 'Kyocera'
  345. ]);
  346. $this->data->device->identifyModel('/KONKA[-_]?([^\s]+)/ui', $ua, [
  347. 'type' => Constants\DeviceType::MOBILE,
  348. 'manufacturer' => 'Konka'
  349. ]);
  350. $this->data->device->identifyModel('/TIANYU-KTOUCH\/([^\/]+)/ui', $ua, [
  351. 'type' => Constants\DeviceType::MOBILE,
  352. 'manufacturer' => 'K-Touch'
  353. ]);
  354. $this->data->device->identifyModel('/K-Touch_?([^\/]*)/ui', $ua, [
  355. 'type' => Constants\DeviceType::MOBILE,
  356. 'manufacturer' => 'K-Touch'
  357. ]);
  358. $this->data->device->identifyModel('/Lenovo[_-]?([^\/]*)/ui', $ua, [
  359. 'type' => Constants\DeviceType::MOBILE,
  360. 'manufacturer' => 'Lenovo'
  361. ]);
  362. $this->data->device->identifyModel('/Lephone_([^\/]*)/ui', $ua, [
  363. 'type' => Constants\DeviceType::MOBILE,
  364. 'manufacturer' => 'Lephone'
  365. ]);
  366. $this->data->device->identifyModel('/LGE?([A-Z]{2,2}[0-9]+)/ui', $ua, [
  367. 'type' => Constants\DeviceType::MOBILE,
  368. 'manufacturer' => 'LG'
  369. ]);
  370. $this->data->device->identifyModel('/LGE?(?:\/|-|_)([^\s\)\-\[\/]+)/ui', $ua, [
  371. 'type' => Constants\DeviceType::MOBILE,
  372. 'manufacturer' => 'LG'
  373. ]);
  374. $this->data->device->identifyModel('/LGE? ?([A-Z]*[0-9]+[A-Z]?)/u', $ua, [
  375. 'type' => Constants\DeviceType::MOBILE,
  376. 'manufacturer' => 'LG'
  377. ]);
  378. $this->data->device->identifyModel('/Micromax([^\)]+)/ui', $ua, [
  379. 'type' => Constants\DeviceType::MOBILE,
  380. 'manufacturer' => 'Micromax'
  381. ]);
  382. $this->data->device->identifyModel('/^MOTO-?([^\/_]+)/u', $ua, [
  383. 'type' => Constants\DeviceType::MOBILE,
  384. 'manufacturer' => 'Motorola'
  385. ]);
  386. $this->data->device->identifyModel('/MOT-([^\/_\.]+)/ui', $ua, [
  387. 'type' => Constants\DeviceType::MOBILE,
  388. 'manufacturer' => 'Motorola'
  389. ]);
  390. $this->data->device->identifyModel('/Motorola-([^\s]+)/ui', $ua, [
  391. 'type' => Constants\DeviceType::MOBILE,
  392. 'manufacturer' => 'Motorola',
  393. 'model' => function ($model) {
  394. return strtoupper($model);
  395. }
  396. ]);
  397. $this->data->device->identifyModel('/Motorola[_ ]([^\/_;]+)/ui', $ua, [
  398. 'type' => Constants\DeviceType::MOBILE,
  399. 'manufacturer' => 'Motorola'
  400. ]);
  401. $this->data->device->identifyModel('/Moto([^\/\s_;r][^\/\s_;]*)/u', $ua, [
  402. 'type' => Constants\DeviceType::MOBILE,
  403. 'manufacturer' => 'Motorola'
  404. ]);
  405. $this->data->device->identifyModel('/Nexian([^\/_]+)/ui', $ua, [
  406. 'type' => Constants\DeviceType::MOBILE,
  407. 'manufacturer' => 'Nexian'
  408. ]);
  409. $this->data->device->identifyModel('/NEC-([^\/_]+)/ui', $ua, [
  410. 'type' => Constants\DeviceType::MOBILE,
  411. 'manufacturer' => 'NEC'
  412. ]);
  413. $this->data->device->identifyModel('/NGM_([^\/_]+)/ui', $ua, [
  414. 'type' => Constants\DeviceType::MOBILE,
  415. 'manufacturer' => 'NGM'
  416. ]);
  417. $this->data->device->identifyModel('/OPPO_([^\/_]+)/ui', $ua, [
  418. 'type' => Constants\DeviceType::MOBILE,
  419. 'manufacturer' => 'Oppo'
  420. ]);
  421. $this->data->device->identifyModel('/Panasonic-([^\/_]+)/ui', $ua, [
  422. 'type' => Constants\DeviceType::MOBILE,
  423. 'manufacturer' => 'Panasonic'
  424. ]);
  425. $this->data->device->identifyModel('/Pantech[-_]?([^\/_]+)/ui', $ua, [
  426. 'type' => Constants\DeviceType::MOBILE,
  427. 'manufacturer' => 'Pantech'
  428. ]);
  429. $this->data->device->identifyModel('/Philips ?([A-Z]?[0-9@]+[a-z]?)/u', $ua, [
  430. 'type' => Constants\DeviceType::MOBILE,
  431. 'manufacturer' => 'Philips'
  432. ]);
  433. $this->data->device->identifyModel('/PHILIPS-([a-zA-Z0-9@]+(?: [0-9]+)?)/u', $ua, [
  434. 'type' => Constants\DeviceType::MOBILE,
  435. 'manufacturer' => 'Philips',
  436. 'model' => function ($model) {
  437. if (preg_match('/Az@lis([0-9]{3,3})/ui', $model, $match)) {
  438. return 'Az@lis ' . $match[1];
  439. }
  440. if (preg_match('/Fisio ?([0-9]{3,3})/ui', $model, $match)) {
  441. return 'Fisio ' . $match[1];
  442. }
  443. return $model;
  444. }
  445. ]);
  446. $this->data->device->identifyModel('/SAGEM-([A-Z0-9\-]+)/ui', $ua, [
  447. 'type' => Constants\DeviceType::MOBILE,
  448. 'manufacturer' => 'Sagem'
  449. ]);
  450. $this->data->device->identifyModel('/Sanyo-([A-Z0-9]+)/ui', $ua, [
  451. 'type' => Constants\DeviceType::MOBILE,
  452. 'manufacturer' => 'Sanyo'
  453. ]);
  454. $this->data->device->identifyModel('/sam-([A-Z][0-9]+)/ui', $ua, [
  455. 'type' => Constants\DeviceType::MOBILE,
  456. 'manufacturer' => 'Samsung'
  457. ]);
  458. $this->data->device->identifyModel('/SEC-(SGH[A-Z][0-9]+)/u', $ua, [
  459. 'type' => Constants\DeviceType::MOBILE,
  460. 'manufacturer' => 'Samsung',
  461. 'model' => function ($model) {
  462. return str_replace('SGH', 'SGH-', $model);
  463. }
  464. ]);
  465. $this->data->device->identifyModel('/((?:SGH|SCH)-[A-Z][0-9]+)/u', $ua, [
  466. 'type' => Constants\DeviceType::MOBILE,
  467. 'manufacturer' => 'Samsung'
  468. ]);
  469. $this->data->device->identifyModel('/(GT-[A-Z][0-9]+[A-Z]?)/ui', $ua, [
  470. 'type' => Constants\DeviceType::MOBILE,
  471. 'manufacturer' => 'Samsung'
  472. ]);
  473. $this->data->device->identifyModel('/(?:Siemens |SIE-)([A-Z]+[0-9]+)/ui', $ua, [
  474. 'type' => Constants\DeviceType::MOBILE,
  475. 'manufacturer' => 'Siemens'
  476. ]);
  477. $this->data->device->identifyModel('/SIE-([0-9]{4,4}|[A-Z]{4,4})/ui', $ua, [
  478. 'type' => Constants\DeviceType::MOBILE,
  479. 'manufacturer' => 'Siemens'
  480. ]);
  481. $this->data->device->identifyModel('/Sony ([A-Z0-9\-]+)/u', $ua, [
  482. 'type' => Constants\DeviceType::MOBILE,
  483. 'manufacturer' => 'Sony'
  484. ]);
  485. $this->data->device->identifyModel('/SE([A-Z][0-9]+[a-z])/u', $ua, [
  486. 'type' => Constants\DeviceType::MOBILE,
  487. 'manufacturer' => 'Sony Ericsson'
  488. ]);
  489. $this->data->device->identifyModel('/sony-ericsson ([A-Z][0-9]+[a-z])/u', $ua, [
  490. 'type' => Constants\DeviceType::MOBILE,
  491. 'manufacturer' => 'Sony Ericsson'
  492. ]);
  493. $this->data->device->identifyModel('/SonyE?ricsson ?([^\/\);]+)/iu', $ua, [
  494. 'type' => Constants\DeviceType::MOBILE,
  495. 'manufacturer' => 'Sony Ericsson',
  496. 'model' => function ($model) {
  497. if (preg_match('/^([A-Z]) ([0-9]+)$/u', $model, $match)) {
  498. $model = $match[1] . $match[2];
  499. }
  500. if (preg_match('/^[a-z][0-9]+/u', $model)) {
  501. $model[0] = strtoupper($model[0]);
  502. }
  503. return $model;
  504. }
  505. ]);
  506. $this->data->device->identifyModel('/SHARP[-_\/]([^\/\;]*)/u', $ua, [
  507. 'type' => Constants\DeviceType::MOBILE,
  508. 'manufacturer' => 'Sharp'
  509. ]);
  510. $this->data->device->identifyModel('/Spice\s([^\s]+)/ui', $ua, [
  511. 'type' => Constants\DeviceType::MOBILE,
  512. 'manufacturer' => 'Spice'
  513. ]);
  514. $this->data->device->identifyModel('/Spice\s?([A-Z][0-9]+)/ui', $ua, [
  515. 'type' => Constants\DeviceType::MOBILE,
  516. 'manufacturer' => 'Spice'
  517. ]);
  518. $this->data->device->identifyModel('/Tecno([^\/]*)/ui', $ua, [
  519. 'type' => Constants\DeviceType::MOBILE,
  520. 'manufacturer' => 'Tecno'
  521. ]);
  522. $this->data->device->identifyModel('/T-smart_([^\/]*)/ui', $ua, [
  523. 'type' => Constants\DeviceType::MOBILE,
  524. 'manufacturer' => 'T-smart'
  525. ]);
  526. $this->data->device->identifyModel('/TCL[-_ ]([^\/\;\)]*)/ui', $ua, [
  527. 'manufacturer' => 'TCL'
  528. ]);
  529. $this->data->device->identifyModel('/Tiphone ([^\/]*)/ui', $ua, [
  530. 'type' => Constants\DeviceType::MOBILE,
  531. 'manufacturer' => 'TiPhone'
  532. ]);
  533. $this->data->device->identifyModel('/Toshiba[-\/]([^\/-]*)/u', $ua, [
  534. 'type' => Constants\DeviceType::MOBILE,
  535. 'manufacturer' => 'Toshiba'
  536. ]);
  537. $this->data->device->identifyModel('/UTStar(?:com)?-([^\s\.\/;]+)/ui', $ua, [
  538. 'type' => Constants\DeviceType::MOBILE,
  539. 'manufacturer' => 'UTStarcom'
  540. ]);
  541. $this->data->device->identifyModel('/vk-(vk[0-9]+)/u', $ua, [
  542. 'type' => Constants\DeviceType::MOBILE,
  543. 'manufacturer' => 'VK Mobile',
  544. 'model' => function ($model) {
  545. return strtoupper($model);
  546. }
  547. ]);
  548. $this->data->device->identifyModel('/Videocon[-_ \/]([A-Z0-9\.]+)/iu', $ua, [
  549. 'type' => Constants\DeviceType::MOBILE,
  550. 'manufacturer' => 'Videocon'
  551. ]);
  552. $this->data->device->identifyModel('/Vodafone(?:[ _-]Chat)?[ _-]?([0-9]+)/u', $ua, [
  553. 'type' => Constants\DeviceType::MOBILE,
  554. 'manufacturer' => 'Vodafone'
  555. ]);
  556. $this->data->device->identifyModel('/Vodafone\/[0-9.]+\/(v[0-9]+)[^\/]*\//u', $ua, [
  557. 'type' => Constants\DeviceType::MOBILE,
  558. 'manufacturer' => 'Vodafone'
  559. ]);
  560. $this->data->device->identifyModel('/Xiaomi[_]?([^\s]+)/ui', $ua, [
  561. 'type' => Constants\DeviceType::MOBILE,
  562. 'manufacturer' => 'Xiaomi'
  563. ]);
  564. $this->data->device->identifyModel('/ZTE[-_\s]?([^\s\/\(\);,]+)/ui', $ua, [
  565. 'type' => Constants\DeviceType::MOBILE,
  566. 'manufacturer' => 'ZTE',
  567. 'model' => function ($model) {
  568. return preg_match('/[A-Z]+[0-9]+/iu', $model) ? strtoupper($model) : $model;
  569. }
  570. ]);
  571. $this->identifyBasedOnIdentifier();
  572. }
  573. /* Japanese models */
  574. private function detectJapaneseMobileModels($ua)
  575. {
  576. if (isset($this->data->device->manufacturer)) {
  577. return;
  578. }
  579. if ($this->data->os->isFamily('Android')) {
  580. return;
  581. }
  582. /* Sometimes DoCoMo UA strings are (partially) encoded */
  583. if (preg_match('/^DoCoMo/u', $ua)) {
  584. $ua = preg_replace_callback(
  585. "#\\\x([0-9A-Fa-f]{2})#",
  586. function ($m) {
  587. return chr(hexdec($m[1]));
  588. },
  589. $ua
  590. );
  591. }
  592. /* First identify it based on id */
  593. $model = null;
  594. $manufacturer = null;
  595. $carrier = null;
  596. $falsepositive = false;
  597. $ids = [
  598. 'CA' => 'Casio',
  599. 'DL' => 'Dell',
  600. 'ER' => 'Ericsson',
  601. 'HT' => 'HTC',
  602. 'HW' => 'Huawei',
  603. 'IA' => 'Inventec',
  604. 'JR' => 'JRC',
  605. 'KO' => 'Kokusai',
  606. 'LC' => 'Longcheer',
  607. 'NK' => 'Nokia',
  608. 'NM' => 'Nokia',
  609. 'KE' => 'KES',
  610. 'SA' => 'Sanyo',
  611. 'SC' => 'Samsung',
  612. 'SS' => 'Samsung',
  613. 'SH' => 'Sharp',
  614. 'SE' => 'Sony Ericsson',
  615. 'SO' => 'Sony',
  616. 'ZT' => 'ZTE',
  617. 'F' => 'Fujitsu',
  618. 'D' => 'Mitsubishi',
  619. 'J' => 'JRC',
  620. 'K' => 'Kyocera',
  621. 'L' => 'LG',
  622. 'M' => 'Motorola',
  623. 'N' => 'NEC',
  624. 'P' => 'Panasonic',
  625. 'R' => 'JRC',
  626. 'T' => 'Toshiba',
  627. 'Z' => 'ZTE',
  628. ];
  629. if (preg_match('/(?:^|[\s\/\-\(;])((' . implode('|', array_keys($ids)) . ')[0-9]{3,3}[a-z]+[A-Z]*)/u', $ua, $match)) {
  630. $model = $match[1];
  631. $manufacturer = $match[2];
  632. $carrier = 'DoCoMo';
  633. }
  634. if (preg_match('/(?:; |\()((' . implode('|', array_keys($ids)) . ')[0-9]{2,2}[A-Z][0-9]?)[\);]/u', $ua, $match)) {
  635. $model = $match[1];
  636. $manufacturer = $match[2];
  637. $carrier = 'DoCoMo';
  638. }
  639. if (preg_match('/DoCoMo\/[0-9].0 ((' . implode('|', array_keys($ids)) . ')[0-9]{2,2}[A-Z][0-9]?)(?:\s?\(|$)/u', $ua, $match)) {
  640. $model = $match[1];
  641. $manufacturer = $match[2];
  642. $carrier = 'DoCoMo';
  643. }
  644. 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)) {
  645. $model = $match[1];
  646. $manufacturer = $match[2];
  647. $carrier = 'DoCoMo';
  648. }
  649. if (preg_match('/[\/\(]([SHW][0-9]{2,2}(' . implode('|', array_keys($ids)) . '))[\/;]/u', $ua, $match)) {
  650. $model = $match[1];
  651. $manufacturer = $match[2];
  652. $carrier = 'EMOBILE';
  653. }
  654. if (preg_match('/\) ([SHW][0-9]{2,2}(' . implode('|', array_keys($ids)) . '))$/u', $ua, $match)) {
  655. $model = $match[1];
  656. $manufacturer = $match[2];
  657. $carrier = 'EMOBILE';
  658. }
  659. if (preg_match('/[\s\/\-\(;](J-(' . implode('|', array_keys($ids)) . ')[0-9]{2,2})/u', $ua, $match)) {
  660. $model = $match[1];
  661. $manufacturer = $match[2];
  662. $carrier = 'Softbank';
  663. }
  664. if (preg_match('/(?:^|; |\/)([0-9]{3,3}(' . implode('|', array_keys($ids)) . '))[eps]?[\/\)]/u', $ua, $match)) {
  665. $model = $match[1];
  666. $manufacturer = $match[2];
  667. $carrier = 'Softbank';
  668. }
  669. if (preg_match('/\(([0-9]{3,3}(' . implode('|', array_keys($ids)) . ')[eps]?);SoftBank/u', $ua, $match)) {
  670. $model = $match[1];
  671. $manufacturer = $match[2];
  672. $carrier = 'Softbank';
  673. }
  674. if (preg_match('/(?:^|[\s\/\(;])((V|DM|W|WS|WX)[0-9]{2,3}(' . implode('|', array_keys($ids)) . '))/u', $ua, $match)) {
  675. $model = $match[1];
  676. $manufacturer = $match[3];
  677. switch ($match[2]) {
  678. case 'V':
  679. $carrier = 'Softbank';
  680. break;
  681. case 'DM':
  682. $carrier = 'Disney Mobile';
  683. break;
  684. case 'W':
  685. case 'WS':
  686. case 'WX':
  687. $carrier = 'Willcom';
  688. break;
  689. }
  690. }
  691. if (preg_match('/(AH-(' . implode('|', array_keys($ids)) . ')[1-9][0-9]{3,3}[A-Z]?)/u', $ua, $match)) {
  692. $model = $match[1];
  693. $manufacturer = $match[2];
  694. $carrier = 'Willcom';
  695. }
  696. if (in_array($model, [ '360SE' ])) {
  697. $falsepositive = true;
  698. }
  699. if (!$falsepositive && !empty($model) && !empty($manufacturer)) {
  700. $this->data->device->reset([
  701. 'type' => Constants\DeviceType::MOBILE,
  702. 'model' => $model,
  703. 'carrier' => $carrier
  704. ]);
  705. if (array_key_exists($manufacturer, $ids)) {
  706. $this->data->device->manufacturer = $ids[$manufacturer];
  707. }
  708. $this->data->device->identified |= Constants\Id::PATTERN;
  709. /* Set flags for MOAP */
  710. switch ($model) {
  711. case 'F06B':
  712. case 'F07B':
  713. case 'F08B':
  714. case 'SH07B':
  715. $this->data->os->reset([ 'family' => new Family([ 'name' => 'Symbian' ]) ]);
  716. $this->data->device->flag = Constants\Flag::MOAPS;
  717. break;
  718. }
  719. return;
  720. }
  721. /* Then KDDI model number */
  722. $ids = [
  723. 'CA' => 'Casio',
  724. 'DE' => 'Denso',
  725. 'PT' => 'Pantech',
  726. 'SA' => 'Sanyo',
  727. 'ST' => 'Sanyo',
  728. 'SH' => 'Sharp',
  729. 'H' => 'Hitachi',
  730. 'K' => 'Kyocera',
  731. 'P' => 'Panasonic',
  732. 'S' => 'Sony Ericsson',
  733. 'T' => 'Toshiba'
  734. ];
  735. if (preg_match('/(?:^|KDDI-)(W[0-9]{2,2}(' . implode('|', array_keys($ids)) . '))[;\)\s\/]/u', $ua, $match)) {
  736. $model = $match[1];
  737. $manufacturer = $match[2];
  738. $this->data->device->reset([
  739. 'type' => Constants\DeviceType::MOBILE,
  740. 'model' => $model,
  741. 'carrier' => 'au'
  742. ]);
  743. if (array_key_exists($manufacturer, $ids)) {
  744. $this->data->device->manufacturer = $ids[$manufacturer];
  745. }
  746. $this->data->device->identified |= Constants\Id::PATTERN;
  747. return;
  748. }
  749. /* Then identify it based on KDDI id */
  750. $ids = [
  751. 'CA' => 'Casio',
  752. 'DN' => 'Denso',
  753. 'ER' => 'Ericsson',
  754. 'FJ' => 'Fujitsu',
  755. 'HI' => 'Hitachi',
  756. 'KC' => 'Kyocera',
  757. 'MA' => 'Panasonic',
  758. 'MI' => 'Mitsubishi',
  759. 'PT' => 'Pantech',
  760. 'SA' => 'Sanyo',
  761. 'ST' => 'Sanyo',
  762. 'SY' => 'Sanyo',
  763. 'SH' => 'Sharp',
  764. 'SN' => 'Sony Ericsson',
  765. 'TS' => 'Toshiba'
  766. ];
  767. 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)) {
  768. $model = strtoupper($match[1]);
  769. $manufacturer = strtoupper($match[2]);
  770. $falsepositive = false;
  771. if (in_array($model, [ 'MAM2', 'MAM3' ])) {
  772. $falsepositive = true;
  773. }
  774. if (!$falsepositive) {
  775. $this->data->device->reset([
  776. 'type' => Constants\DeviceType::MOBILE,
  777. 'model' => $model,
  778. 'carrier' => 'au'
  779. ]);
  780. if (array_key_exists($manufacturer, $ids)) {
  781. $this->data->device->manufacturer = $ids[$manufacturer];
  782. $device = Data\DeviceModels::identify('kddi', $model);
  783. if ($device->identified) {
  784. $device->identified |= $this->data->device->identified;
  785. $device->carrier = 'au';
  786. $this->data->device = $device;
  787. }
  788. }
  789. $this->data->device->identified |= Constants\Id::PATTERN;
  790. return;
  791. }
  792. }
  793. /* Finally identify it based on carrier */
  794. $this->data->device->identifyModel('/\(([A-Z]+[0-9]+[A-Z])[^;]*; ?FOMA/ui', $ua, [
  795. 'type' => Constants\DeviceType::MOBILE,
  796. 'carrier' => 'DoCoMo'
  797. ]);
  798. $this->data->device->identifyModel('/\(FOMA ([^;]+)+;/u', $ua, [
  799. 'type' => Constants\DeviceType::MOBILE,
  800. 'carrier' => 'DoCoMo'
  801. ]);
  802. $this->data->device->identifyModel('/DoCoMo\/[0-9].0[\/\s]([0-9A-Z]+)/ui', $ua, [
  803. 'type' => Constants\DeviceType::MOBILE,
  804. 'carrier' => 'DoCoMo'
  805. ]);
  806. $this->data->device->identifyModel('/NTTDoCoMo ([0-9A-Z]+)/ui', $ua, [
  807. 'type' => Constants\DeviceType::MOBILE,
  808. 'carrier' => 'DoCoMo'
  809. ]);
  810. $this->data->device->identifyModel('/J-PHONE\/[^\/]+\/([^\/_]+)/u', $ua, [
  811. 'type' => Constants\DeviceType::MOBILE,
  812. 'carrier' => 'Softbank'
  813. ]);
  814. $this->data->device->identifyModel('/SoftBank\/[^\/]+\/([^\/]+)\//u', $ua, [
  815. 'type' => Constants\DeviceType::MOBILE,
  816. 'carrier' => 'Softbank'
  817. ]);
  818. $this->data->device->identifyModel('/Vodafone\/[0-9.]+\/V([0-9]+[A-Z]+)[^\/]*\//ui', $ua, [
  819. 'type' => Constants\DeviceType::MOBILE,
  820. 'carrier' => 'Softbank'
  821. ]);
  822. $this->data->device->identifyModel('/(KDDI-[^\s\)\.;]{4,})/ui', $ua, [
  823. 'type' => Constants\DeviceType::MOBILE,
  824. 'carrier' => 'au'
  825. ]);
  826. if (!empty($this->data->device->model)) {
  827. $this->identifyBasedOnId($this->data->device->model);
  828. }
  829. }
  830. /* Device models not identified by a prefix */
  831. private function detectGenericMobileLocations($ua)
  832. {
  833. if ($this->data->device->identified & Constants\Id::PATTERN) {
  834. return;
  835. }
  836. $candidates = [];
  837. if (preg_match('/^([a-z0-9\.\_\+\/ ]+)_TD\//iu', $ua, $match)) {
  838. array_push($candidates, $match[1]);
  839. }
  840. if (preg_match('/^([a-z0-9\_]+)/iu', $ua, $match)) {
  841. array_push($candidates, $match[1]);
  842. }
  843. if (preg_match('/[; ]\(?([^\s\)\/;]+)[^\s;]*$/u', $ua, $match)) {
  844. array_push($candidates, $match[1]);
  845. }
  846. if (preg_match('/^([^\/\)]+)/u', $ua, $match)) {
  847. array_push($candidates, $match[1]);
  848. }
  849. if (preg_match('/MobilePhone ([^\/\)]+)/u', $ua, $match)) {
  850. array_push($candidates, $match[1]);
  851. }
  852. $candidates = array_diff($candidates, [
  853. 'Mobile', 'Safari', 'Version', 'GoogleTV', 'WebKit', 'NetFront',
  854. 'Microsoft', 'ZuneWP7', 'Firefox', 'UCBrowser', 'IEMobile', 'Touch',
  855. 'Fennec', 'Minimo', 'Gecko', 'TizenBrowser', 'Browser', 'sdk',
  856. 'Mini', 'Fennec', 'Darwin', 'Puffin', 'Tanggula', 'Edge',
  857. 'QHBrowser', 'BonEcho', 'Iceweasel', 'Midori', 'BeOS', 'UBrowser',
  858. 'SeaMonkey', 'Model', 'Silk-Accelerated=true', 'Configuration',
  859. 'UNTRUSTED', 'OSRE', 'Dolfin', 'Surf', 'Epiphany', 'Konqueror',
  860. 'Presto', 'OWB', 'PmWFx', 'Netscape', 'Netscape6', 'Navigator',
  861. 'Opera', 'Mozilla', 'BrightSign', 'Motorola', 'UCWEB',
  862. 'NativeOperaMini', 'OperaMini', 'SogouMobileBrowser', 'iLunascape',
  863. 'Sleipnir', 'MobileSafari', 'MQQBrowser', 'BREW', '?',
  864. 'Maxthon', '360%20Browser', 'OPR', 'CFNetwork', 'JUC', 'Skyfire',
  865. 'UP.Browser', 'DolphinHDCN', 'NintendoBrowser', 'NCSA',
  866. 'NCSA Mosaic', 'NCSA_Mosaic', 'U', 'NetFrontNX', 'QtWebKit',
  867. 'HtmlRenderer', 'HbbTV', 'WebAppManager', 'SmartTV', 'UPLUSTVBROWSER',
  868. 'LG Browser', 'LG', 'LGSmartTV', 'OBIGO-T10', 'Linux', 'DLNADOC',
  869. 'Aplix_SANYO_browser', 'Japanese', 'WebBrowser', 'Freetime',
  870. 'OreganMediaBrowser', 'NETRANGEMMH', 'http:', 'bxapi', 'Kodi',
  871. 'XBMC', 'KreaTVWebKit', 'MachBlue', 'Espial', 'TouchPad',
  872. 'sharp', 'sharp wd browser', 'sharp pda browser', 'browser',
  873. 'Palmscape', 'CorePlayer', 'Xiino', 'SONY', 'WorldTALK', 'TOPS',
  874. 'Windows', 'Microsoft Pocket Internet Explorer', 'Explorer',
  875. 'CE', 'Desktop', 'Maemo Browser', 'Maemo', 'baidubrowser',
  876. 'Mercury', 'BREW-Applet', 'ucweb-squid', 'iSurf', '3gpp-gba',
  877. 'InfoPath.2', 'UC', 'J2ME', 'IUC', 'AveFront', 'MMP', 'BaiduHD',
  878. '360%20Lite', '360', 'AppleWebKit', 'Instagram', 'FBOP',
  879. 'Nuanti', 'NuantiMeta', 'Silk', 'VTE', 'DreamKey', 'DreamPassport',
  880. 'Aplix_SEGASATURN_browser', 'NWF', 'Bunjalloo', 'libwww',
  881. 'Inferno', 'NEXT', 'I', 'Microsoft Internet Explorer', 'MAM3',
  882. 'MAM2', '360SE', 'Ziepod', 'Vista', 'XP', 'Links', 'Syllable',
  883. 'sun4m', 'sun4c', 'sun4u', 'i86pc', 'X11', 'NaenaraBrowser',
  884. 'QuickTime', 'IBM', 'QQBrowser', 'x86_64', 'i686', 'i386', 'Chrome',
  885. 'TenFourFox', 'Swing', 'NetFrontBrowserNX', 'Mac_PowerPC',
  886. 'NetCast.TV-2012', 'NetCast.TV-2011', 'NetCast.Media-2011',
  887. 'PaleMoon', 'Fedora', 'SUSE', 'iCab', 'Googlebot', 'Pixi',
  888. 'Pre', 'ELinks', 'developer', 'beta', 'BingPreview', 'IBrowse', '+http:'
  889. ]);
  890. $candidates = array_unique($candidates);
  891. foreach ($candidates as $i => $id) {
  892. if (preg_match('/^[0-9\.]+$/u', $id)) {
  893. unset($candidates[$i]);
  894. continue;
  895. }
  896. if (preg_match('/^[0-9]+[xX][0-9]+$/u', $id)) {
  897. unset($candidates[$i]);
  898. continue;
  899. }
  900. if (preg_match('/^\[?[a-z]{2,2}(\-[a-z]{2,2})?\]?$/ui', $id)) {
  901. unset($candidates[$i]);
  902. continue;
  903. }
  904. if (strlen($id) < 4) {
  905. unset($candidates[$i]);
  906. continue;
  907. }
  908. }
  909. foreach ($candidates as $i => $id) {
  910. $this->identifyBasedOnIdUsingOs($id);
  911. if ($this->data->device->identified & Constants\Id::MATCH_UA) {
  912. return;
  913. }
  914. }
  915. }
  916. function identifyBasedOnIdentifier()
  917. {
  918. if ($this->data->device->identified & Constants\Id::MATCH_UA) {
  919. return;
  920. }
  921. $ids = [];
  922. if (!empty($this->data->device->identifier)) {
  923. $ids[] = $this->data->device->identifier;
  924. }
  925. if (!empty($this->data->device->model)) {
  926. $ids[] = $this->data->device->model;
  927. }
  928. foreach ($ids as $i => $id) {
  929. $this->identifyBasedOnIdUsingOs($id);
  930. if ($this->data->device->identified & Constants\Id::MATCH_UA) {
  931. return;
  932. }
  933. }
  934. foreach ($ids as $i => $id) {
  935. $this->identifyBasedOnId($id);
  936. if ($this->data->device->identified & Constants\Id::MATCH_UA) {
  937. return;
  938. }
  939. }
  940. }
  941. function identifyBasedOnIdUsingOs($id)
  942. {
  943. switch ($this->data->os->getFamily()) {
  944. case 'Android':
  945. $device = Data\DeviceModels::identify('android', $id);
  946. if ($device->identified) {
  947. $device->identified |= $this->data->device->identified;
  948. $this->data->device = $device;
  949. }
  950. break;
  951. case 'Brew':
  952. $device = Data\DeviceModels::identify('brew', $id);
  953. if ($device->identified) {
  954. $device->identified |= $this->data->device->identified;
  955. $this->data->device = $device;
  956. }
  957. break;
  958. case 'Symbian':
  959. $device = Data\DeviceModels::identify('symbian', $id);
  960. if ($device->identified) {
  961. $device->identified |= $this->data->device->identified;
  962. $this->data->device = $device;
  963. }
  964. break;
  965. case 'Windows':
  966. case 'Windows CE':
  967. case 'Windows Mobile':
  968. $device = Data\DeviceModels::identify('wm', $id);
  969. if ($device->identified) {
  970. $device->identified |= $this->data->device->identified;
  971. $this->data->device = $device;
  972. if (!$this->data->isOs('Windows Mobile')) {
  973. $this->data->os->reset([
  974. 'name' => 'Windows Mobile'
  975. ]);
  976. }
  977. }
  978. break;
  979. default:
  980. $device = Data\DeviceModels::identify('feature', $id);
  981. if ($device->identified) {
  982. $device->identified |= $this->data->device->identified;
  983. $this->data->device = $device;
  984. }
  985. break;
  986. }
  987. }
  988. function identifyBasedOnId($id)
  989. {
  990. if ($this->data->device->type != 'mobile') {
  991. return;
  992. }
  993. if (!($this->data->device->identified & Constants\Id::MATCH_UA)) {
  994. $device = Data\DeviceModels::identify('brew', $id);
  995. if ($device->identified) {
  996. $device->identified |= $this->data->device->identified;
  997. $this->data->device = $device;
  998. if (!in_array($this->data->os->name, [ 'Brew', 'Brew MP' ])) {
  999. $this->data->os->name = 'Brew';
  1000. }
  1001. }
  1002. }
  1003. if (!($this->data->device->identified & Constants\Id::MATCH_UA)) {
  1004. $device = Data\DeviceModels::identify('bada', $id);
  1005. if ($device->identified) {
  1006. $device->identified |= $this->data->device->identified;
  1007. $this->data->device = $device;
  1008. $this->data->os->name = 'Bada';
  1009. }
  1010. }
  1011. if (!($this->data->device->identified & Constants\Id::MATCH_UA)) {
  1012. $device = Data\DeviceModels::identify('touchwiz', $id);
  1013. if ($device->identified) {
  1014. $device->identified |= $this->data->device->identified;
  1015. $this->data->device = $device;
  1016. $this->data->os->name = 'Touchwiz';
  1017. }
  1018. }
  1019. if (!($this->data->device->identified & Constants\Id::MATCH_UA)) {
  1020. $device = Data\DeviceModels::identify('symbian', $id);
  1021. if ($device->identified) {
  1022. $device->identified |= $this->data->device->identified;
  1023. $this->data->device = $device;
  1024. $this->data->os->reset([
  1025. 'family' => new Family([ 'name' => 'Symbian' ])
  1026. ]);
  1027. }
  1028. }
  1029. if (!($this->data->device->identified & Constants\Id::MATCH_UA)) {
  1030. $device = Data\DeviceModels::identify('wm', $id);
  1031. if ($device->identified) {
  1032. $device->identified |= $this->data->device->identified;
  1033. $this->data->device = $device;
  1034. $this->data->os->name = 'Windows Mobile';
  1035. }
  1036. }
  1037. if (!($this->data->device->identified & Constants\Id::MATCH_UA)) {
  1038. $device = Data\DeviceModels::identify('feature', $id);
  1039. if ($device->identified) {
  1040. $device->identified |= $this->data->device->identified;
  1041. $this->data->device = $device;
  1042. }
  1043. }
  1044. }
  1045. }