device_detector 1.0.0 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +58 -4
  3. data/README.md +57 -21
  4. data/lib/device_detector/bot.rb +2 -2
  5. data/lib/device_detector/browser.rb +691 -0
  6. data/lib/device_detector/client.rb +11 -2
  7. data/lib/device_detector/client_hint.rb +249 -0
  8. data/lib/device_detector/device.rb +1954 -23
  9. data/lib/device_detector/memory_cache.rb +26 -19
  10. data/lib/device_detector/metadata_extractor.rb +7 -8
  11. data/lib/device_detector/model_extractor.rb +3 -3
  12. data/lib/device_detector/name_extractor.rb +2 -2
  13. data/lib/device_detector/os.rb +289 -112
  14. data/lib/device_detector/parser.rb +49 -13
  15. data/lib/device_detector/vendor_fragment.rb +25 -0
  16. data/lib/device_detector/version.rb +3 -1
  17. data/lib/device_detector/version_extractor.rb +29 -2
  18. data/lib/device_detector.rb +192 -44
  19. data/regexes/bots.yml +3399 -91
  20. data/regexes/client/browser_engine.yml +28 -4
  21. data/regexes/client/browsers.yml +2697 -408
  22. data/regexes/client/feed_readers.yml +60 -22
  23. data/regexes/client/hints/apps.yml +150 -0
  24. data/regexes/client/hints/browsers.yml +292 -0
  25. data/regexes/client/libraries.yml +598 -4
  26. data/regexes/client/mediaplayers.yml +110 -5
  27. data/regexes/client/mobile_apps.yml +2451 -14
  28. data/regexes/client/pim.yml +128 -3
  29. data/regexes/device/cameras.yml +6 -6
  30. data/regexes/device/car_browsers.yml +39 -3
  31. data/regexes/device/consoles.yml +40 -6
  32. data/regexes/device/mobiles.yml +38844 -2907
  33. data/regexes/device/notebooks.yml +127 -0
  34. data/regexes/device/portable_media_player.yml +75 -12
  35. data/regexes/device/shell_tv.yml +145 -0
  36. data/regexes/device/televisions.yml +981 -40
  37. data/regexes/oss.yml +1560 -311
  38. data/regexes/vendorfragments.yml +6 -2
  39. metadata +31 -105
  40. data/.gitignore +0 -14
  41. data/.travis.yml +0 -18
  42. data/Gemfile +0 -8
  43. data/Rakefile +0 -79
  44. data/device_detector.gemspec +0 -26
  45. data/spec/device_detector/bot_fixtures_spec.rb +0 -30
  46. data/spec/device_detector/client_fixtures_spec.rb +0 -31
  47. data/spec/device_detector/concrete_user_agent_spec.rb +0 -136
  48. data/spec/device_detector/detector_fixtures_spec.rb +0 -60
  49. data/spec/device_detector/device_fixtures_spec.rb +0 -36
  50. data/spec/device_detector/device_spec.rb +0 -151
  51. data/spec/device_detector/memory_cache_spec.rb +0 -116
  52. data/spec/device_detector/model_extractor_spec.rb +0 -63
  53. data/spec/device_detector/os_fixtures_spec.rb +0 -26
  54. data/spec/device_detector/version_extractor_spec.rb +0 -80
  55. data/spec/device_detector_spec.rb +0 -198
  56. data/spec/fixtures/client/browser.yml +0 -1313
  57. data/spec/fixtures/client/feed_reader.yml +0 -187
  58. data/spec/fixtures/client/library.yml +0 -84
  59. data/spec/fixtures/client/mediaplayer.yml +0 -168
  60. data/spec/fixtures/client/mobile_app.yml +0 -30
  61. data/spec/fixtures/client/pim.yml +0 -96
  62. data/spec/fixtures/detector/bots.yml +0 -2418
  63. data/spec/fixtures/detector/camera.yml +0 -115
  64. data/spec/fixtures/detector/car_browser.yml +0 -20
  65. data/spec/fixtures/detector/console.yml +0 -267
  66. data/spec/fixtures/detector/desktop.yml +0 -4828
  67. data/spec/fixtures/detector/feature_phone.yml +0 -782
  68. data/spec/fixtures/detector/feed_reader.yml +0 -486
  69. data/spec/fixtures/detector/mediaplayer.yml +0 -179
  70. data/spec/fixtures/detector/mobile_apps.yml +0 -149
  71. data/spec/fixtures/detector/phablet.yml +0 -2140
  72. data/spec/fixtures/detector/portable_media_player.yml +0 -153
  73. data/spec/fixtures/detector/smart_display.yml +0 -58
  74. data/spec/fixtures/detector/smartphone-1.yml +0 -9469
  75. data/spec/fixtures/detector/smartphone-2.yml +0 -9414
  76. data/spec/fixtures/detector/smartphone-3.yml +0 -9396
  77. data/spec/fixtures/detector/smartphone-4.yml +0 -5742
  78. data/spec/fixtures/detector/smartphone.yml +0 -9411
  79. data/spec/fixtures/detector/tablet-1.yml +0 -9495
  80. data/spec/fixtures/detector/tablet-2.yml +0 -248
  81. data/spec/fixtures/detector/tablet.yml +0 -9484
  82. data/spec/fixtures/detector/tv.yml +0 -2582
  83. data/spec/fixtures/detector/unknown.yml +0 -3196
  84. data/spec/fixtures/device/camera.yml +0 -18
  85. data/spec/fixtures/device/car_browser.yml +0 -6
  86. data/spec/fixtures/device/console.yml +0 -78
  87. data/spec/fixtures/parser/oss.yml +0 -800
  88. data/spec/fixtures/parser/vendorfragments.yml +0 -162
  89. data/spec/spec_helper.rb +0 -9
@@ -1,20 +1,1898 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class DeviceDetector
2
4
  class Device < Parser
3
-
4
5
  # order is relevant for testing with fixtures
6
+ # https://github.com/matomo-org/device-detector/blob/75d88bbefb0182f9207c9f48dc39b1bc8c7cc43f/Parser/Device/AbstractDeviceParser.php#L59-L74
5
7
  DEVICE_NAMES = [
6
- 'desktop',
7
- 'smartphone',
8
- 'tablet',
9
- 'feature phone',
10
- 'console',
11
- 'tv',
12
- 'car browser',
13
- 'smart display',
14
- 'camera',
15
- 'portable media player',
16
- 'phablet'
17
- ]
8
+ 'desktop',
9
+ 'smartphone',
10
+ 'tablet',
11
+ 'feature phone',
12
+ 'console',
13
+ 'tv',
14
+ 'car browser',
15
+ 'smart display',
16
+ 'camera',
17
+ 'portable media player',
18
+ 'phablet',
19
+ 'smart speaker',
20
+ 'wearable',
21
+ 'peripheral'
22
+ ].freeze
23
+
24
+ # https://github.com/matomo-org/device-detector/blob/75d88bbefb0182f9207c9f48dc39b1bc8c7cc43f/Parser/Device/AbstractDeviceParser.php#L83-L1951
25
+ DEVICE_BRANDS = {
26
+ '5E' => '2E',
27
+ '5IV' => '5IVE',
28
+ '2F' => 'F2 Mobile',
29
+ '3Q' => '3Q',
30
+ 'J7' => '7 Mobile',
31
+ '2Q' => '3GNET',
32
+ '4G' => '4Good',
33
+ '27' => '3GO',
34
+ '04' => '4ife',
35
+ '36' => '360',
36
+ '88' => '8848',
37
+ '10M' => '10moons',
38
+ '41' => 'A1',
39
+ 'AK1' => 'A&K',
40
+ '00' => 'Accent',
41
+ 'ACC' => 'Accesstyle',
42
+ 'AE' => 'Ace',
43
+ 'AC' => 'Acer',
44
+ 'ACL' => 'Aceline',
45
+ '3K' => 'Acteck',
46
+ 'ACT' => 'actiMirror',
47
+ 'A9' => 'Advan',
48
+ 'AD' => 'Advance',
49
+ 'ADV' => 'Advantage Air',
50
+ '76' => 'Adronix',
51
+ 'AF' => 'AfriOne',
52
+ 'FY' => 'AFFIX',
53
+ 'A3' => 'AGM',
54
+ 'AEE' => 'AEEZO',
55
+ 'J0' => 'AG Mobile',
56
+ 'AJI' => 'Ajib',
57
+ 'AZ' => 'Ainol',
58
+ 'AIR' => 'Airis',
59
+ 'AI' => 'Airness',
60
+ 'ARP' => 'Airpha',
61
+ 'AT' => 'Airties',
62
+ '7U' => 'Airtel',
63
+ 'AIT' => 'AirTouch',
64
+ 'U0' => 'AIRON',
65
+ '0A' => 'AIS',
66
+ 'AW' => 'Aiwa',
67
+ '85' => 'Aiuto',
68
+ 'U7' => 'AIDATA',
69
+ 'AK' => 'Akai',
70
+ 'Q3' => 'AKIRA',
71
+ '1A' => 'Alba',
72
+ 'AL' => 'Alcatel',
73
+ 'AL0' => 'Alienware',
74
+ '20' => 'Alcor',
75
+ 'XY' => 'Alps',
76
+ 'XYA' => 'XY Auto',
77
+ 'AAU' => 'AAUW',
78
+ '7L' => 'ALDI NORD',
79
+ '6L' => 'ALDI SÜD',
80
+ '3L' => 'Alfawise',
81
+ '4A' => 'Aligator',
82
+ 'AA' => 'AllCall',
83
+ '3A' => 'AllDocube',
84
+ 'A2' => 'Allview',
85
+ 'ALI' => 'ALLINmobile',
86
+ 'A7' => 'Allwinner',
87
+ 'A1' => 'Altech UEC',
88
+ '66' => 'Altice',
89
+ 'ALM' => 'Altimo',
90
+ 'A5' => 'altron',
91
+ 'ALT' => 'Altus',
92
+ 'KN' => 'Amazon',
93
+ 'AMZ' => 'Amazon Basics',
94
+ 'AMA' => 'AMA',
95
+ 'AG' => 'AMGOO',
96
+ '9A' => 'Amigoo',
97
+ 'AO' => 'Amoi',
98
+ '3J' => 'Amino',
99
+ '54' => 'AMCV',
100
+ '60' => 'Andowl',
101
+ 'ANX' => 'ANXONIT',
102
+ 'ANC' => 'ANBERNIC',
103
+ '6J' => 'Angelcare',
104
+ 'ANG' => 'AngelTech',
105
+ '7A' => 'Anry',
106
+ 'A0' => 'ANS',
107
+ '74' => 'Anker',
108
+ '3N' => 'Aoson',
109
+ 'O8' => 'AOC',
110
+ 'J2' => 'AOYODKG',
111
+ '55' => 'AOpen',
112
+ 'RW' => 'Aoro',
113
+ '9Y' => 'Aocos',
114
+ 'AOW' => 'Aocwei',
115
+ 'AP' => 'Apple',
116
+ 'ARC' => 'Arçelik',
117
+ 'AR' => 'Archos',
118
+ 'AB' => 'Arian Space',
119
+ 'ARI' => 'Arival',
120
+ 'A6' => 'Ark',
121
+ '5A' => 'ArmPhone',
122
+ 'AN' => 'Arnova',
123
+ 'AS' => 'ARRIS',
124
+ 'AQ' => 'Aspera',
125
+ 'HJ' => 'Aquarius',
126
+ '40' => 'Artel',
127
+ '21' => 'Artizlee',
128
+ '59' => 'ArtLine',
129
+ '8A' => 'Asano',
130
+ '90' => 'Asanzo',
131
+ '1U' => 'Astro',
132
+ 'A4' => 'Ask',
133
+ 'A8' => 'Assistant',
134
+ 'ASS' => 'ASSE',
135
+ 'AU' => 'Asus',
136
+ '6A' => 'AT&T',
137
+ 'ATH' => 'Athesi',
138
+ 'ATE' => 'Atlantic Electrics',
139
+ '5Q' => 'Atmaca Elektronik',
140
+ 'YH' => 'ATMAN',
141
+ '2A' => 'Atom',
142
+ 'ATO' => 'ATOL',
143
+ 'Z2' => 'Atvio',
144
+ 'ATI' => 'Attila',
145
+ 'AX' => 'Audiovox',
146
+ 'AJ' => 'AURIS',
147
+ 'YZ' => 'Autan',
148
+ 'AUP' => 'AUPO',
149
+ 'ZA' => 'Avenzo',
150
+ 'AH' => 'AVH',
151
+ 'AV' => 'Avvio',
152
+ 'AVA' => 'Avaya',
153
+ 'AXE' => 'AXEN',
154
+ 'AY' => 'Axxion',
155
+ 'AXX' => 'AXXA',
156
+ 'AYA' => 'AYA',
157
+ 'YR' => 'AYYA',
158
+ 'XA' => 'Axioo',
159
+ 'AM' => 'Azumi Mobile',
160
+ 'AZE' => 'Azeyou',
161
+ 'WW' => 'Awow',
162
+ 'AWO' => 'AWOX',
163
+ 'XU' => 'AUX',
164
+ 'BAC' => 'Backcell',
165
+ 'BFF' => 'BAFF',
166
+ 'BO' => 'BangOlufsen',
167
+ 'BN' => 'Barnes & Noble',
168
+ 'BAR' => 'BARTEC',
169
+ 'BAS' => 'BASE',
170
+ 'BAU' => 'BAUHN',
171
+ 'BB' => 'BBK',
172
+ '0B' => 'BB Mobile',
173
+ 'B6' => 'BDF',
174
+ 'QD' => 'BDQ',
175
+ '8Z' => 'BDsharing',
176
+ 'BEF' => 'Beafon',
177
+ 'BE' => 'Becker',
178
+ 'B5' => 'Beeline',
179
+ 'B0' => 'Beelink',
180
+ 'BL' => 'Beetel',
181
+ 'BEK' => 'Beko',
182
+ '2X' => 'Benco',
183
+ 'BQ' => 'BenQ',
184
+ 'BS' => 'BenQ-Siemens',
185
+ '4Y' => 'Benzo',
186
+ 'XJ' => 'Benesse',
187
+ 'BEN' => 'BenWee',
188
+ 'YB' => 'Beista',
189
+ 'BY' => 'BS Mobile',
190
+ 'BZ' => 'Bezkam',
191
+ '9B' => 'Bellphone',
192
+ '63' => 'Beyond',
193
+ 'BG' => 'BGH',
194
+ '6B' => 'Bigben',
195
+ 'B8' => 'BIHEE',
196
+ '1B' => 'Billion',
197
+ 'BA' => 'BilimLand',
198
+ 'BIL' => 'Billow',
199
+ 'BH' => 'BioRugged',
200
+ 'BI' => 'Bird',
201
+ 'BT' => 'Bitel',
202
+ 'B7' => 'Bitmore',
203
+ 'ZB' => 'Bittium',
204
+ 'BK' => 'Bkav',
205
+ '5B' => 'Black Bear',
206
+ 'BLK' => 'Black Box',
207
+ 'BF' => 'Black Fox',
208
+ 'BPC' => 'Blackpcs',
209
+ 'B2' => 'Blackview',
210
+ '2Y' => 'b2m',
211
+ 'BP' => 'Blaupunkt',
212
+ 'BU' => 'Blu',
213
+ 'BUS' => 'BluSlate',
214
+ 'BUZ' => 'BuzzTV',
215
+ 'B3' => 'Bluboo',
216
+ '2B' => 'Bluedot',
217
+ 'BD' => 'Bluegood',
218
+ 'LB' => 'Bluewave',
219
+ 'J8' => 'Bluebird',
220
+ 'BSS' => 'BlueSky',
221
+ '7B' => 'Blloc',
222
+ 'UB' => 'Bleck',
223
+ 'Q2' => 'Blow',
224
+ 'BLI' => 'BLISS',
225
+ 'BM' => 'Bmobile',
226
+ 'Y5' => 'BMAX',
227
+ 'BMX' => 'BMXC',
228
+ 'B9' => 'Bobarry',
229
+ 'B4' => 'bogo',
230
+ 'BOL' => 'Bolva',
231
+ 'BW' => 'Boway',
232
+ 'BOO' => 'Boost',
233
+ 'BOK' => 'Bookeen',
234
+ 'BOT' => 'Botech',
235
+ 'BX' => 'bq',
236
+ '8B' => 'Brandt',
237
+ 'BRA' => 'BrandCode',
238
+ 'BV' => 'Bravis',
239
+ 'BRV' => 'BRAVE',
240
+ 'BRG' => 'Brigmton',
241
+ 'BR' => 'Brondi',
242
+ 'XF' => 'BROR',
243
+ 'BJ' => 'BrightSign',
244
+ 'B1' => 'Bush',
245
+ '4Q' => 'Bundy',
246
+ 'Y8' => 'Bubblegum',
247
+ 'BMW' => 'BMW',
248
+ 'C9' => 'CAGI',
249
+ 'CAD' => 'CADENA',
250
+ 'CT' => 'Capitel',
251
+ 'G3' => 'CG Mobile',
252
+ '37' => 'CGV',
253
+ 'CP' => 'Captiva',
254
+ 'CF' => 'Carrefour',
255
+ 'CA1' => 'Carbon Mobile',
256
+ 'CS' => 'Casio',
257
+ 'R4' => 'Casper',
258
+ 'CA' => 'Cat',
259
+ 'BC' => 'Camfone',
260
+ 'CJ' => 'Cavion',
261
+ 'CAN' => 'Canal+',
262
+ '4D' => 'Canal Digital',
263
+ 'CNG' => 'Canguro',
264
+ 'CNT' => 'CCIT',
265
+ 'CEC' => 'Cecotec',
266
+ 'CEP' => 'CEPTER',
267
+ 'CEI' => 'Ceibal',
268
+ '02' => 'Cell-C',
269
+ 'CEL' => 'Cellacom',
270
+ '34' => 'CellAllure',
271
+ '7C' => 'Celcus',
272
+ 'CE' => 'Celkon',
273
+ 'CG' => 'Cellution',
274
+ '62' => 'Centric',
275
+ 'CEN' => 'CENTEK',
276
+ 'C2' => 'Changhong',
277
+ 'CHA' => 'Chainway',
278
+ 'CHG' => 'ChiliGreen',
279
+ 'CH' => 'Cherry Mobile',
280
+ 'C3' => 'China Mobile',
281
+ 'U9' => 'China Telecom',
282
+ 'CI' => 'Chico Mobile',
283
+ 'CIA' => 'C Idea',
284
+ 'CIP' => 'CipherLab',
285
+ 'CIT' => 'Citycall',
286
+ '1C' => 'Chuwi',
287
+ 'L8' => 'Clarmin',
288
+ '25' => 'Claresta',
289
+ 'CLA' => 'CLAYTON',
290
+ 'CLT' => 'Clovertek',
291
+ '1J' => 'Cloud',
292
+ 'CD' => 'Cloudfone',
293
+ '6C' => 'Cloudpad',
294
+ 'C0' => 'Clout',
295
+ 'CN' => 'CnM',
296
+ 'CY' => 'Coby Kyros',
297
+ 'XC' => 'Cobalt',
298
+ 'C6' => 'Comio',
299
+ 'CL' => 'Compal',
300
+ 'CQ' => 'Compaq',
301
+ 'C7' => 'ComTrade Tesla',
302
+ '7Z' => 'COMPUMAX',
303
+ 'C8' => 'Concord',
304
+ 'CC' => 'ConCorde',
305
+ 'C5' => 'Condor',
306
+ 'C5M' => 'C5 Mobile',
307
+ '4C' => 'Conquest',
308
+ '3C' => 'Contixo',
309
+ '8C' => 'Connex',
310
+ '53' => 'Connectce',
311
+ 'CON' => 'Conceptum',
312
+ 'CED' => 'Continental Edison',
313
+ '9C' => 'Colors',
314
+ 'CO' => 'Coolpad',
315
+ 'COO' => 'Coopers',
316
+ 'CDE' => 'COOD-E',
317
+ '4R' => 'CORN',
318
+ '1O' => 'Cosmote',
319
+ 'CW' => 'Cowon',
320
+ '75' => 'Covia',
321
+ 'QG' => 'COYOTE',
322
+ 'CKK' => 'CKK Mobile',
323
+ 'YW' => 'ClearPHONE',
324
+ '33' => 'Clementoni',
325
+ 'CR' => 'CreNova',
326
+ 'CX' => 'Crescent',
327
+ 'CK' => 'Cricket',
328
+ 'CM' => 'Crius Mea',
329
+ '0C' => 'Crony',
330
+ 'C1' => 'Crosscall',
331
+ '4W' => 'Crown',
332
+ 'CTR' => 'Ctroniq',
333
+ 'CU' => 'Cube',
334
+ 'CB' => 'CUBOT',
335
+ 'CUI' => 'Cuiud',
336
+ 'CV' => 'CVTE',
337
+ 'CWO' => 'Cwowdefu',
338
+ 'C4' => 'Cyrus',
339
+ 'D5' => 'Daewoo',
340
+ 'DA' => 'Danew',
341
+ 'DAN' => 'Dany',
342
+ 'DA1' => 'DangcapHD',
343
+ 'DAR' => 'Daria',
344
+ 'DT' => 'Datang',
345
+ 'D7' => 'Datawind',
346
+ '7D' => 'Datamini',
347
+ '6D' => 'Datalogic',
348
+ 'D1' => 'Datsun',
349
+ 'DZ' => 'Dazen',
350
+ 'DAS' => 'DASS',
351
+ 'DB' => 'Dbtel',
352
+ 'DBP' => 'DbPhone',
353
+ 'DCO' => 'Dcode',
354
+ 'DL' => 'Dell',
355
+ 'DL0' => 'DL',
356
+ 'DE' => 'Denver',
357
+ 'DS' => 'Desay',
358
+ 'DSD' => 'DSDevices',
359
+ 'DSI' => 'DSIC',
360
+ 'DW' => 'DeWalt',
361
+ 'DX' => 'DEXP',
362
+ 'DEY' => 'DEYI',
363
+ 'DEN' => 'Denali',
364
+ 'DEA' => 'DEALDIG',
365
+ '8D' => 'DF',
366
+ 'DGT' => 'DGTEC',
367
+ 'DG' => 'Dialog',
368
+ 'DIA' => 'DIALN',
369
+ 'DI' => 'Dicam',
370
+ 'D4' => 'Digi',
371
+ 'D3' => 'Digicel',
372
+ 'DDG' => 'Digidragon',
373
+ 'DH' => 'Digihome',
374
+ 'DD' => 'Digiland',
375
+ 'DIJ' => 'DIJITSU',
376
+ 'DIG' => 'Digit4G',
377
+ 'DIC' => 'DIGICOM',
378
+ 'Q0' => 'DIGIFORS',
379
+ 'DIK' => 'DIKOM',
380
+ 'DQ' => 'DISH',
381
+ 'DIS' => 'Disney',
382
+ '9D' => 'Ditecma',
383
+ 'D2' => 'Digma',
384
+ '1D' => 'Diva',
385
+ 'DIV' => 'DiverMax',
386
+ 'D6' => 'Divisat',
387
+ 'DIO' => 'DIORA',
388
+ 'X6' => 'DIXON',
389
+ 'DIM' => 'DIMO',
390
+ '5D' => 'DING DING',
391
+ 'DIN' => 'Dinax',
392
+ 'DNA' => 'Dinalink',
393
+ 'DM' => 'DMM',
394
+ 'DN' => 'DNS',
395
+ 'DC' => 'DoCoMo',
396
+ 'DF' => 'Doffler',
397
+ 'D9' => 'Dolamee',
398
+ 'DO' => 'Doogee',
399
+ 'D0' => 'Doopro',
400
+ 'DV' => 'Doov',
401
+ 'DOM' => 'Dom.ru',
402
+ 'DP' => 'Dopod',
403
+ 'DPA' => 'DPA',
404
+ 'JQ' => 'Doppio',
405
+ 'DR' => 'Doro',
406
+ 'ZD' => 'DORLAND',
407
+ 'DRO' => 'Droidlogic',
408
+ 'D8' => 'Droxio',
409
+ 'DJ' => 'Dragon Touch',
410
+ 'DRA' => 'DRAGON',
411
+ 'DY' => 'Dreamgate',
412
+ 'DRE' => 'DreamTab',
413
+ 'DR1' => 'DreamStar',
414
+ 'DTA' => 'Dtac',
415
+ 'DU' => 'Dune HD',
416
+ 'UD' => 'DUNNS Mobile',
417
+ 'DUU' => 'Duubee',
418
+ 'DUR' => 'Durabook',
419
+ 'DYO' => 'Dyon',
420
+ 'DTE' => 'D-Tech',
421
+ 'DLI' => 'D-Link',
422
+ 'ENO' => 'eNOVA',
423
+ 'IN2' => 'iNOVA',
424
+ 'IN3' => 'inovo',
425
+ 'INH' => 'Inhon',
426
+ 'EB' => 'E-Boda',
427
+ 'EJ' => 'Engel',
428
+ 'ENA' => 'ENACOM',
429
+ 'ENI' => 'ENIE',
430
+ '2E' => 'E-Ceros',
431
+ 'E8' => 'E-tel',
432
+ 'EAS' => 'EAS Electric',
433
+ 'EP' => 'Easypix',
434
+ 'EQ' => 'Eagle',
435
+ 'EGS' => 'EagleSoar',
436
+ 'EA' => 'EBEST',
437
+ 'YC' => 'EBEN',
438
+ 'E4' => 'Echo Mobiles',
439
+ 'EQ1' => 'Equator',
440
+ 'ES' => 'ECS',
441
+ '35' => 'ECON',
442
+ 'ECC' => 'ECOO',
443
+ 'ZZ' => 'ecom',
444
+ 'EDE' => 'Edenwood',
445
+ 'E6' => 'EE',
446
+ 'GW' => 'EGL',
447
+ 'EFT' => 'EFT',
448
+ 'EK' => 'EKO',
449
+ 'EY' => 'Einstein',
450
+ 'EM' => 'Eks Mobility',
451
+ 'UE' => 'Ematic',
452
+ 'EMR' => 'Emporia',
453
+ '4K' => 'EKT',
454
+ 'EKI' => 'EKINOX',
455
+ '7E' => 'ELARI',
456
+ '03' => 'Electroneum',
457
+ 'Z8' => 'ELECTRONIA',
458
+ 'EL1' => 'Elecson',
459
+ 'ELK' => 'Elektroland',
460
+ 'L0' => 'Element',
461
+ 'EG' => 'Elenberg',
462
+ 'EL' => 'Elephone',
463
+ 'JE' => 'Elekta',
464
+ 'ELE' => 'Elevate',
465
+ '4E' => 'Eltex',
466
+ 'ELM' => 'Elong Mobile',
467
+ 'ED' => 'Energizer',
468
+ 'E1' => 'Energy Sistem',
469
+ '3E' => 'Enot',
470
+ 'ENT' => 'Entity',
471
+ 'ENV' => 'Envizen',
472
+ '8E' => 'Epik One',
473
+ 'EPK' => 'Epic',
474
+ 'XP' => 'Epson',
475
+ 'EPH' => 'Ephone',
476
+ 'E7' => 'Ergo',
477
+ 'EC' => 'Ericsson',
478
+ '05' => 'Erisson',
479
+ 'ER' => 'Ericy',
480
+ 'EE' => 'Essential',
481
+ 'E2' => 'Essentielb',
482
+ '6E' => 'eSTAR',
483
+ 'ETO' => 'ETOE',
484
+ 'EN' => 'Eton',
485
+ 'ET' => 'eTouch',
486
+ '1E' => 'Etuline',
487
+ 'EU' => 'Eurostar',
488
+ '4J' => 'Eurocase',
489
+ 'E9' => 'Evercoss',
490
+ 'EV' => 'Evertek',
491
+ 'EVE' => 'Everest',
492
+ 'EV1' => 'Everex',
493
+ 'E3' => 'Evolio',
494
+ 'EO' => 'Evolveo',
495
+ '0Q' => 'Evoo',
496
+ '5U' => 'EVPAD',
497
+ 'E0' => 'EvroMedia',
498
+ 'XE' => 'ExMobile',
499
+ '4Z' => 'Exmart',
500
+ 'EH' => 'EXO',
501
+ 'EX' => 'Explay',
502
+ 'EXP' => 'Express LUCK',
503
+ 'E5' => 'Extrem',
504
+ 'EXL' => 'ExtraLink',
505
+ 'EF' => 'EXCEED',
506
+ 'QE' => 'EWIS',
507
+ 'EI' => 'Ezio',
508
+ 'EZ' => 'Ezze',
509
+ 'UF' => 'EYU',
510
+ 'EYE' => 'Eyemoo',
511
+ 'UE1' => 'UE',
512
+ '5F' => 'F150',
513
+ 'FPS' => 'F+',
514
+ 'F6' => 'Facebook',
515
+ 'FAC' => 'Facetel',
516
+ 'FA1' => 'Facime',
517
+ 'FA' => 'Fairphone',
518
+ 'FM' => 'Famoco',
519
+ 'FAM' => 'Famous',
520
+ '17' => 'FarEasTone',
521
+ '9R' => 'FaRao Pro',
522
+ 'FAR' => 'Farassoo',
523
+ 'FB' => 'Fantec',
524
+ 'FE' => 'Fengxiang',
525
+ 'FEN' => 'Fenoti',
526
+ 'F7' => 'Fero',
527
+ '67' => 'FEONAL',
528
+ 'FI' => 'FiGO',
529
+ 'J9' => 'FiGi',
530
+ 'FIG' => 'Figgers',
531
+ 'F9' => 'FiiO',
532
+ 'F1' => 'FinePower',
533
+ 'FX' => 'Finlux',
534
+ 'F3' => 'FireFly Mobile',
535
+ 'F8' => 'FISE',
536
+ 'FIT' => 'FITCO',
537
+ 'FLM' => 'Filimo',
538
+ 'FIL' => 'FILIX',
539
+ 'FL' => 'Fly',
540
+ 'QC' => 'FLYCAT',
541
+ 'FLY' => 'FLYCOAY',
542
+ 'FLU' => 'Fluo',
543
+ 'FN' => 'FNB',
544
+ 'FOB' => 'Fobem',
545
+ 'FD' => 'Fondi',
546
+ '0F' => 'Fourel',
547
+ '44' => 'Four Mobile',
548
+ 'F0' => 'Fonos',
549
+ 'F2' => 'FORME',
550
+ 'F5' => 'Formuler',
551
+ 'FR' => 'Forstar',
552
+ 'RF' => 'Fortis',
553
+ 'FO' => 'Foxconn',
554
+ 'FOD' => 'FoxxD',
555
+ 'FJ' => 'FOODO',
556
+ 'FOS' => 'FOSSiBOT',
557
+ 'FRE' => 'free',
558
+ 'FT' => 'Freetel',
559
+ 'FEY' => 'FreeYond',
560
+ 'FRU' => 'Frunsi',
561
+ 'F4' => 'F&U',
562
+ '1F' => 'FMT',
563
+ 'FPT' => 'FPT',
564
+ 'FG' => 'Fuego',
565
+ 'FU' => 'Fujitsu',
566
+ '4F' => 'Funai',
567
+ '5J' => 'Fusion5',
568
+ 'FF' => 'Future Mobile Technology',
569
+ 'FFF' => 'FFF SmartLife',
570
+ 'FW' => 'FNF',
571
+ 'FXT' => 'Fxtec',
572
+ 'GT' => 'G-TiDE',
573
+ 'G9' => 'G-Touch',
574
+ 'GFO' => 'Gfone',
575
+ 'GTM' => 'GTMEDIA',
576
+ 'GTX' => 'GTX',
577
+ '0G' => 'GFive',
578
+ 'GM' => 'Garmin-Asus',
579
+ 'GA' => 'Gateway',
580
+ '99' => 'Galaxy Innovations',
581
+ 'GA1' => 'Galactic',
582
+ 'GAM' => 'Gamma',
583
+ 'GAZ' => 'Gazer',
584
+ 'GEA' => 'Geanee',
585
+ 'GEN' => 'Geant',
586
+ 'GD' => 'Gemini',
587
+ 'GN' => 'General Mobile',
588
+ '2G' => 'Genesis',
589
+ 'G2' => 'GEOFOX',
590
+ 'GE' => 'Geotel',
591
+ 'Q4' => 'Geotex',
592
+ 'GEO' => 'GEOZON',
593
+ 'GNO' => 'Getnord',
594
+ 'GER' => 'Gear Mobile',
595
+ 'GH' => 'Ghia',
596
+ '2C' => 'Ghong',
597
+ 'GJ' => 'Ghost',
598
+ 'GG' => 'Gigabyte',
599
+ 'GS' => 'Gigaset',
600
+ 'GZ' => 'Ginzzu',
601
+ '1G' => 'Gini',
602
+ 'GI' => 'Gionee',
603
+ 'GIR' => 'GIRASOLE',
604
+ 'G4' => 'Globex',
605
+ 'GLB' => 'Globmall',
606
+ '38' => 'GLONYX',
607
+ 'U6' => 'Glofiish',
608
+ 'G7' => 'GoGEN',
609
+ 'GC' => 'GOCLEVER',
610
+ '5G' => 'Gocomma',
611
+ 'GB' => 'Gol Mobile',
612
+ 'GL' => 'Goly',
613
+ 'GOL' => 'GoldMaster',
614
+ 'GOS' => 'GoldStar',
615
+ 'GOB' => 'GOLDBERG',
616
+ 'GX' => 'GLX',
617
+ 'G5' => 'Gome',
618
+ 'G1' => 'GoMobile',
619
+ 'GO' => 'Google',
620
+ 'G0' => 'Goophone',
621
+ '6G' => 'Gooweel',
622
+ 'GOO' => 'GOODTEL',
623
+ '8G' => 'Gplus',
624
+ 'GR' => 'Gradiente',
625
+ 'GRE' => 'Graetz',
626
+ 'GP' => 'Grape',
627
+ 'G6' => 'Gree',
628
+ 'GRA' => 'Great Asia',
629
+ '3G' => 'Greentel',
630
+ 'GRO' => 'Green Orange',
631
+ 'GRL' => 'Green Lion',
632
+ 'GR1' => 'GroBerwert',
633
+ 'GF' => 'Gretel',
634
+ '82' => 'Gresso',
635
+ 'GU' => 'Grundig',
636
+ 'GV' => 'Gtel',
637
+ 'CUO' => 'Guophone',
638
+ 'H13' => 'H133',
639
+ '9Z' => 'H96',
640
+ 'HF' => 'Hafury',
641
+ '9F' => 'HAOVM',
642
+ 'HAQ' => 'HAOQIN',
643
+ 'HA' => 'Haier',
644
+ 'HEC' => 'HEC',
645
+ 'XH' => 'Haipai',
646
+ 'HAN' => 'Handheld',
647
+ 'HE' => 'HannSpree',
648
+ 'HNS' => 'Hanseatic',
649
+ 'HK' => 'Hardkernel',
650
+ 'HAR' => 'Harper',
651
+ 'HA1' => 'Hartens',
652
+ 'HS' => 'Hasee',
653
+ '8H' => 'Hamlet',
654
+ 'HAM' => 'Hammer',
655
+ 'HAT' => 'Hathway',
656
+ 'H6' => 'Helio',
657
+ 'HQ' => 'HERO',
658
+ 'ZH' => 'Hezire',
659
+ 'HEX' => 'HexaByte',
660
+ 'HEW' => 'HeadWolf',
661
+ 'HEI' => 'Heimat',
662
+ 'HL' => 'Hi-Level',
663
+ '3H' => 'Hi',
664
+ 'HIB' => 'Hiberg',
665
+ 'HBY' => 'HiBy',
666
+ 'HIH' => 'HiHi',
667
+ 'HIK' => 'HiKing',
668
+ 'H2' => 'Highscreen',
669
+ 'Q1' => 'High Q',
670
+ 'HIG' => 'HiGrace',
671
+ '1H' => 'Hipstreet',
672
+ 'HIR' => 'Hiremco',
673
+ 'HI' => 'Hisense',
674
+ 'HIP' => 'HIPER',
675
+ 'HC' => 'Hitachi',
676
+ 'H8' => 'Hitech',
677
+ 'W3' => 'HiMax',
678
+ '8X' => 'Hi Nova',
679
+ 'HLL' => 'HLLO',
680
+ 'HKC' => 'HKC',
681
+ 'HMD' => 'HMD',
682
+ '8W' => 'HKPro',
683
+ 'HOF' => 'HOFER',
684
+ 'H1' => 'Hoffmann',
685
+ 'HOM' => 'Homatics',
686
+ 'H0' => 'Hometech',
687
+ 'HLB' => 'HOLLEBERG',
688
+ 'HM' => 'Homtom',
689
+ 'HZ' => 'Hoozo',
690
+ 'H7' => 'Horizon',
691
+ '4H' => 'Horizont',
692
+ 'HO' => 'Hosin',
693
+ 'H3' => 'Hotel',
694
+ 'HV' => 'Hotwav',
695
+ 'U8' => 'Hot Pepper',
696
+ 'JH' => 'HOTREALS',
697
+ 'HW' => 'How',
698
+ 'WH' => 'Honeywell',
699
+ 'HP' => 'HP',
700
+ 'HDC' => 'HDC',
701
+ 'HT' => 'HTC',
702
+ 'QZ' => 'Huagan',
703
+ 'HD' => 'Huadoo',
704
+ 'HG' => 'Huavi',
705
+ 'HU' => 'Huawei',
706
+ 'HX' => 'Humax',
707
+ 'HR' => 'Hurricane',
708
+ 'H5' => 'Huskee',
709
+ 'HUG' => 'Hugerock',
710
+ 'HY' => 'Hyrican',
711
+ 'HN' => 'Hyundai',
712
+ '7H' => 'Hyve',
713
+ 'HYT' => 'Hytera',
714
+ 'HYK' => 'Hykker',
715
+ '3I' => 'i-Cherry',
716
+ 'IJ' => 'i-Joy',
717
+ 'IM' => 'i-mate',
718
+ 'IO' => 'i-mobile',
719
+ 'INN' => 'I-INN',
720
+ 'IPL' => 'I-Plus',
721
+ 'OF' => 'iOutdoor',
722
+ 'IB' => 'iBall',
723
+ 'IY' => 'iBerry',
724
+ '7I' => 'iBrit',
725
+ 'IBO' => 'ibowin',
726
+ 'I2' => 'IconBIT',
727
+ 'IC' => 'iDroid',
728
+ 'IDI' => 'iDino',
729
+ '6Z' => 'iData',
730
+ 'IG' => 'iGet',
731
+ 'IH' => 'iHunt',
732
+ 'IA' => 'Ikea',
733
+ 'IYO' => 'iYou',
734
+ '8I' => 'IKU Mobile',
735
+ '2K' => 'IKI Mobile',
736
+ 'IK' => 'iKoMo',
737
+ '58' => 'iKon',
738
+ '588' => 'iKonia',
739
+ 'I7' => 'iLA',
740
+ '2I' => 'iLife',
741
+ '1I' => 'iMars',
742
+ 'IMI' => 'iMI',
743
+ 'U4' => 'iMan',
744
+ 'ILE' => 'iLepo',
745
+ 'IL' => 'IMO Mobile',
746
+ 'IMA' => 'Imaq',
747
+ 'IM1' => 'Imose',
748
+ 'I3' => 'Impression',
749
+ 'FC' => 'INCAR',
750
+ '2H' => 'Inch',
751
+ '6I' => 'Inco',
752
+ 'INK' => 'Inka',
753
+ 'IW' => 'iNew',
754
+ 'IF' => 'Infinix',
755
+ 'INF' => 'Infiniton',
756
+ 'I0' => 'InFocus',
757
+ 'IN1' => 'InFone',
758
+ 'II' => 'Inkti',
759
+ 'MIR' => 'Infomir',
760
+ '81' => 'InfoKit',
761
+ 'I5' => 'InnJoo',
762
+ '26' => 'Innos',
763
+ 'IN' => 'Innostream',
764
+ 'I4' => 'Inoi',
765
+ 'INO' => 'iNo Mobile',
766
+ 'IQ' => 'INQ',
767
+ 'QN' => 'iQ&T',
768
+ 'IS' => 'Insignia',
769
+ 'YI' => 'INSYS',
770
+ 'IT' => 'Intek',
771
+ 'INT' => 'Intel',
772
+ 'IX' => 'Intex',
773
+ 'IV' => 'Inverto',
774
+ '32' => 'Invens',
775
+ '4I' => 'Invin',
776
+ 'INA' => 'iNavi',
777
+ 'I1' => 'iOcean',
778
+ 'IMU' => 'iMuz',
779
+ 'IP' => 'iPro',
780
+ 'X9' => 'iPEGTOP',
781
+ '8Q' => 'IQM',
782
+ 'Q8' => 'IRA',
783
+ 'I6' => 'Irbis',
784
+ '5I' => 'Iris',
785
+ 'IRE' => 'iReplace',
786
+ 'IR' => 'iRola',
787
+ 'IU' => 'iRulu',
788
+ 'IRO' => 'iRobot',
789
+ '9I' => 'iSWAG',
790
+ '9J' => 'iSafe Mobile',
791
+ 'IST' => 'iStar',
792
+ '86' => 'IT',
793
+ 'IZ' => 'iTel',
794
+ '0I' => 'iTruck',
795
+ 'I8' => 'iVA',
796
+ 'IE' => 'iView',
797
+ '0J' => 'iVooMi',
798
+ 'UI' => 'ivvi',
799
+ 'QW' => 'iWaylink',
800
+ 'I9' => 'iZotron',
801
+ 'IXT' => 'iXTech',
802
+ 'IOT' => 'IOTWE',
803
+ 'JA' => 'JAY-Tech',
804
+ 'KJ' => 'Jiake',
805
+ 'JD' => 'Jedi',
806
+ 'JEE' => 'Jeep',
807
+ 'J6' => 'Jeka',
808
+ 'JF' => 'JFone',
809
+ 'JI' => 'Jiayu',
810
+ 'JG' => 'Jinga',
811
+ 'JIN' => 'Jin Tu',
812
+ 'JX' => 'Jio',
813
+ 'VJ' => 'Jivi',
814
+ 'JK' => 'JKL',
815
+ 'JR1' => 'JREN',
816
+ 'JO' => 'Jolla',
817
+ 'JP' => 'Joy',
818
+ 'JOY' => 'JoySurf',
819
+ 'UJ' => 'Juniper Systems',
820
+ 'J5' => 'Just5',
821
+ '7J' => 'Jumper',
822
+ 'JPA' => 'JPay',
823
+ 'JV' => 'JVC',
824
+ 'JXD' => 'JXD',
825
+ 'JS' => 'Jesy',
826
+ 'KT' => 'K-Touch',
827
+ 'KLT' => 'K-Lite',
828
+ 'K4' => 'Kaan',
829
+ 'K7' => 'Kaiomy',
830
+ 'KL' => 'Kalley',
831
+ 'K6' => 'Kanji',
832
+ 'KA' => 'Karbonn',
833
+ 'K5' => 'KATV1',
834
+ 'KAP' => 'Kapsys',
835
+ 'K0' => 'Kata',
836
+ 'KZ' => 'Kazam',
837
+ '9K' => 'Kazuna',
838
+ 'KD' => 'KDDI',
839
+ 'KHA' => 'Khadas',
840
+ 'KS' => 'Kempler & Strauss',
841
+ 'K3' => 'Keneksi',
842
+ 'KHI' => 'KENSHI',
843
+ 'KX' => 'Kenxinda',
844
+ 'KEN' => 'Kenbo',
845
+ 'KND' => 'Kendo',
846
+ 'KZG' => 'KZG',
847
+ 'K1' => 'Kiano',
848
+ '5W' => 'Kingbox',
849
+ 'KI' => 'Kingsun',
850
+ 'KIS' => 'Kinstone',
851
+ 'KF' => 'KINGZONE',
852
+ 'KIN' => 'Kingstar',
853
+ '46' => 'Kiowa',
854
+ 'KV' => 'Kivi',
855
+ '64' => 'Kvant',
856
+ 'KVA' => 'KVADRA',
857
+ '0K' => 'Klipad',
858
+ 'KNM' => 'KN Mobile',
859
+ 'KC' => 'Kocaso',
860
+ 'KK' => 'Kodak',
861
+ 'KG' => 'Kogan',
862
+ 'KM' => 'Komu',
863
+ 'KO' => 'Konka',
864
+ 'KW' => 'Konrow',
865
+ 'KB' => 'Koobee',
866
+ '7K' => 'Koolnee',
867
+ 'K9' => 'Kooper',
868
+ 'KP' => 'KOPO',
869
+ 'KR' => 'Koridy',
870
+ 'XK' => 'Koslam',
871
+ 'K2' => 'KRONO',
872
+ 'KE' => 'Krüger&Matz',
873
+ '5K' => 'KREZ',
874
+ 'WK' => 'KRIP',
875
+ 'KRA' => 'Kraft',
876
+ 'KH' => 'KT-Tech',
877
+ 'Z6' => 'KUBO',
878
+ 'KUG' => 'KuGou',
879
+ 'K8' => 'Kuliao',
880
+ '8K' => 'Kult',
881
+ 'KU' => 'Kumai',
882
+ '6K' => 'Kurio',
883
+ 'KYD' => 'Kydos',
884
+ 'KY' => 'Kyocera',
885
+ 'KQ' => 'Kyowon',
886
+ '1K' => 'Kzen',
887
+ 'LQ' => 'LAIQ',
888
+ 'L6' => 'Land Rover',
889
+ 'L2' => 'Landvo',
890
+ 'LA' => 'Lanix',
891
+ 'LA1' => 'Lanin',
892
+ 'LK' => 'Lark',
893
+ 'Z3' => 'Laurus',
894
+ 'LEC' => 'Lectrus',
895
+ 'LV' => 'Lava',
896
+ 'LVI' => 'Lville',
897
+ 'LC' => 'LCT',
898
+ 'L5' => 'Leagoo',
899
+ 'U3' => 'Leben',
900
+ 'LEB' => 'LeBest',
901
+ 'LD' => 'Ledstar',
902
+ 'LEE' => 'Leelbox',
903
+ 'L1' => 'LeEco',
904
+ '4B' => 'Leff',
905
+ 'LEG' => 'Legend',
906
+ 'L4' => 'Lemhoov',
907
+ 'W9' => 'LEMFO',
908
+ 'LEM' => 'Lemco',
909
+ 'LN' => 'Lenco',
910
+ 'LE' => 'Lenovo',
911
+ 'LT' => 'Leotec',
912
+ 'LP' => 'Le Pan',
913
+ 'ZJ' => 'Leke',
914
+ 'L7' => 'Lephone',
915
+ 'LZ' => 'Lesia',
916
+ 'L3' => 'Lexand',
917
+ 'LX' => 'Lexibook',
918
+ 'LG' => 'LG',
919
+ '39' => 'Liberton',
920
+ '5L' => 'Linsar',
921
+ 'LIN' => 'Linsay',
922
+ 'LF' => 'Lifemaxx',
923
+ 'LI' => 'Lingwin',
924
+ 'LIB' => 'Lingbo',
925
+ 'LIM' => 'Lime',
926
+ 'LJ' => 'L-Max',
927
+ 'LW' => 'Linnex',
928
+ 'JJ' => 'Listo',
929
+ 'LNM' => 'LNMBBS',
930
+ 'LO' => 'Loewe',
931
+ 'YL' => 'Loview',
932
+ 'LOV' => 'Lovme',
933
+ '1L' => 'Logic',
934
+ 'LH' => 'Logic Instrument',
935
+ 'LM' => 'Logicom',
936
+ 'LOG' => 'Logik',
937
+ 'GY' => 'LOKMAT',
938
+ 'LPX' => 'LPX-G',
939
+ '0L' => 'Lumigon',
940
+ 'LU' => 'Lumus',
941
+ 'LUM' => 'Lumitel',
942
+ 'L9' => 'Luna',
943
+ 'LR' => 'Luxor',
944
+ 'LY' => 'LYF',
945
+ 'LL' => 'Leader Phone',
946
+ 'QL' => 'LT Mobile',
947
+ 'MQ' => 'M.T.T.',
948
+ 'MN' => 'M4tel',
949
+ 'XM' => 'Macoox',
950
+ '92' => 'MAC AUDIO',
951
+ 'MJ' => 'Majestic',
952
+ 'FQ' => 'Mafe',
953
+ 'MAG' => 'MAG',
954
+ 'MA2' => 'MAGCH',
955
+ '6Y' => 'Magicsee',
956
+ '23' => 'Magnus',
957
+ 'NH' => 'Manhattan',
958
+ 'MAN' => 'Mango',
959
+ '5M' => 'Mann',
960
+ 'MA' => 'Manta Multimedia',
961
+ 'Z0' => 'Mantra',
962
+ 'J4' => 'Mara',
963
+ 'MAR' => 'Marshal',
964
+ '8Y' => 'Massgo',
965
+ 'MA1' => 'Mascom',
966
+ '2M' => 'Masstel',
967
+ '3X' => 'Mastertech',
968
+ 'MAS' => 'Master-G',
969
+ '50' => 'Matrix',
970
+ 'MAT' => 'Matco Tools',
971
+ '7M' => 'Maxcom',
972
+ '7M1' => 'Maxfone',
973
+ 'ZM' => 'Maximus',
974
+ '6X' => 'Maxtron',
975
+ '0D' => 'MAXVI',
976
+ 'MAX' => 'Maxwell',
977
+ 'XZ' => 'MAXX',
978
+ 'MW' => 'Maxwest',
979
+ 'M0' => 'Maze',
980
+ 'YM' => 'Maze Speed',
981
+ '87' => 'Malata',
982
+ 'MAU' => 'Maunfeld',
983
+ '28' => 'MBOX',
984
+ 'FK' => 'MBI',
985
+ 'MBK' => 'MBK',
986
+ '3D' => 'MDC Store',
987
+ '1Y' => 'MDTV',
988
+ '09' => 'meanIT',
989
+ 'M3' => 'Mecer',
990
+ 'M3M' => 'M3 Mobile',
991
+ '0M' => 'Mecool',
992
+ 'MEM' => 'MeMobile',
993
+ 'MC' => 'Mediacom',
994
+ 'MK' => 'MediaTek',
995
+ 'MD' => 'Medion',
996
+ 'M2' => 'MEEG',
997
+ 'MEG' => 'MEGA VISION',
998
+ 'MP' => 'MegaFon',
999
+ 'X0' => 'mPhone',
1000
+ '3M' => 'Meitu',
1001
+ 'M1' => 'Meizu',
1002
+ '0E' => 'Melrose',
1003
+ 'MU' => 'Memup',
1004
+ 'ME' => 'Metz',
1005
+ 'MEO' => 'MEO',
1006
+ 'MX' => 'MEU',
1007
+ 'MI' => 'MicroMax',
1008
+ 'MIP' => 'mipo',
1009
+ 'MS' => 'Microsoft',
1010
+ '6Q' => 'Microtech',
1011
+ '1X' => 'Minix',
1012
+ 'OM' => 'Mintt',
1013
+ 'MIN' => 'Mint',
1014
+ 'MO' => 'Mio',
1015
+ 'X7' => 'Mione',
1016
+ 'M7' => 'Miray',
1017
+ 'MIT' => 'Mitchell & Brown',
1018
+ '8M' => 'Mito',
1019
+ 'MT' => 'Mitsubishi',
1020
+ '0Y' => 'Mitsui',
1021
+ 'M5' => 'MIXC',
1022
+ '2D' => 'MIVO',
1023
+ '1Z' => 'MiXzo',
1024
+ 'MIW' => 'MIWANG',
1025
+ 'ML' => 'MLLED',
1026
+ 'LS' => 'MLS',
1027
+ 'MLA' => 'MLAB',
1028
+ '5H' => 'MMI',
1029
+ '4M' => 'Mobicel',
1030
+ 'M6' => 'Mobiistar',
1031
+ 'MOK' => 'Mobile Kingdom',
1032
+ 'MH' => 'Mobiola',
1033
+ 'MB' => 'Mobistel',
1034
+ 'ID' => 'MobiIoT',
1035
+ '6W' => 'MobiWire',
1036
+ '9M' => 'Mobo',
1037
+ 'MOB' => 'Mobell',
1038
+ 'MVO' => 'Mobvoi',
1039
+ 'M4' => 'Modecom',
1040
+ 'MF' => 'Mofut',
1041
+ 'MR' => 'Motorola',
1042
+ 'MIV' => 'Motiv',
1043
+ 'MV' => 'Movic',
1044
+ 'MOV' => 'Movitel',
1045
+ 'MO1' => 'MOVISUN',
1046
+ 'MOS' => 'Mosimosi',
1047
+ 'MOX' => 'Moxee',
1048
+ 'MM' => 'Mpman',
1049
+ 'MZ' => 'MSI',
1050
+ '3R' => 'MStar',
1051
+ 'M9' => 'MTC',
1052
+ 'N4' => 'MTN',
1053
+ '72' => 'M-Tech',
1054
+ '9H' => 'M-Horse',
1055
+ '1R' => 'Multilaser',
1056
+ 'MPS' => 'MultiPOS',
1057
+ '1M' => 'MYFON',
1058
+ 'MY' => 'MyPhone',
1059
+ '51' => 'Myros',
1060
+ 'M8' => 'Myria',
1061
+ '6M' => 'Mystery',
1062
+ '3T' => 'MyTab',
1063
+ 'MG' => 'MyWigo',
1064
+ 'J3' => 'Mymaga',
1065
+ 'MYM' => 'MyMobile',
1066
+ '07' => 'MyGica',
1067
+ 'MYG' => 'MygPad',
1068
+ 'MWA' => 'MwalimuPlus',
1069
+ 'NEO' => 'neoCore',
1070
+ 'NER' => 'Neoregent',
1071
+ '08' => 'Nabi',
1072
+ 'N7' => 'National',
1073
+ 'NC' => 'Navcity',
1074
+ '6N' => 'Navitech',
1075
+ '7V' => 'Navitel',
1076
+ 'N3' => 'Navon',
1077
+ '7R' => 'NavRoad',
1078
+ 'NAB' => 'NABO',
1079
+ 'NAS' => 'NASCO',
1080
+ 'NP' => 'Naomi Phone',
1081
+ 'NAN' => 'Nanho',
1082
+ 'NE' => 'NEC',
1083
+ 'NDP' => 'Nedaphone',
1084
+ '8N' => 'Necnot',
1085
+ 'NF' => 'Neffos',
1086
+ '9X' => 'Neo',
1087
+ 'NEK' => 'NEKO',
1088
+ '1N' => 'Neomi',
1089
+ '7Q' => 'Neon IQ',
1090
+ '8F' => 'Neolix',
1091
+ 'NET' => 'NetBox',
1092
+ 'NA' => 'Netgear',
1093
+ 'NEM' => 'Netmak',
1094
+ 'NU' => 'NeuImage',
1095
+ 'NEU' => 'NeuTab',
1096
+ 'NEV' => 'NEVIR',
1097
+ 'NW' => 'Newgen',
1098
+ 'N9' => 'Newland',
1099
+ '0N' => 'Newman',
1100
+ 'NS' => 'NewsMy',
1101
+ 'ND' => 'Newsday',
1102
+ 'HB' => 'New Balance',
1103
+ 'BRI' => 'New Bridge',
1104
+ 'XB' => 'NEXBOX',
1105
+ 'NX' => 'Nexian',
1106
+ '7X' => 'Nexa',
1107
+ 'N8' => 'NEXON',
1108
+ 'N2' => 'Nextbit',
1109
+ 'NT' => 'NextBook',
1110
+ 'NTT' => 'NTT West',
1111
+ '4N' => 'NextTab',
1112
+ 'NEX' => 'NEXT',
1113
+ 'NST' => 'Next & NextStar',
1114
+ 'NJO' => 'nJoy',
1115
+ 'NG' => 'NGM',
1116
+ 'NZ' => 'NG Optics',
1117
+ 'NZP' => 'NGpon',
1118
+ 'NN' => 'Nikon',
1119
+ 'NI' => 'Nintendo',
1120
+ 'NIN' => 'NINETEC',
1121
+ 'N5' => 'NOA',
1122
+ 'N1' => 'Noain',
1123
+ 'N6' => 'Nobby',
1124
+ 'NOC' => 'Novacom',
1125
+ 'NOS' => 'NoviSea',
1126
+ 'NOV' => 'Novey',
1127
+ 'NO1' => 'NOVO',
1128
+ '57' => 'Nubia',
1129
+ 'JN' => 'NOBUX',
1130
+ 'NB' => 'Noblex',
1131
+ 'OG' => 'NOGA',
1132
+ 'NK' => 'Nokia',
1133
+ 'NM' => 'Nomi',
1134
+ '2N' => 'Nomu',
1135
+ '6H' => 'Noontec',
1136
+ 'NR' => 'Nordmende',
1137
+ 'NOR' => 'NORMANDE',
1138
+ '7N' => 'NorthTech',
1139
+ 'NOT' => 'Nothing Phone',
1140
+ '5N' => 'Nos',
1141
+ 'NO' => 'Nous',
1142
+ 'NQ' => 'Novex',
1143
+ 'NOD' => 'noDROPOUT',
1144
+ 'NJ' => 'NuAns',
1145
+ 'NL' => 'NUU Mobile',
1146
+ 'N0' => 'Nuvo',
1147
+ 'NUV' => 'NuVision',
1148
+ 'NV' => 'Nvidia',
1149
+ 'NY' => 'NYX Mobile',
1150
+ 'NON' => 'N-one',
1151
+ 'O3' => 'O+',
1152
+ 'OT' => 'O2',
1153
+ 'O7' => 'Oale',
1154
+ 'OC' => 'OASYS',
1155
+ 'OB' => 'Obi',
1156
+ 'OBR' => 'Ober',
1157
+ 'OQ' => 'Meta',
1158
+ 'O1' => 'Odys',
1159
+ 'ODP' => 'Odotpad',
1160
+ 'O9' => 'Ok',
1161
+ 'OA' => 'Okapia',
1162
+ 'OKI' => 'Oking',
1163
+ 'OLA' => 'Olax',
1164
+ 'OLK' => 'Olkya',
1165
+ 'OLY' => 'Olympia',
1166
+ 'OCE' => 'OCEANIC',
1167
+ 'OLT' => 'OLTO',
1168
+ 'OJ' => 'Ookee',
1169
+ 'OD' => 'Onda',
1170
+ 'ON' => 'OnePlus',
1171
+ 'ONC' => 'OneClick',
1172
+ 'ONL' => 'OneLern',
1173
+ 'OAN' => 'Oangcc',
1174
+ 'OX' => 'Onix',
1175
+ 'OIN' => 'Onida',
1176
+ '3O' => 'ONYX BOOX',
1177
+ 'O4' => 'ONN',
1178
+ '9Q' => 'Onkyo',
1179
+ 'ONV' => 'ONVO',
1180
+ 'OOR' => 'Ooredoo',
1181
+ '2O' => 'OpelMobile',
1182
+ 'OH' => 'Openbox',
1183
+ '7Y' => 'Obabox',
1184
+ 'OP' => 'OPPO',
1185
+ 'OO' => 'Opsson',
1186
+ 'OPT' => 'Optoma',
1187
+ 'OPH' => 'Ophone',
1188
+ 'OR' => 'Orange',
1189
+ 'ORA' => 'Orava',
1190
+ 'O5' => 'Orbic',
1191
+ 'Y6' => 'Orbita',
1192
+ 'ORB' => 'Orbsmart',
1193
+ 'OS' => 'Ordissimo',
1194
+ '8O' => 'Orion',
1195
+ 'OTT' => 'OTTO',
1196
+ 'OK' => 'Ouki',
1197
+ '0O' => 'OINOM',
1198
+ 'QK' => 'OKWU',
1199
+ 'QQ' => 'OMIX',
1200
+ '56' => 'OKSI',
1201
+ 'OE' => 'Oukitel',
1202
+ 'OU' => 'OUYA',
1203
+ 'JB' => 'OUJIA',
1204
+ 'OV' => 'Overmax',
1205
+ '30' => 'Ovvi',
1206
+ 'O2' => 'Owwo',
1207
+ 'OSC' => 'OSCAL',
1208
+ 'OY' => 'Oysters',
1209
+ 'QF' => 'OYSIN',
1210
+ 'O6' => 'Oyyu',
1211
+ 'OZ' => 'OzoneHD',
1212
+ 'OLL' => 'Ollee',
1213
+ '7P' => 'P-UP',
1214
+ 'PRA' => 'Pacific Research Alliance',
1215
+ 'PAG' => 'PAGRAER',
1216
+ 'PAD' => 'Padpro',
1217
+ 'YP' => 'Paladin',
1218
+ 'PM' => 'Palm',
1219
+ 'PN' => 'Panacom',
1220
+ 'PA' => 'Panasonic',
1221
+ 'PNV' => 'Panavox',
1222
+ 'PT' => 'Pantech',
1223
+ 'PAN' => 'Pano',
1224
+ 'PND' => 'Panodic',
1225
+ 'PA1' => 'Panoramic',
1226
+ 'PLT' => 'Platoon',
1227
+ '94' => 'Packard Bell',
1228
+ 'H9' => 'Parrot Mobile',
1229
+ 'PAR' => 'Partner Mobile',
1230
+ 'PAP' => 'PAPYRE',
1231
+ 'PB' => 'PCBOX',
1232
+ 'PCS' => 'PC Smart',
1233
+ 'PC' => 'PCD',
1234
+ 'PD' => 'PCD Argentina',
1235
+ 'PE' => 'PEAQ',
1236
+ 'PEN' => 'Penta',
1237
+ 'PG' => 'Pentagram',
1238
+ 'PQ' => 'Pendoo',
1239
+ '93' => 'Perfeo',
1240
+ '8J' => 'Pelitt',
1241
+ '1P' => 'Phicomm',
1242
+ '4P' => 'Philco',
1243
+ 'PH' => 'Philips',
1244
+ '5P' => 'Phonemax',
1245
+ 'PO' => 'phoneOne',
1246
+ 'PI' => 'Pioneer',
1247
+ 'PIC' => 'Pioneer Computers',
1248
+ 'PJ' => 'PiPO',
1249
+ '8P' => 'Pixelphone',
1250
+ '9O' => 'Pixela',
1251
+ 'PX' => 'Pixus',
1252
+ 'QP' => 'Pico',
1253
+ 'PIR' => 'PIRANHA',
1254
+ 'PIN' => 'PINE',
1255
+ '9P' => 'Planet Computers',
1256
+ 'PLA' => 'Play Now',
1257
+ 'PY' => 'Ployer',
1258
+ 'P4' => 'Plum',
1259
+ 'PLU' => 'PlusStyle',
1260
+ '22' => 'Pluzz',
1261
+ 'P8' => 'PocketBook',
1262
+ '0P' => 'POCO',
1263
+ 'FH' => 'Point Mobile',
1264
+ 'PV' => 'Point of View',
1265
+ 'PL' => 'Polaroid',
1266
+ 'Q6' => 'Polar',
1267
+ '97' => 'PolarLine',
1268
+ 'PP' => 'PolyPad',
1269
+ 'P5' => 'Polytron',
1270
+ 'P2' => 'Pomp',
1271
+ 'P0' => 'Poppox',
1272
+ '0X' => 'POPTEL',
1273
+ 'PS' => 'Positivo',
1274
+ '3P' => 'Positivo BGH',
1275
+ '3F' => 'Porsche',
1276
+ 'P3' => 'PPTV',
1277
+ 'FP' => 'Premio',
1278
+ 'PR1' => 'Premier',
1279
+ 'PR' => 'Prestigio',
1280
+ 'P9' => 'Primepad',
1281
+ 'PRM' => 'PRIME',
1282
+ '6P' => 'Primux',
1283
+ '2P' => 'Prixton',
1284
+ 'PRI' => 'Pritom',
1285
+ 'PF' => 'PROFiLO',
1286
+ 'P6' => 'Proline',
1287
+ '5O' => 'Prology',
1288
+ 'P1' => 'ProScan',
1289
+ 'PRO' => 'PROSONIC',
1290
+ 'P7' => 'Protruly',
1291
+ 'R0' => 'ProVision',
1292
+ '7O' => 'Polestar',
1293
+ 'PU' => 'PULID',
1294
+ 'UP' => 'Purism',
1295
+ 'PUN' => 'Punos',
1296
+ 'QFX' => 'QFX',
1297
+ 'Q7' => 'Q-Box',
1298
+ 'QH' => 'Q-Touch',
1299
+ 'QB' => 'Q.Bell',
1300
+ 'QI' => 'Qilive',
1301
+ 'QIN' => 'QIN',
1302
+ 'QM' => 'QMobile',
1303
+ 'QT' => 'Qtek',
1304
+ 'Q9' => 'QTECH',
1305
+ 'QA' => 'Quantum',
1306
+ 'QUE' => 'Quest',
1307
+ 'QUA' => 'Quatro',
1308
+ 'QU' => 'Quechua',
1309
+ 'QUI' => 'Quipus',
1310
+ 'QO' => 'Qumo',
1311
+ 'UQ' => 'Qubo',
1312
+ 'YQ' => 'QLink',
1313
+ 'QY' => 'Qnet Mobile',
1314
+ 'WJ' => 'Qware',
1315
+ 'QWT' => 'QWATT',
1316
+ 'R2' => 'R-TV',
1317
+ 'RA' => 'Ramos',
1318
+ '0R' => 'Raspberry',
1319
+ 'R9' => 'Ravoz',
1320
+ 'RZ' => 'Razer',
1321
+ '95' => 'Rakuten',
1322
+ 'RAY' => 'Raylandz',
1323
+ 'RC' => 'RCA Tablets',
1324
+ '2R' => 'Reach',
1325
+ 'REL' => 'RelNAT',
1326
+ 'RB' => 'Readboy',
1327
+ 'RE' => 'Realme',
1328
+ 'RE1' => 'Redbean',
1329
+ 'R8' => 'RED',
1330
+ 'REW' => 'Redway',
1331
+ '6F' => 'Redfox',
1332
+ 'RE2' => 'RedLine',
1333
+ 'RD' => 'Reeder',
1334
+ 'Z9' => 'REGAL',
1335
+ 'RH' => 'Remdun',
1336
+ 'RP' => 'Revo',
1337
+ 'REV' => 'Revomovil',
1338
+ '8R' => 'Retroid Pocket',
1339
+ 'REN' => 'Renova',
1340
+ 'RIC' => 'Ricoh',
1341
+ 'RI' => 'Rikomagic',
1342
+ 'RM' => 'RIM',
1343
+ 'RN' => 'Rinno',
1344
+ 'RX' => 'Ritmix',
1345
+ 'R7' => 'Ritzviva',
1346
+ 'RV' => 'Riviera',
1347
+ '6R' => 'Rivo',
1348
+ 'RIZ' => 'Rizzen',
1349
+ 'RR' => 'Roadrover',
1350
+ 'QR' => 'ROADMAX',
1351
+ 'ROC' => 'Roam Cat',
1352
+ 'ROT' => 'Rocket',
1353
+ 'R1' => 'Rokit',
1354
+ 'ROI' => 'ROiK',
1355
+ 'RK' => 'Roku',
1356
+ 'R3' => 'Rombica',
1357
+ 'R5' => 'Ross&Moor',
1358
+ 'RO' => 'Rover',
1359
+ 'R6' => 'RoverPad',
1360
+ 'RQ' => 'RoyQueen',
1361
+ 'RJ' => 'Royole',
1362
+ 'RT' => 'RT Project',
1363
+ 'RG' => 'RugGear',
1364
+ 'RUG' => 'Ruggex',
1365
+ 'RUT' => 'RuggeTech',
1366
+ 'RU' => 'Runbo',
1367
+ 'RUP' => 'Rupa',
1368
+ 'RL' => 'Ruio',
1369
+ 'RY' => 'Ryte',
1370
+ 'X5' => 'Saba',
1371
+ '8L' => 'S-TELL',
1372
+ '8L1' => 'S-Color',
1373
+ '4O' => 'S2Tel',
1374
+ '89' => 'Seatel',
1375
+ 'SEW' => 'Sewoo',
1376
+ 'SE1' => 'SEEWO',
1377
+ 'Y7' => 'Saiet',
1378
+ 'SLF' => 'SAILF',
1379
+ 'X1' => 'Safaricom',
1380
+ 'SG' => 'Sagem',
1381
+ 'SAG' => 'Sagemcom',
1382
+ '4L' => 'Salora',
1383
+ 'SA' => 'Samsung',
1384
+ 'SAT' => 'Samtech',
1385
+ 'SAM' => 'Samtron',
1386
+ 'SNA' => 'SNAMI',
1387
+ 'S0' => 'Sanei',
1388
+ '12' => 'Sansui',
1389
+ 'SAK' => 'Sankey',
1390
+ 'SQ' => 'Santin',
1391
+ 'SY' => 'Sanyo',
1392
+ 'SAN' => 'SANY',
1393
+ 'S9' => 'Savio',
1394
+ 'Y4' => 'SCBC',
1395
+ 'CZ' => 'Schneider',
1396
+ 'SCO' => 'Scosmos',
1397
+ 'ZG' => 'Schok',
1398
+ 'G8' => 'SEG',
1399
+ 'SEX' => 'SEHMAX',
1400
+ 'SD' => 'Sega',
1401
+ '0U' => 'Selecline',
1402
+ '9G' => 'Selenga',
1403
+ 'SV' => 'Selevision',
1404
+ 'SL' => 'Selfix',
1405
+ '0S' => 'SEMP TCL',
1406
+ 'S1' => 'Sencor',
1407
+ 'SN' => 'Sendo',
1408
+ '01' => 'Senkatel',
1409
+ 'S6' => 'Senseit',
1410
+ 'EW' => 'Senwa',
1411
+ '24' => 'Seeken',
1412
+ 'SEB' => 'SEBBE',
1413
+ '61' => 'Seuic',
1414
+ 'SX' => 'SFR',
1415
+ 'SGI' => 'SGIN',
1416
+ 'SH' => 'Sharp',
1417
+ 'JU' => 'Shanling',
1418
+ '7S' => 'Shift Phones',
1419
+ '78' => 'Shivaki',
1420
+ 'RS' => 'Shtrikh-M',
1421
+ '3S' => 'Shuttle',
1422
+ '13' => 'Sico',
1423
+ 'SI' => 'Siemens',
1424
+ '1S' => 'Sigma',
1425
+ '70' => 'Silelis',
1426
+ 'SJ' => 'Silent Circle',
1427
+ 'SIL' => 'Silva Schneider',
1428
+ '10' => 'Simbans',
1429
+ '98' => 'Simply',
1430
+ 'SIM' => 'simfer',
1431
+ '52' => 'Singtech',
1432
+ '31' => 'Siragon',
1433
+ '83' => 'Sirin Labs',
1434
+ '5Z' => 'SK Broadband',
1435
+ 'GK' => 'SKG',
1436
+ 'SW' => 'Sky',
1437
+ 'SK' => 'Skyworth',
1438
+ 'SKY' => 'Skyline',
1439
+ 'SK1' => 'SkyStream',
1440
+ 'SKT' => 'Skytech',
1441
+ 'SKK' => 'SKK Mobile',
1442
+ '14' => 'Smadl',
1443
+ '19' => 'Smailo',
1444
+ 'SR' => 'Smart Electronic',
1445
+ 'SMA' => 'Smart Kassel',
1446
+ '49' => 'Smart',
1447
+ '47' => 'SmartBook',
1448
+ '3B' => 'Smartab',
1449
+ '80' => 'SMARTEC',
1450
+ 'SM1' => 'Smartex',
1451
+ 'SC' => 'Smartfren',
1452
+ 'S7' => 'Smartisan',
1453
+ 'SMU' => 'SMUX',
1454
+ 'JR' => 'Sylvania',
1455
+ 'SYH' => 'SYH',
1456
+ '3Y' => 'Smarty',
1457
+ 'HH' => 'Smooth Mobile',
1458
+ '1Q' => 'Smotreshka',
1459
+ 'SF' => 'Softbank',
1460
+ '9L' => 'SOLE',
1461
+ 'JL' => 'SOLO',
1462
+ 'SOS' => 'SOSH',
1463
+ 'SOD' => 'Soda',
1464
+ 'SOL' => 'Solas',
1465
+ '16' => 'Solone',
1466
+ 'OI' => 'Sonim',
1467
+ 'SVE' => 'Sveon',
1468
+ 'SO' => 'Sony',
1469
+ 'SE' => 'Sony Ericsson',
1470
+ 'X2' => 'Soundmax',
1471
+ 'SUL' => 'SoulLink',
1472
+ '8S' => 'Soyes',
1473
+ '77' => 'SONOS',
1474
+ '68' => 'Soho Style',
1475
+ 'SOB' => 'SobieTech',
1476
+ 'PK' => 'Spark',
1477
+ 'SPX' => 'Sparx',
1478
+ 'FS' => 'SPC',
1479
+ '6S' => 'Spectrum',
1480
+ '43' => 'Spectralink',
1481
+ 'SP' => 'Spice',
1482
+ '84' => 'Sprint',
1483
+ 'SPU' => 'SPURT',
1484
+ 'QS' => 'SQOOL',
1485
+ 'S4' => 'Star',
1486
+ 'OL' => 'Starlight',
1487
+ '18' => 'Starmobile',
1488
+ '2S' => 'Starway',
1489
+ '45' => 'Starwind',
1490
+ 'SB' => 'STF Mobile',
1491
+ 'S8' => 'STK',
1492
+ 'GQ' => 'STG Telecom',
1493
+ 'S2' => 'Stonex',
1494
+ 'ST' => 'Storex',
1495
+ 'STR' => 'Stream',
1496
+ '71' => 'StrawBerry',
1497
+ '96' => 'STRONG',
1498
+ '69' => 'Stylo',
1499
+ '9S' => 'Sugar',
1500
+ 'SUR' => 'Surge',
1501
+ 'SUF' => 'Surfans',
1502
+ '06' => 'Subor',
1503
+ 'SZ' => 'Sumvision',
1504
+ '0H' => 'Sunstech',
1505
+ 'S3' => 'SunVan',
1506
+ '5S' => 'Sunvell',
1507
+ '5Y' => 'Sunny',
1508
+ 'W8' => 'SUNWIND',
1509
+ 'SBX' => 'SuperBOX',
1510
+ 'SBR' => 'Sber',
1511
+ 'SGE' => 'Super General',
1512
+ 'SU' => 'SuperSonic',
1513
+ '79' => 'SuperTab',
1514
+ 'S5' => 'Supra',
1515
+ 'SUP' => 'Supraim',
1516
+ 'ZS' => 'Suzuki',
1517
+ '2J' => 'Sunmi',
1518
+ 'SUN' => 'Sunmax',
1519
+ '0W' => 'Swipe',
1520
+ 'SWI' => 'Switel',
1521
+ 'SS' => 'SWISSMOBILITY',
1522
+ '1W' => 'Swisstone',
1523
+ 'SSK' => 'SSKY',
1524
+ 'SYC' => 'Syco',
1525
+ 'SM' => 'Symphony',
1526
+ '4S' => 'Syrox',
1527
+ 'SYS' => 'System76',
1528
+ 'TM' => 'T-Mobile',
1529
+ 'T96' => 'T96',
1530
+ 'TAD' => 'TADAAM',
1531
+ 'TK' => 'Takara',
1532
+ '73' => 'Tambo',
1533
+ '9N' => 'Tanix',
1534
+ 'U5' => 'Taiga System',
1535
+ 'TAL' => 'Talius',
1536
+ '7G' => 'TAG Tech',
1537
+ 'TAU' => 'TAUBE',
1538
+ 'T5' => 'TB Touch',
1539
+ 'TC' => 'TCL',
1540
+ 'T0' => 'TD Systems',
1541
+ 'YY' => 'TD Tech',
1542
+ 'H4' => 'Technicolor',
1543
+ 'TEA' => 'TeachTouch',
1544
+ 'Z5' => 'Technika',
1545
+ 'TE1' => 'TechSmart',
1546
+ 'TX' => 'TechniSat',
1547
+ 'TT' => 'TechnoTrend',
1548
+ 'TTS' => 'TECHNOSAT',
1549
+ 'TP' => 'TechPad',
1550
+ 'TPS' => 'TPS',
1551
+ '9E' => 'Techwood',
1552
+ '7F' => 'Technopc',
1553
+ 'TCH' => 'Techstorm',
1554
+ 'T7' => 'Teclast',
1555
+ 'TB' => 'Tecno Mobile',
1556
+ 'TEC' => 'TecToy',
1557
+ '91' => 'TEENO',
1558
+ 'TLK' => 'Telkom',
1559
+ '2L' => 'Tele2',
1560
+ 'TL' => 'Telefunken',
1561
+ 'TG' => 'Telego',
1562
+ 'T2' => 'Telenor',
1563
+ 'TE' => 'Telit',
1564
+ '65' => 'Telia',
1565
+ 'TLY' => 'Telly',
1566
+ 'TEL' => 'Telma',
1567
+ 'PW' => 'Telpo',
1568
+ 'TLS' => 'TeloSystems',
1569
+ 'TER' => 'Teracube',
1570
+ 'TD' => 'Tesco',
1571
+ 'TA' => 'Tesla',
1572
+ '9T' => 'Tetratab',
1573
+ 'TET' => 'TETC',
1574
+ 'TZ' => 'teXet',
1575
+ '29' => 'Teknosa',
1576
+ 'JZ' => 'TJC',
1577
+ 'JC' => 'TENPLUS',
1578
+ 'T4' => 'ThL',
1579
+ 'TN' => 'Thomson',
1580
+ 'O0' => 'Thuraya',
1581
+ 'TI' => 'TIANYU',
1582
+ 'JY' => 'Tigers',
1583
+ '8T' => 'Time2',
1584
+ 'TQ' => 'Timovi',
1585
+ 'TIM' => 'TIMvision',
1586
+ '2T' => 'Tinai',
1587
+ 'TF' => 'Tinmo',
1588
+ 'TH' => 'TiPhone',
1589
+ 'YV' => 'TiVo',
1590
+ 'TIB' => 'Tibuta',
1591
+ 'Y3' => 'TOKYO',
1592
+ 'TOX' => 'TOX',
1593
+ 'T1' => 'Tolino',
1594
+ '0T' => 'Tone',
1595
+ 'TY' => 'Tooky',
1596
+ 'TYD' => 'TYD',
1597
+ 'TOO' => 'TOOGO',
1598
+ 'T9' => 'Top House',
1599
+ 'DK' => 'Topelotek',
1600
+ '42' => 'Topway',
1601
+ 'TO' => 'Toplux',
1602
+ 'TOD' => 'TOPDON',
1603
+ 'TOP' => 'TopDevice',
1604
+ 'TO2' => 'TOPSHOWS',
1605
+ '7T' => 'Torex',
1606
+ 'TOR' => 'Torque',
1607
+ '6O' => 'TOSCIDO',
1608
+ 'TO1' => 'Topsion',
1609
+ 'TS' => 'Toshiba',
1610
+ 'T8' => 'Touchmate',
1611
+ 'TOU' => 'Touch Plus',
1612
+ '5R' => 'Transpeed',
1613
+ 'T6' => 'TrekStor',
1614
+ 'T3' => 'Trevi',
1615
+ 'TRI' => 'TriaPlay',
1616
+ 'TJ' => 'Trifone',
1617
+ 'Q5' => 'Trident',
1618
+ '4T' => 'Tronsmart',
1619
+ '11' => 'True',
1620
+ 'JT' => 'True Slim',
1621
+ 'J1' => 'Trio',
1622
+ 'THT' => 'Tsinghua Tongfang',
1623
+ '5C' => 'TTEC',
1624
+ 'TTF' => 'TTfone',
1625
+ 'TTK' => 'TTK-TV',
1626
+ 'TU' => 'Tunisie Telecom',
1627
+ '1T' => 'Turbo',
1628
+ 'TR' => 'Turbo-X',
1629
+ '5X' => 'TurboPad',
1630
+ '5T' => 'TurboKids',
1631
+ 'UR' => 'Turkcell',
1632
+ '4U' => 'TuCEL',
1633
+ 'TUV' => 'Tuvio',
1634
+ '2U' => 'Türk Telekom',
1635
+ 'TV' => 'TVC',
1636
+ 'TW' => 'TWM',
1637
+ 'Z1' => 'TWZ',
1638
+ '6T' => 'Twoe',
1639
+ 'TWN' => 'TwinMOS',
1640
+ '15' => 'Tymes',
1641
+ 'UC' => 'U.S. Cellular',
1642
+ 'UD1' => 'UD',
1643
+ 'UGI' => 'UGINE',
1644
+ 'UG' => 'Ugoos',
1645
+ 'U1' => 'Uhans',
1646
+ 'UH' => 'Uhappy',
1647
+ 'UL' => 'Ulefone',
1648
+ 'UA' => 'Umax',
1649
+ 'UM' => 'UMIDIGI',
1650
+ 'UNT' => 'Unitech',
1651
+ 'UZ' => 'Unihertz',
1652
+ '3Z' => 'UZ Mobile',
1653
+ 'UX' => 'Unimax',
1654
+ 'UNQ' => 'Uniqcell',
1655
+ 'US' => 'Uniscope',
1656
+ 'UNI' => 'Unistrong',
1657
+ 'U2' => 'UNIWA',
1658
+ 'UND' => 'Uniden',
1659
+ 'UO' => 'Unnecto',
1660
+ 'UNN' => 'Unnion Technologies',
1661
+ 'UU' => 'Unonu',
1662
+ 'UN' => 'Unowhy',
1663
+ 'UY' => 'UNNO',
1664
+ 'UOO' => 'UOOGOU',
1665
+ 'UNB' => 'Unblock Tech',
1666
+ 'UK' => 'UTOK',
1667
+ '3U' => 'IUNI',
1668
+ 'UT' => 'UTStarcom',
1669
+ '6U' => 'UTime',
1670
+ '9U' => 'Urovo',
1671
+ 'UW' => 'U-Magic',
1672
+ '5V' => 'VAIO',
1673
+ 'WV' => 'VAVA',
1674
+ 'VA' => 'Vastking',
1675
+ 'VP' => 'Vargo',
1676
+ 'VC' => 'Vankyo',
1677
+ 'VAL' => 'VALEM',
1678
+ 'VA2' => 'VALE',
1679
+ 'VAT' => 'VALTECH',
1680
+ 'VAN' => 'VANGUARD',
1681
+ 'VAW' => 'VANWIN',
1682
+ 'VB' => 'VC',
1683
+ 'VN' => 'Venso',
1684
+ 'VNP' => 'VNPT Technology',
1685
+ 'VEN' => 'Venstar',
1686
+ 'UV' => 'Venturer',
1687
+ 'VQ' => 'Vega',
1688
+ 'WC' => 'VEON',
1689
+ '4V' => 'Verico',
1690
+ 'V4' => 'Verizon',
1691
+ 'VR' => 'Vernee',
1692
+ 'VX' => 'Vertex',
1693
+ 'VE' => 'Vertu',
1694
+ 'VET' => 'VETAS',
1695
+ 'VL' => 'Verykool',
1696
+ 'QV' => 'Verssed',
1697
+ 'VER' => 'Versus',
1698
+ 'V8' => 'Vesta',
1699
+ 'VEK' => 'Vekta',
1700
+ 'VT' => 'Vestel',
1701
+ '48' => 'Vexia',
1702
+ 'V6' => 'VGO TEL',
1703
+ 'QJ' => 'VDVD',
1704
+ 'VIC' => 'Victurio',
1705
+ 'VD' => 'Videocon',
1706
+ 'VW' => 'Videoweb',
1707
+ 'VS' => 'ViewSonic',
1708
+ 'V7' => 'Vinga',
1709
+ 'V3' => 'Vinsoc',
1710
+ 'XD' => 'Vinabox',
1711
+ 'FV' => 'Vios',
1712
+ '0V' => 'Vipro',
1713
+ 'ZV' => 'Virzo',
1714
+ 'VIP' => 'Viper',
1715
+ 'VI' => 'Vitelcom',
1716
+ 'VIB' => 'ViBox',
1717
+ '8V' => 'Viumee',
1718
+ 'V5' => 'Vivax',
1719
+ 'VIV' => 'VIVIMAGE',
1720
+ 'VV' => 'Vivo',
1721
+ '6V' => 'VIWA',
1722
+ 'VII' => 'VIIPOO',
1723
+ 'VID' => 'VIDA',
1724
+ 'VZ' => 'Vizio',
1725
+ 'VIZ' => 'Vizmo',
1726
+ 'VIT' => 'Vityaz',
1727
+ '9V' => 'Vision Touch',
1728
+ 'VIL' => 'Visual Land',
1729
+ 'VI1' => 'VILLAON',
1730
+ 'VK' => 'VK Mobile',
1731
+ 'JM' => 'v-mobile',
1732
+ 'VHO' => 'V-HOPE',
1733
+ 'VHM' => 'V-HOME',
1734
+ 'VGE' => 'V-Gen',
1735
+ 'V0' => 'VKworld',
1736
+ 'VM' => 'Vodacom',
1737
+ 'VOC' => 'VOCAL',
1738
+ 'VF' => 'Vodafone',
1739
+ '7W' => 'VOGA',
1740
+ 'V2' => 'Vonino',
1741
+ '1V' => 'Vontar',
1742
+ 'VG' => 'Vorago',
1743
+ '2V' => 'Vorke',
1744
+ '8U' => 'Vorcom',
1745
+ 'JW' => 'Vortex',
1746
+ 'VOR' => 'Vormor',
1747
+ 'V1' => 'Voto',
1748
+ 'Z7' => 'VOX',
1749
+ 'VO' => 'Voxtel',
1750
+ 'VY' => 'Voyo',
1751
+ 'VOL' => 'Völfen',
1752
+ 'VO1' => 'Volt',
1753
+ 'VOP' => 'Volla',
1754
+ 'V02' => 'VOLIA',
1755
+ 'VH' => 'Vsmart',
1756
+ 'V9' => 'Vsun',
1757
+ 'VU' => 'Vulcan',
1758
+ '3V' => 'VVETIME',
1759
+ 'ZC' => 'VUCATIMES',
1760
+ 'VO2' => 'VOLKANO',
1761
+ 'VUE' => 'Vue Micro',
1762
+ 'WAK' => 'Walker',
1763
+ 'WA' => 'Walton',
1764
+ 'WAF' => 'WAF',
1765
+ 'WAO' => 'W&O',
1766
+ 'WAL' => 'Waltter',
1767
+ 'WAI' => 'Wainyok',
1768
+ 'WHI' => 'White Mobile',
1769
+ 'WHO' => 'Whoop',
1770
+ 'WBL' => 'We. by Loewe.',
1771
+ 'WCP' => 'WeChip',
1772
+ 'WM' => 'Weimei',
1773
+ 'WE' => 'WellcoM',
1774
+ 'W6' => 'WELLINGTON',
1775
+ 'WD' => 'Western Digital',
1776
+ 'WT' => 'Westpoint',
1777
+ 'WAN' => 'Wanmukang',
1778
+ 'WA1' => 'WANSA',
1779
+ 'WY' => 'Wexler',
1780
+ '3W' => 'WE',
1781
+ 'WEC' => 'Wecool',
1782
+ 'WEE' => 'Weelikeit',
1783
+ 'WP' => 'Wieppo',
1784
+ 'W2' => 'Wigor',
1785
+ 'WI' => 'Wiko',
1786
+ 'WF' => 'Wileyfox',
1787
+ 'WS' => 'Winds',
1788
+ 'WN' => 'Wink',
1789
+ '9W' => 'Winmax',
1790
+ 'W5' => 'Winnovo',
1791
+ 'WU' => 'Wintouch',
1792
+ 'WIS' => 'Winstar',
1793
+ 'W0' => 'Wiseasy',
1794
+ '2W' => 'Wizz',
1795
+ 'W4' => 'WIWA',
1796
+ 'WIZ' => 'WizarPos',
1797
+ 'WL' => 'Wolder',
1798
+ 'WG' => 'Wolfgang',
1799
+ 'WQ' => 'Wolki',
1800
+ 'WON' => 'WONDER',
1801
+ 'WO' => 'Wonu',
1802
+ 'W1' => 'Woo',
1803
+ 'WR' => 'Wortmann',
1804
+ 'WX' => 'Woxter',
1805
+ 'XQ' => 'X-AGE',
1806
+ 'XEL' => 'XElectron',
1807
+ 'X3' => 'X-BO',
1808
+ 'XMO' => 'X-Mobile',
1809
+ 'XT' => 'X-TIGI',
1810
+ 'XV' => 'X-View',
1811
+ 'X4' => 'X.Vision',
1812
+ 'X88' => 'X88',
1813
+ 'X96' => 'X96',
1814
+ '96Q' => 'X96Q',
1815
+ 'A95' => 'A95X',
1816
+ 'XG' => 'Xgody',
1817
+ 'XGE' => 'XGEM',
1818
+ 'QX' => 'XGIMI',
1819
+ 'XL' => 'Xiaolajiao',
1820
+ 'XI' => 'Xiaomi',
1821
+ 'XW' => 'Xiaodu',
1822
+ 'XN' => 'Xion',
1823
+ 'XO' => 'Xolo',
1824
+ 'XR' => 'Xoro',
1825
+ 'XS' => 'Xshitou',
1826
+ 'XSM' => 'Xsmart',
1827
+ '4X' => 'Xtouch',
1828
+ 'X8' => 'Xtratech',
1829
+ 'XCR' => 'Xcruiser',
1830
+ 'XCO' => 'XCOM',
1831
+ 'XCL' => 'Xcell',
1832
+ 'XWA' => 'Xwave',
1833
+ 'YD' => 'Yandex',
1834
+ 'YA' => 'Yarvik',
1835
+ 'Y2' => 'Yes',
1836
+ 'YES' => 'Yestel',
1837
+ 'YE' => 'Yezz',
1838
+ 'YG' => 'YEPEN',
1839
+ 'YEL' => 'YELLYOUTH',
1840
+ 'YK' => 'Yoka TV',
1841
+ 'YO' => 'Yota',
1842
+ 'YOU' => 'Youin',
1843
+ 'YO1' => 'Youwei',
1844
+ 'YOO' => 'Yooz',
1845
+ 'YT' => 'Ytone',
1846
+ 'Y9' => 'YOTOPT',
1847
+ 'Y1' => 'Yu',
1848
+ 'YF' => 'YU Fly',
1849
+ 'Y0' => 'YUHO',
1850
+ 'YN' => 'Yuno',
1851
+ 'YUN' => 'YUNDOO',
1852
+ 'YUS' => 'YunSong',
1853
+ 'YUM' => 'YUMKEM',
1854
+ 'YU' => 'Yuandao',
1855
+ 'YS' => 'Yusun',
1856
+ 'YJ' => 'YASIN',
1857
+ 'YX' => 'Yxtel',
1858
+ '0Z' => 'Zatec',
1859
+ '2Z' => 'Zaith',
1860
+ 'ZAM' => 'Zamolxe',
1861
+ 'ZEA' => 'Zealot',
1862
+ 'PZ' => 'Zebra',
1863
+ 'ZE1' => 'Zeblaze',
1864
+ 'ZE' => 'Zeemi',
1865
+ 'WZ' => 'Zeeker',
1866
+ 'ZN' => 'Zen',
1867
+ 'ZK' => 'Zenek',
1868
+ 'ZL' => 'Zentality',
1869
+ 'ZF' => 'Zfiner',
1870
+ 'ZI' => 'Zidoo',
1871
+ 'FZ' => 'ZIFRO',
1872
+ 'ZX' => 'Ziox',
1873
+ 'ZIK' => 'ZIK',
1874
+ 'ZKI' => 'Z-Kai',
1875
+ 'ZIG' => 'Zigo',
1876
+ 'ZIN' => 'Zinox',
1877
+ 'ZO' => 'Zonda',
1878
+ 'ZW' => 'Zonko',
1879
+ 'ZP' => 'Zopo',
1880
+ 'ZOO' => 'ZoomSmart',
1881
+ 'ZO1' => 'Zoom',
1882
+ 'ZT' => 'ZTE',
1883
+ 'ZU' => 'Zuum',
1884
+ 'ZY' => 'Zync',
1885
+ 'ZR' => 'Zyrex',
1886
+ 'ZQ' => 'ZYQ',
1887
+ 'Z4' => 'ZH&K',
1888
+ 'OW' => 'öwn',
1889
+ 'WBF' => 'Webfleet',
1890
+ 'WSS' => 'WS',
1891
+
1892
+ # legacy brands, might be removed in future versions
1893
+ 'WB' => 'Web TV',
1894
+ 'XX' => 'Unknown'
1895
+ }.freeze
18
1896
 
19
1897
  def known?
20
1898
  regex_meta.any?
@@ -25,36 +1903,62 @@ class DeviceDetector
25
1903
  end
26
1904
 
27
1905
  def type
28
- hbbtv? ? 'tv' : regex_meta[:device]
1906
+ if hbbtv? || shelltv?
1907
+ 'tv'
1908
+ else
1909
+ regex_meta[:device]
1910
+ end
29
1911
  end
30
1912
 
31
1913
  def brand
32
- regex_meta[:brand]
1914
+ return regex_meta[:brand] if regex_meta[:brand] == 'Sony Ericsson'
1915
+
1916
+ brand = regex_meta[:regex_name] || regex_meta[:brand] || vendor_fragment.name || fix_for_x_music
1917
+ return if brand == 'Unknown'
1918
+
1919
+ brand
33
1920
  end
34
1921
 
35
1922
  private
36
1923
 
1924
+ def fix_for_x_music
1925
+ user_agent&.include?('X-music Ⅲ') ? 'OneClick' : nil
1926
+ end
1927
+
1928
+ def vendor_fragment
1929
+ ::DeviceDetector::VendorFragment.new(user_agent)
1930
+ end
1931
+
37
1932
  # The order of files needs to be the same as the order of device
38
1933
  # parser classes used in the piwik project.
39
1934
  def filenames
40
1935
  [
41
1936
  'device/televisions.yml',
1937
+ 'device/shell_tv.yml',
1938
+ 'device/notebooks.yml',
42
1939
  'device/consoles.yml',
43
1940
  'device/car_browsers.yml',
44
1941
  'device/cameras.yml',
45
1942
  'device/portable_media_player.yml',
46
- 'device/mobiles.yml',
1943
+ 'device/mobiles.yml'
47
1944
  ]
48
1945
  end
49
1946
 
50
1947
  def matching_regex
51
1948
  from_cache([self.class.name, user_agent]) do
52
1949
  regex_list = hbbtv? ? regexes_for_hbbtv : regexes_other
53
- regex = regex_list.find { |r| user_agent =~ r[:regex] }
1950
+ regex_list = shelltv? ? regexes_for_shelltv : regex_list
1951
+
1952
+ regex = regex_find(user_agent, regex_list)
54
1953
  if regex && regex[:models]
55
- model_regex = regex[:models].find { |m| user_agent =~ m[:regex]}
1954
+ model_regex = regex[:models].find { |m| user_agent =~ m[:regex] }
56
1955
  if model_regex
57
- regex = regex.merge(:regex_model => model_regex[:regex], :model => model_regex[:model], :brand => model_regex[:brand])
1956
+ regex = regex.merge({
1957
+ regex_model: model_regex[:regex],
1958
+ model: model_regex[:model],
1959
+ brand: model_regex[:brand]
1960
+ })
1961
+ regex[:brand] = DEVICE_BRANDS[regex[:brand]] if DEVICE_BRANDS.key?(regex[:brand])
58
1962
  regex[:device] = model_regex[:device] if model_regex.key?(:device)
59
1963
  regex.delete(:models)
60
1964
  end
@@ -63,26 +1967,54 @@ class DeviceDetector
63
1967
  end
64
1968
  end
65
1969
 
1970
+ # Finds the first match of the string in a list of regexes.
1971
+ # Handles exception with special characters caused by bug in Ruby regex
1972
+ # @param user_agent [String] User Agent string
1973
+ # @param regex_list [Array<Regex>] List of regexes
1974
+ #
1975
+ # @return [MatchData, nil] MatchData if string matches any regexp, nil otherwise
1976
+ def regex_find(user_agent, regex_list)
1977
+ regex_list.find { |r| user_agent =~ r[:regex] }
1978
+ rescue RegexpError
1979
+ # Bug in ruby regex and special characters, retry with clean
1980
+ # https://bugs.ruby-lang.org/issues/13671
1981
+ user_agent = user_agent.encode(
1982
+ ::Encoding::ASCII, invalid: :replace, undef: :replace, replace: ''
1983
+ )
1984
+ regex_list.find { |r| user_agent =~ r[:regex] }
1985
+ end
1986
+
66
1987
  def hbbtv?
67
1988
  @regex_hbbtv ||= build_regex('HbbTV/([1-9]{1}(?:\.[0-9]{1}){1,2})')
68
1989
  user_agent =~ @regex_hbbtv
69
1990
  end
70
1991
 
1992
+ def shelltv?
1993
+ @regex_shelltv ||= build_regex('[a-z]+[ _]Shell[ _]\w{6}')
1994
+ user_agent =~ @regex_shelltv
1995
+ end
1996
+
71
1997
  def regexes_for_hbbtv
72
1998
  regexes.select { |r| r[:path] == :'device/televisions.yml' }
73
1999
  end
74
2000
 
2001
+ def regexes_for_shelltv
2002
+ regexes.select { |r| r[:path] == :'device/shell_tv.yml' }
2003
+ end
2004
+
75
2005
  def regexes_other
76
- regexes.select { |r| r[:path] != :'device/televisions.yml' }
2006
+ regexes.reject { |r| r[:path] == :'device/televisions.yml' }
77
2007
  end
78
2008
 
79
2009
  def parse_regexes(path, raw_regexes)
80
2010
  raw_regexes.map do |brand, meta|
81
- fail "invalid device spec: #{meta.inspect}" unless meta[:regex].is_a? String
2011
+ raise "invalid device spec: #{meta.inspect}" unless meta[:regex].is_a? String
2012
+
82
2013
  meta[:regex] = build_regex(meta[:regex])
83
2014
  if meta.key?(:models)
84
2015
  meta[:models].each do |model|
85
- fail "invalid model spec: #{model.inspect}" unless model[:regex].is_a? String
2016
+ raise "invalid model spec: #{model.inspect}" unless model[:regex].is_a? String
2017
+
86
2018
  model[:regex] = build_regex(model[:regex])
87
2019
  model[:brand] = brand.to_s unless model[:brand]
88
2020
  end
@@ -91,6 +2023,5 @@ class DeviceDetector
91
2023
  meta
92
2024
  end
93
2025
  end
94
-
95
2026
  end
96
2027
  end