Animate It! - Version 2.4.1

Version Description

Download this release

Release Info

Developer eleopard
Plugin Icon 128x128 Animate It!
Version 2.4.1
Comparing to
See all releases

Code changes from version 2.4.0 to 2.4.1

assets/helper/class-eds-mobile-detect.php CHANGED
@@ -1,1458 +1,1692 @@
1
  <?php
2
  /**
3
  * Mobile Detect Library
4
- * =====================
5
- *
6
- * Motto: "Every business should have a mobile detection script to detect mobile readers"
7
- *
8
- * Mobile_Detect is a lightweight PHP class for detecting mobile devices (including tablets).
9
- * It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.
10
- *
11
- * @author Current authors: Serban Ghita <serbanghita@gmail.com>
12
- * Nick Ilyin <nick.ilyin@gmail.com>
13
- *
14
- * Original author: Victor Stanciu <vic.stanciu@gmail.com>
15
- *
16
- * @license Code and contributions have 'MIT License'
17
- * More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt
18
- *
19
- * @link Homepage: http://mobiledetect.net
20
- * GitHub Repo: https://github.com/serbanghita/Mobile-Detect
21
- * Google Code: http://code.google.com/p/php-mobile-detect/
22
- * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md
23
- * HOWTO: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples
24
- *
25
- * @version 2.8.24
26
- */
27
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  class EDS_Mobile_Detect
29
  {
30
- /**
31
- * Mobile detection type.
32
- *
33
- * @deprecated since version 2.6.9
34
- */
35
- const DETECTION_TYPE_MOBILE = 'mobile';
36
-
37
- /**
38
- * Extended detection type.
39
- *
40
- * @deprecated since version 2.6.9
41
- */
42
- const DETECTION_TYPE_EXTENDED = 'extended';
43
-
44
- /**
45
- * A frequently used regular expression to extract version #s.
46
- *
47
- * @deprecated since version 2.6.9
48
- */
49
- const VER = '([\w._\+]+)';
50
-
51
- /**
52
- * Top-level device.
53
- */
54
- const MOBILE_GRADE_A = 'A';
55
-
56
- /**
57
- * Mid-level device.
58
- */
59
- const MOBILE_GRADE_B = 'B';
60
-
61
- /**
62
- * Low-level device.
63
- */
64
- const MOBILE_GRADE_C = 'C';
65
-
66
- /**
67
- * Stores the version number of the current release.
68
- */
69
- const VERSION = '2.8.24';
70
-
71
- /**
72
- * A type for the version() method indicating a string return value.
73
- */
74
- const VERSION_TYPE_STRING = 'text';
75
-
76
- /**
77
- * A type for the version() method indicating a float return value.
78
- */
79
- const VERSION_TYPE_FLOAT = 'float';
80
-
81
- /**
82
- * A cache for resolved matches
83
- * @var array
84
- */
85
- protected $cache = array();
86
-
87
- /**
88
- * The User-Agent HTTP header is stored in here.
89
- * @var string
90
- */
91
- protected $userAgent = null;
92
-
93
- /**
94
- * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
95
- * @var array
96
- */
97
- protected $httpHeaders = array();
98
-
99
- /**
100
- * CloudFront headers. E.g. CloudFront-Is-Desktop-Viewer, CloudFront-Is-Mobile-Viewer & CloudFront-Is-Tablet-Viewer.
101
- * @var array
102
- */
103
- protected $cloudfrontHeaders = array();
104
-
105
- /**
106
- * The matching Regex.
107
- * This is good for debug.
108
- * @var string
109
- */
110
- protected $matchingRegex = null;
111
-
112
- /**
113
- * The matches extracted from the regex expression.
114
- * This is good for debug.
115
- * @var string
116
- */
117
- protected $matchesArray = null;
118
-
119
- /**
120
- * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
121
- *
122
- * @deprecated since version 2.6.9
123
- *
124
- * @var string
125
- */
126
- protected $detectionType = self::DETECTION_TYPE_MOBILE;
127
-
128
- /**
129
- * HTTP headers that trigger the 'isMobile' detection
130
- * to be true.
131
- *
132
- * @var array
133
- */
134
- protected static $mobileHeaders = array(
135
-
136
- 'HTTP_ACCEPT' => array('matches' => array(
137
- // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
138
- 'application/x-obml2d',
139
- // BlackBerry devices.
140
- 'application/vnd.rim.html',
141
- 'text/vnd.wap.wml',
142
- 'application/vnd.wap.xhtml+xml'
143
- )),
144
- 'HTTP_X_WAP_PROFILE' => null,
145
- 'HTTP_X_WAP_CLIENTID' => null,
146
- 'HTTP_WAP_CONNECTION' => null,
147
- 'HTTP_PROFILE' => null,
148
- // Reported by Opera on Nokia devices (eg. C3).
149
- 'HTTP_X_OPERAMINI_PHONE_UA' => null,
150
- 'HTTP_X_NOKIA_GATEWAY_ID' => null,
151
- 'HTTP_X_ORANGE_ID' => null,
152
- 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
153
- 'HTTP_X_HUAWEI_USERID' => null,
154
- // Reported by Windows Smartphones.
155
- 'HTTP_UA_OS' => null,
156
- // Reported by Verizon, Vodafone proxy system.
157
- 'HTTP_X_MOBILE_GATEWAY' => null,
158
- // Seen this on HTC Sensation. SensationXE_Beats_Z715e.
159
- 'HTTP_X_ATT_DEVICEID' => null,
160
- // Seen this on a HTC.
161
- 'HTTP_UA_CPU' => array('matches' => array('ARM')),
162
- );
163
-
164
- /**
165
- * List of mobile devices (phones).
166
- *
167
- * @var array
168
- */
169
- protected static $phoneDevices = array(
170
- 'iPhone' => '\biPhone\b|\biPod\b', // |\biTunes
171
- 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
172
- 'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m',
173
- 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6',
174
- // @todo: Is 'Dell Streak' a tablet or a phone? ;)
175
- 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b',
176
- 'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\bMoto E\b',
177
- 'Samsung' => '\bSamsung\b|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F',
178
- 'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323)',
179
- 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533',
180
- 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile',
181
- 'NokiaLumia' => 'Lumia [0-9]{3,4}',
182
- // http://www.micromaxinfo.com/mobiles/smartphones
183
- // Added because the codes might conflict with Acer Tablets.
184
- 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b',
185
- // @todo Complete the regex.
186
- 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ;
187
- 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
188
- // http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
189
- // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
190
- 'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790',
191
- // http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
192
- 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
193
- // http://fr.wikomobile.com
194
- 'Wiko' => 'KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM',
195
- 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)',
196
- // Added simvalley mobile just for fun. They have some interesting devices.
197
- // http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
198
- 'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b',
199
- // Wolfgang - a brand that is sold by Aldi supermarkets.
200
- // http://www.wolfgangmobile.com/
201
- 'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q',
202
- 'Alcatel' => 'Alcatel',
203
- 'Nintendo' => 'Nintendo 3DS',
204
- // http://en.wikipedia.org/wiki/Amoi
205
- 'Amoi' => 'Amoi',
206
- // http://en.wikipedia.org/wiki/INQ
207
- 'INQ' => 'INQ',
208
- // @Tapatalk is a mobile app; http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039
209
- 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser',
210
- );
211
-
212
- /**
213
- * List of tablet devices.
214
- *
215
- * @var array
216
- */
217
- protected static $tabletDevices = array(
218
- // @todo: check for mobile friendly emails topic.
219
- 'iPad' => 'iPad|iPad.*Mobile',
220
- // Removed |^.*Android.*Nexus(?!(?:Mobile).)*$
221
- // @see #442
222
- 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)',
223
- 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y|SM-T280', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone.
224
- // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
225
- 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI)\b',
226
- // Only the Surface tablets with Windows RT are considered mobile.
227
- // http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
228
- 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)',
229
- // http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
230
- 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10',
231
- // Watch out for PadFone, see #132.
232
- // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/
233
- 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z',
234
- 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
235
- 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410',
236
- 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
237
- 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
238
- // http://www.acer.ro/ac/ro/RO/content/drivers
239
- // http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
240
- // http://us.acer.com/ac/en/US/content/group/tablets
241
- // http://www.acer.de/ac/de/DE/content/models/tablets/
242
- // Can conflict with Micromax and Motorola phones codes.
243
- 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\b|W3-810|\bA3-A10\b|\bA3-A11\b|\bA3-A20\b|\bA3-A30',
244
- // http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
245
- // http://us.toshiba.com/tablets/tablet-finder
246
- // http://www.toshiba.co.jp/regza/tablet/
247
- 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
248
- // http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
249
- // http://www.lg.com/us/tablets
250
- 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b',
251
- 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
252
- // Prestigio Tablets http://www.prestigio.com/support
253
- 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002',
254
- // http://support.lenovo.com/en_GB/downloads/default.page?#
255
- 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)',
256
- // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets
257
- 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7',
258
- // http://www.yarvik.com/en/matrix/tablets/
259
- 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b',
260
- 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
261
- 'ArnovaTablet' => '97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2',
262
- // http://www.intenso.de/kategorie_en.php?kategorie=33
263
- // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate
264
- 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004',
265
- // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
266
- 'IRUTablet' => 'M702pro',
267
- 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
268
- // http://www.e-boda.ro/tablete-pc.html
269
- 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
270
- // http://www.allview.ro/produse/droseries/lista-tablete-pc/
271
- 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
272
- // http://wiki.archosfans.com/index.php?title=Main_Page
273
- 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|Archos5|\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\b',
274
- // http://www.ainol.com/plugin.php?identifier=ainol&module=product
275
- 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
276
- 'NokiaLumiaTablet' => 'Lumia 2520',
277
- // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
278
- // Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
279
- // http://www.sony.jp/support/tablet/
280
- 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP612|SOT31',
281
- // http://www.support.philips.com/support/catalog/worldproducts.jsp?userLanguage=en&userCountry=cn&categoryid=3G_LTE_TABLET_SU_CN_CARE&title=3G%20tablets%20/%20LTE%20range&_dyncharset=UTF-8
282
- 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b',
283
- // db + http://www.cube-tablet.com/buy-products.html
284
- 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
285
- // http://www.cobyusa.com/?p=pcat&pcat_id=3001
286
- 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
287
- // http://www.match.net.cn/products.asp
288
- 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10',
289
- // http://www.msi.com/support
290
- // @todo Research the Windows Tablets.
291
- 'MSITablet' => 'MSI \b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\b',
292
- // @todo http://www.kyoceramobile.com/support/drivers/
293
- // 'KyoceraTablet' => null,
294
- // @todo http://intexuae.com/index.php/category/mobile-devices/tablets-products/
295
- // 'IntextTablet' => null,
296
- // http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
297
- // http://www.imp3.net/14/show.php?itemid=20454
298
- 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
299
- // http://www.rock-chips.com/index.php?do=prod&pid=2
300
- 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
301
- // http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
302
- 'FlyTablet' => 'IQ310|Fly Vision',
303
- // http://www.bqreaders.com/gb/tablets-prices-sale.html
304
- 'bqTablet' => 'Android.*(bq)?.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris [E|M]10)|Maxwell.*Lite|Maxwell.*Plus',
305
- // http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
306
- // http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
307
- 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim',
308
- // Nec or Medias Tab
309
- 'NecTablet' => '\bN-06D|\bN-08D',
310
- // Pantech Tablets: http://www.pantechusa.com/phones/
311
- 'PantechTablet' => 'Pantech.*P4100',
312
- // Broncho Tablets: http://www.broncho.cn/ (hard to find)
313
- 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
314
- // http://versusuk.com/support.html
315
- 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
316
- // http://www.zync.in/index.php/our-products/tablet-phablets
317
- 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
318
- // http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
319
- 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
320
- // https://www.nabitablet.com/
321
- 'NabiTablet' => 'Android.*\bNabi',
322
- 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
323
- // French Danew Tablets http://www.danew.com/produits-tablette.php
324
- 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
325
- // Texet Tablets and Readers http://www.texet.ru/tablet/
326
- 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE',
327
- // Avoid detecting 'PLAYSTATION 3' as mobile.
328
- 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
329
- // http://www.trekstor.de/surftabs.html
330
- 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab',
331
- // http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets
332
- 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
333
- // http://www.advandigital.com/index.php?link=content-product&jns=JP001
334
- // because of the short codenames we have to include whitespaces to reduce the possible conflicts.
335
- 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ',
336
- // http://www.danytech.com/category/tablet-pc
337
- 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1',
338
- // http://www.galapad.net/product.html
339
- 'GalapadTablet' => 'Android.*\bG1\b',
340
- // http://www.micromaxinfo.com/tablet/funbook
341
- 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
342
- // http://www.karbonnmobiles.com/products_tablet.php
343
- 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
344
- // http://www.myallfine.com/Products.asp
345
- 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
346
- // http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
347
- 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b',
348
- // http://www.yonesnav.com/products/products.php
349
- 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
350
- // http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
351
- // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
352
- 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503',
353
- // http://www.gloryunion.cn/products.asp
354
- // http://www.allwinnertech.com/en/apply/mobile.html
355
- // http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
356
- // @todo: Softwiner tablets?
357
- // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
358
- 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G
359
- // http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
360
- 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10',
361
- // http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
362
- // @todo: add more tests.
363
- 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)',
364
- // http://hclmetablet.com/India/index.php
365
- 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync',
366
- // http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
367
- 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
368
- // http://www.visture.com/index.asp
369
- 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
370
- // http://www.mijncresta.nl/tablet
371
- 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
372
- // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309
373
- 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
374
- // Concorde tab
375
- 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
376
- // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/
377
- 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042',
378
- // Modecom Tablets - http://www.modecom.eu/tablets/portal/
379
- 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003',
380
- // Vonino Tablets - http://www.vonino.eu/tablets
381
- 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b',
382
- // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0
383
- 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
384
- // Storex Tablets - http://storex.fr/espace_client/support.html
385
- // @note: no need to add all the tablet codes since they are guided by the first regex.
386
- 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
387
- // Generic Vodafone tablets.
388
- 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497',
389
- // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb
390
- // Aka: http://www.essentielb.fr/
391
- 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
392
- // Ross & Moor - http://ross-moor.ru/
393
- 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
394
- // i-mobile http://product.i-mobilephone.com/Mobile_Device
395
- 'iMobileTablet' => 'i-mobile i-note',
396
- // http://www.tolino.de/de/vergleichen/
397
- 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
398
- // AudioSonic - a Kmart brand
399
- // http://www.kmart.com.au/webapp/wcs/stores/servlet/Search?langId=-1&storeId=10701&catalogId=10001&categoryId=193001&pageSize=72&currentPage=1&searchCategory=193001%2b4294965664&sortBy=p_MaxPrice%7c1
400
- 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
401
- // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/
402
- // @todo: add them gradually to avoid conflicts.
403
- 'AMPETablet' => 'Android.* A78 ',
404
- // Skk Mobile - http://skkmobile.com.ph/product_tablets.php
405
- 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
406
- // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1
407
- 'TecnoTablet' => 'TECNO P9',
408
- // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3
409
- 'JXDTablet' => 'Android.* \b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b',
410
- // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/
411
- 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)',
412
- // http://www.intracon.eu/tablet
413
- 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
414
- // http://www.xoro.de/produkte/
415
- // @note: Might be the same brand with 'Simply tablets'
416
- 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151',
417
- // http://www1.viewsonic.com/products/computing/tablets/
418
- 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
419
- // http://www.odys.de/web/internet-tablet_en.html
420
- 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10',
421
- // http://www.captiva-power.de/products.html#tablets-en
422
- 'CaptivaTablet' => 'CAPTIVA PAD',
423
- // IconBIT - http://www.iconbit.com/products/tablets/
424
- 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S',
425
- // http://www.teclast.com/topic.php?channelID=70&topicID=140&pid=63
426
- 'TeclastTablet' => 'T98 4G|\bP80\b|\bX90HD\b|X98 Air|X98 Air 3G|\bX89\b|P80 3G|\bX80h\b|P98 Air|\bX89HD\b|P98 3G|\bP90HD\b|P89 3G|X98 3G|\bP70h\b|P79HD 3G|G18d 3G|\bP79HD\b|\bP89s\b|\bA88\b|\bP10HD\b|\bP19HD\b|G18 3G|\bP78HD\b|\bA78\b|\bP75\b|G17s 3G|G17h 3G|\bP85t\b|\bP90\b|\bP11\b|\bP98t\b|\bP98HD\b|\bG18d\b|\bP85s\b|\bP11HD\b|\bP88s\b|\bA80HD\b|\bA80se\b|\bA10h\b|\bP89\b|\bP78s\b|\bG18\b|\bP85\b|\bA70h\b|\bA70\b|\bG17\b|\bP18\b|\bA80s\b|\bA11s\b|\bP88HD\b|\bA80h\b|\bP76s\b|\bP76h\b|\bP98\b|\bA10HD\b|\bP78\b|\bP88\b|\bA11\b|\bA10t\b|\bP76a\b|\bP76t\b|\bP76e\b|\bP85HD\b|\bP85a\b|\bP86\b|\bP75HD\b|\bP76v\b|\bA12\b|\bP75a\b|\bA15\b|\bP76Ti\b|\bP81HD\b|\bA10\b|\bT760VE\b|\bT720HD\b|\bP76\b|\bP73\b|\bP71\b|\bP72\b|\bT720SE\b|\bC520Ti\b|\bT760\b|\bT720VE\b|T720-3GE|T720-WiFi',
427
- // Onda - http://www.onda-tablet.com/buy-android-onda.html?dir=desc&limit=all&order=price
428
- 'OndaTablet' => '\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\b[\s]+',
429
- 'JaytechTablet' => 'TPC-PA762',
430
- 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010',
431
- // http://www.digma.ru/support/download/
432
- // @todo: Ebooks also (if requested)
433
- 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b',
434
- // http://www.evolioshop.com/ro/tablete-pc.html
435
- // http://www.evolio.ro/support/downloads_static.html?cat=2
436
- // @todo: Research some more
437
- 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b',
438
- // @todo http://www.lavamobiles.com/tablets-data-cards
439
- 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY|\bE-TAB\b',
440
- // http://www.breezetablet.com/
441
- 'AocTablet' => 'MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712',
442
- // http://www.mpmaneurope.com/en/products/internet-tablets-14/android-tablets-14/
443
- 'MpmanTablet' => 'MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\bMPG7\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010',
444
- // https://www.celkonmobiles.com/?_a=categoryphones&sid=2
445
- 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b',
446
- // http://www.wolderelectronics.com/productos/manuales-y-guias-rapidas/categoria-2-miTab
447
- 'WolderTablet' => 'miTab \b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\b',
448
- // http://www.mi.com/en
449
- 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b',
450
- // http://www.nbru.cn/index.html
451
- 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One',
452
- // http://navroad.com/products/produkty/tablety/
453
- 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI',
454
- // http://leader-online.com/new_site/product-category/tablets/
455
- // http://www.leader-online.net.au/List/Tablet
456
- 'LeaderTablet' => 'TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100',
457
- // http://www.datawind.com/ubislate/
458
- 'UbislateTablet' => 'UbiSlate[\s]?7C',
459
- // http://www.pocketbook-int.com/ru/support
460
- 'PocketBookTablet' => 'Pocketbook',
461
- // http://www.kocaso.com/product_tablet.html
462
- 'KocasoTablet' => '\b(TB-1207)\b',
463
- // http://global.hisense.com/product/asia/tablet/Sero7/201412/t20141215_91832.htm
464
- 'HisenseTablet' => '\b(F5281|E2371)\b',
465
- // http://www.tesco.com/direct/hudl/
466
- 'Hudl' => 'Hudl HT7S3|Hudl 2',
467
- // http://www.telstra.com.au/home-phone/thub-2/
468
- 'TelstraTablet' => 'T-Hub2',
469
- 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b'
470
- );
471
-
472
- /**
473
- * List of mobile Operating Systems.
474
- *
475
- * @var array
476
- */
477
- protected static $operatingSystems = array(
478
- 'AndroidOS' => 'Android',
479
- 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
480
- 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
481
- 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
482
- // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
483
- 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
484
- // @reference: http://en.wikipedia.org/wiki/Windows_Phone
485
- // http://wifeng.cn/?r=blog&a=view&id=106
486
- // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
487
- // http://msdn.microsoft.com/library/ms537503.aspx
488
- // https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
489
- 'WindowsPhoneOS' => 'Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;',
490
- 'iOS' => '\biPhone.*Mobile|\biPod|\biPad',
491
- // http://en.wikipedia.org/wiki/MeeGo
492
- // @todo: research MeeGo in UAs
493
- 'MeeGoOS' => 'MeeGo',
494
- // http://en.wikipedia.org/wiki/Maemo
495
- // @todo: research Maemo in UAs
496
- 'MaemoOS' => 'Maemo',
497
- 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
498
- 'webOS' => 'webOS|hpwOS',
499
- 'badaOS' => '\bBada\b',
500
- 'BREWOS' => 'BREW',
501
- );
502
-
503
- /**
504
- * List of mobile User Agents.
505
- *
506
- * IMPORTANT: This is a list of only mobile browsers.
507
- * Mobile Detect 2.x supports only mobile browsers,
508
- * it was never designed to detect all browsers.
509
- * The change will come in 2017 in the 3.x release for PHP7.
510
- *
511
- * @var array
512
- */
513
- protected static $browsers = array(
514
- //'Vivaldi' => 'Vivaldi',
515
- // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
516
- 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
517
- 'Dolfin' => '\bDolfin\b',
518
- 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+',
519
- 'Skyfire' => 'Skyfire',
520
- 'Edge' => 'Mobile Safari/[.0-9]* Edge',
521
- 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
522
- 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS',
523
- 'Bolt' => 'bolt',
524
- 'TeaShark' => 'teashark',
525
- 'Blazer' => 'Blazer',
526
- // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
527
- 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari',
528
- // http://en.wikipedia.org/wiki/Midori_(web_browser)
529
- //'Midori' => 'midori',
530
- //'Tizen' => 'Tizen',
531
- 'UCBrowser' => 'UC.*Browser|UCWEB',
532
- 'baiduboxapp' => 'baiduboxapp',
533
- 'baidubrowser' => 'baidubrowser',
534
- // https://github.com/serbanghita/Mobile-Detect/issues/7
535
- 'DiigoBrowser' => 'DiigoBrowser',
536
- // http://www.puffinbrowser.com/index.php
537
- 'Puffin' => 'Puffin',
538
- // http://mercury-browser.com/index.html
539
- 'Mercury' => '\bMercury\b',
540
- // http://en.wikipedia.org/wiki/Obigo_Browser
541
- 'ObigoBrowser' => 'Obigo',
542
- // http://en.wikipedia.org/wiki/NetFront
543
- 'NetFront' => 'NF-Browser',
544
- // @reference: http://en.wikipedia.org/wiki/Minimo
545
- // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
546
- 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger',
547
- // @reference: https://en.wikipedia.org/wiki/Pale_Moon_(web_browser)
548
- 'PaleMoon' => 'Android.*PaleMoon|Mobile.*PaleMoon',
549
- );
550
-
551
- /**
552
- * Utilities.
553
- *
554
- * @var array
555
- */
556
- protected static $utilities = array(
557
- // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
558
- // http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
559
- // https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
560
- // https://developers.facebook.com/docs/sharing/best-practices
561
- 'Bot' => 'Googlebot|facebookexternalhit|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom',
562
- 'MobileBot' => 'Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2',
563
- 'DesktopMode' => 'WPDesktop',
564
- 'TV' => 'SonyDTV|HbbTV', // experimental
565
- 'WebKit' => '(webkit)[ /]([\w.]+)',
566
- // @todo: Include JXD consoles.
567
- 'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|PLAYSTATION|Xbox)\b',
568
- 'Watch' => 'SM-V700',
569
- );
570
-
571
- /**
572
- * All possible HTTP headers that represent the
573
- * User-Agent string.
574
- *
575
- * @var array
576
- */
577
- protected static $uaHttpHeaders = array(
578
- // The default User-Agent string.
579
- 'HTTP_USER_AGENT',
580
- // Header can occur on devices using Opera Mini.
581
- 'HTTP_X_OPERAMINI_PHONE_UA',
582
- // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
583
- 'HTTP_X_DEVICE_USER_AGENT',
584
- 'HTTP_X_ORIGINAL_USER_AGENT',
585
- 'HTTP_X_SKYFIRE_PHONE',
586
- 'HTTP_X_BOLT_PHONE_UA',
587
- 'HTTP_DEVICE_STOCK_UA',
588
- 'HTTP_X_UCBROWSER_DEVICE_UA'
589
- );
590
-
591
- /**
592
- * The individual segments that could exist in a User-Agent string. VER refers to the regular
593
- * expression defined in the constant self::VER.
594
- *
595
- * @var array
596
- */
597
- protected static $properties = array(
598
-
599
- // Build
600
- 'Mobile' => 'Mobile/[VER]',
601
- 'Build' => 'Build/[VER]',
602
- 'Version' => 'Version/[VER]',
603
- 'VendorID' => 'VendorID/[VER]',
604
-
605
- // Devices
606
- 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
607
- 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
608
- 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
609
- //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
610
- 'Kindle' => 'Kindle/[VER]',
611
-
612
- // Browser
613
- 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
614
- 'Coast' => array('Coast/[VER]'),
615
- 'Dolfin' => 'Dolfin/[VER]',
616
- // @reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
617
- 'Firefox' => array('Firefox/[VER]', 'FxiOS/[VER]'),
618
- 'Fennec' => 'Fennec/[VER]',
619
- // http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
620
- // https://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx
621
- 'Edge' => 'Edge/[VER]',
622
- 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];', 'Trident/[0-9.]+;.*rv:[VER]'),
623
- // http://en.wikipedia.org/wiki/NetFront
624
- 'NetFront' => 'NetFront/[VER]',
625
- 'NokiaBrowser' => 'NokiaBrowser/[VER]',
626
- 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),
627
- 'Opera Mini' => 'Opera Mini/[VER]',
628
- 'Opera Mobi' => 'Version/[VER]',
629
- 'UC Browser' => 'UC Browser[VER]',
630
- 'MQQBrowser' => 'MQQBrowser/[VER]',
631
- 'MicroMessenger' => 'MicroMessenger/[VER]',
632
- 'baiduboxapp' => 'baiduboxapp/[VER]',
633
- 'baidubrowser' => 'baidubrowser/[VER]',
634
- 'SamsungBrowser' => 'SamsungBrowser/[VER]',
635
- 'Iron' => 'Iron/[VER]',
636
- // @note: Safari 7534.48.3 is actually Version 5.1.
637
- // @note: On BlackBerry the Version is overwriten by the OS.
638
- 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ),
639
- 'Skyfire' => 'Skyfire/[VER]',
640
- 'Tizen' => 'Tizen/[VER]',
641
- 'Webkit' => 'webkit[ /][VER]',
642
- 'PaleMoon' => 'PaleMoon/[VER]',
643
-
644
- // Engine
645
- 'Gecko' => 'Gecko/[VER]',
646
- 'Trident' => 'Trident/[VER]',
647
- 'Presto' => 'Presto/[VER]',
648
- 'Goanna' => 'Goanna/[VER]',
649
-
650
- // OS
651
- 'iOS' => ' \bi?OS\b [VER][ ;]{1}',
652
- 'Android' => 'Android [VER]',
653
- 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),
654
- 'BREW' => 'BREW [VER]',
655
- 'Java' => 'Java/[VER]',
656
- // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
657
- // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
658
- 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'),
659
- 'Windows Phone' => 'Windows Phone [VER]',
660
- 'Windows CE' => 'Windows CE/[VER]',
661
- // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
662
- 'Windows NT' => 'Windows NT [VER]',
663
- 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
664
- 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
665
- );
666
-
667
- /**
668
- * Construct an instance of this class.
669
- *
670
- * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored.
671
- * If left empty, will use the global _SERVER['HTTP_*'] vars instead.
672
- * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
673
- * from the $headers array instead.
674
- */
675
- public function __construct(
676
- array $headers = null,
677
- $userAgent = null
678
- ) {
679
- $this->setHttpHeaders($headers);
680
- $this->setUserAgent($userAgent);
681
- }
682
-
683
- /**
684
- * Get the current script version.
685
- * This is useful for the demo.php file,
686
- * so people can check on what version they are testing
687
- * for mobile devices.
688
- *
689
- * @return string The version number in semantic version format.
690
- */
691
- public static function getScriptVersion()
692
- {
693
- return self::VERSION;
694
- }
695
-
696
- /**
697
- * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
698
- *
699
- * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
700
- * the headers. The default null is left for backwards compatibility.
701
- */
702
- public function setHttpHeaders($httpHeaders = null)
703
- {
704
- // use global _SERVER if $httpHeaders aren't defined
705
- if (!is_array($httpHeaders) || !count($httpHeaders)) {
706
- $httpHeaders = $_SERVER;
707
- }
708
-
709
- // clear existing headers
710
- $this->httpHeaders = array();
711
-
712
- // Only save HTTP headers. In PHP land, that means only _SERVER vars that
713
- // start with HTTP_.
714
- foreach ($httpHeaders as $key => $value) {
715
- if (substr($key, 0, 5) === 'HTTP_') {
716
- $this->httpHeaders[sanitize_text_field( $key )] = sanitize_text_field( $value );
717
- }
718
- }
719
-
720
- // In case we're dealing with CloudFront, we need to know.
721
- $this->setCfHeaders($httpHeaders);
722
- }
723
-
724
- /**
725
- * Retrieves the HTTP headers.
726
- *
727
- * @return array
728
- */
729
- public function getHttpHeaders()
730
- {
731
- return $this->httpHeaders;
732
- }
733
-
734
- /**
735
- * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
736
- * Simply null is returned.
737
- *
738
- * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
739
- * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
740
- * all-caps, HTTP_ prefixed, underscore seperated awesomeness.
741
- *
742
- * @return string|null The value of the header.
743
- */
744
- public function getHttpHeader($header)
745
- {
746
- // are we using PHP-flavored headers?
747
- if (strpos($header, '_') === false) {
748
- $header = str_replace('-', '_', $header);
749
- $header = strtoupper($header);
750
- }
751
-
752
- // test the alternate, too
753
- $altHeader = 'HTTP_' . $header;
754
-
755
- //Test both the regular and the HTTP_ prefix
756
- if (isset($this->httpHeaders[$header])) {
757
- return $this->httpHeaders[$header];
758
- } elseif (isset($this->httpHeaders[$altHeader])) {
759
- return $this->httpHeaders[$altHeader];
760
- }
761
-
762
- return null;
763
- }
764
-
765
- public function getMobileHeaders()
766
- {
767
- return self::$mobileHeaders;
768
- }
769
-
770
- /**
771
- * Get all possible HTTP headers that
772
- * can contain the User-Agent string.
773
- *
774
- * @return array List of HTTP headers.
775
- */
776
- public function getUaHttpHeaders()
777
- {
778
- return self::$uaHttpHeaders;
779
- }
780
-
781
-
782
- /**
783
- * Set CloudFront headers
784
- * http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-device
785
- *
786
- * @param array $cfHeaders List of HTTP headers
787
- *
788
- * @return boolean If there were CloudFront headers to be set
789
- */
790
- public function setCfHeaders($cfHeaders = null) {
791
- // use global _SERVER if $cfHeaders aren't defined
792
- if (!is_array($cfHeaders) || !count($cfHeaders)) {
793
- $cfHeaders = $_SERVER;
794
- }
795
-
796
- // clear existing headers
797
- $this->cloudfrontHeaders = array();
798
-
799
- // Only save CLOUDFRONT headers. In PHP land, that means only _SERVER vars that
800
- // start with cloudfront-.
801
- $response = false;
802
- foreach ($cfHeaders as $key => $value) {
803
- if (substr(strtolower($key), 0, 16) === 'http_cloudfront_') {
804
- $this->cloudfrontHeaders[sanitize_text_field( strtoupper($key) )] = sanitize_text_field( $value );
805
- $response = true;
806
- }
807
- }
808
-
809
- return $response;
810
- }
811
-
812
- /**
813
- * Retrieves the cloudfront headers.
814
- *
815
- * @return array
816
- */
817
- public function getCfHeaders()
818
- {
819
- return $this->cloudfrontHeaders;
820
- }
821
-
822
- /**
823
- * Set the User-Agent to be used.
824
- *
825
- * @param string $userAgent The user agent string to set.
826
- *
827
- * @return string|null
828
- */
829
- public function setUserAgent($userAgent = null)
830
- {
831
- // Invalidate cache due to #375
832
- $this->cache = array();
833
-
834
- if (false === empty($userAgent)) {
835
- return $this->userAgent = $userAgent;
836
- } else {
837
- $this->userAgent = null;
838
- foreach ($this->getUaHttpHeaders() as $altHeader) {
839
- if (false === empty($this->httpHeaders[$altHeader])) { // @todo: should use getHttpHeader(), but it would be slow. (Serban)
840
- $this->userAgent .= $this->httpHeaders[$altHeader] . " ";
841
- }
842
- }
843
-
844
- if (!empty($this->userAgent)) {
845
- return $this->userAgent = trim($this->userAgent);
846
- }
847
- }
848
-
849
- if (count($this->getCfHeaders()) > 0) {
850
- return $this->userAgent = 'Amazon CloudFront';
851
- }
852
- return $this->userAgent = null;
853
- }
854
-
855
- /**
856
- * Retrieve the User-Agent.
857
- *
858
- * @return string|null The user agent if it's set.
859
- */
860
- public function getUserAgent()
861
- {
862
- return $this->userAgent;
863
- }
864
-
865
- /**
866
- * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
867
- * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
868
- *
869
- * @deprecated since version 2.6.9
870
- *
871
- * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
872
- * parameter is null which will default to self::DETECTION_TYPE_MOBILE.
873
- */
874
- public function setDetectionType($type = null)
875
- {
876
- if ($type === null) {
877
- $type = self::DETECTION_TYPE_MOBILE;
878
- }
879
-
880
- if ($type !== self::DETECTION_TYPE_MOBILE && $type !== self::DETECTION_TYPE_EXTENDED) {
881
- return;
882
- }
883
-
884
- $this->detectionType = $type;
885
- }
886
-
887
- public function getMatchingRegex()
888
- {
889
- return $this->matchingRegex;
890
- }
891
-
892
- public function getMatchesArray()
893
- {
894
- return $this->matchesArray;
895
- }
896
-
897
- /**
898
- * Retrieve the list of known phone devices.
899
- *
900
- * @return array List of phone devices.
901
- */
902
- public static function getPhoneDevices()
903
- {
904
- return self::$phoneDevices;
905
- }
906
-
907
- /**
908
- * Retrieve the list of known tablet devices.
909
- *
910
- * @return array List of tablet devices.
911
- */
912
- public static function getTabletDevices()
913
- {
914
- return self::$tabletDevices;
915
- }
916
-
917
- /**
918
- * Alias for getBrowsers() method.
919
- *
920
- * @return array List of user agents.
921
- */
922
- public static function getUserAgents()
923
- {
924
- return self::getBrowsers();
925
- }
926
-
927
- /**
928
- * Retrieve the list of known browsers. Specifically, the user agents.
929
- *
930
- * @return array List of browsers / user agents.
931
- */
932
- public static function getBrowsers()
933
- {
934
- return self::$browsers;
935
- }
936
-
937
- /**
938
- * Retrieve the list of known utilities.
939
- *
940
- * @return array List of utilities.
941
- */
942
- public static function getUtilities()
943
- {
944
- return self::$utilities;
945
- }
946
-
947
- /**
948
- * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
949
- *
950
- * @deprecated since version 2.6.9
951
- *
952
- * @return array All the rules (but not extended).
953
- */
954
- public static function getMobileDetectionRules()
955
- {
956
- static $rules;
957
-
958
- if (!$rules) {
959
- $rules = array_merge(
960
- self::$phoneDevices,
961
- self::$tabletDevices,
962
- self::$operatingSystems,
963
- self::$browsers
964
- );
965
- }
966
-
967
- return $rules;
968
-
969
- }
970
-
971
- /**
972
- * Method gets the mobile detection rules + utilities.
973
- * The reason this is separate is because utilities rules
974
- * don't necessary imply mobile. This method is used inside
975
- * the new $detect->is('stuff') method.
976
- *
977
- * @deprecated since version 2.6.9
978
- *
979
- * @return array All the rules + extended.
980
- */
981
- public function getMobileDetectionRulesExtended()
982
- {
983
- static $rules;
984
-
985
- if (!$rules) {
986
- // Merge all rules together.
987
- $rules = array_merge(
988
- self::$phoneDevices,
989
- self::$tabletDevices,
990
- self::$operatingSystems,
991
- self::$browsers,
992
- self::$utilities
993
- );
994
- }
995
-
996
- return $rules;
997
- }
998
-
999
- /**
1000
- * Retrieve the current set of rules.
1001
- *
1002
- * @deprecated since version 2.6.9
1003
- *
1004
- * @return array
1005
- */
1006
- public function getRules()
1007
- {
1008
- if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {
1009
- return self::getMobileDetectionRulesExtended();
1010
- } else {
1011
- return self::getMobileDetectionRules();
1012
- }
1013
- }
1014
-
1015
- /**
1016
- * Retrieve the list of mobile operating systems.
1017
- *
1018
- * @return array The list of mobile operating systems.
1019
- */
1020
- public static function getOperatingSystems()
1021
- {
1022
- return self::$operatingSystems;
1023
- }
1024
-
1025
- /**
1026
- * Check the HTTP headers for signs of mobile.
1027
- * This is the fastest mobile check possible; it's used
1028
- * inside isMobile() method.
1029
- *
1030
- * @return bool
1031
- */
1032
- public function checkHttpHeadersForMobile()
1033
- {
1034
-
1035
- foreach ($this->getMobileHeaders() as $mobileHeader => $matchType) {
1036
- if (isset($this->httpHeaders[$mobileHeader])) {
1037
- if (is_array($matchType['matches'])) {
1038
- foreach ($matchType['matches'] as $_match) {
1039
- if (strpos($this->httpHeaders[$mobileHeader], $_match) !== false) {
1040
- return true;
1041
- }
1042
- }
1043
-
1044
- return false;
1045
- } else {
1046
- return true;
1047
- }
1048
- }
1049
- }
1050
-
1051
- return false;
1052
-
1053
- }
1054
-
1055
- /**
1056
- * Magic overloading method.
1057
- *
1058
- * @method boolean is[...]()
1059
- * @param string $name
1060
- * @param array $arguments
1061
- * @return mixed
1062
- * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
1063
- */
1064
- public function __call($name, $arguments)
1065
- {
1066
- // make sure the name starts with 'is', otherwise
1067
- if (substr($name, 0, 2) !== 'is') {
1068
- throw new BadMethodCallException("No such method exists: $name");
1069
- }
1070
-
1071
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1072
-
1073
- $key = substr($name, 2);
1074
-
1075
- return $this->matchUAAgainstKey($key);
1076
- }
1077
-
1078
- /**
1079
- * Find a detection rule that matches the current User-agent.
1080
- *
1081
- * @param null $userAgent deprecated
1082
- * @return boolean
1083
- */
1084
- protected function matchDetectionRulesAgainstUA($userAgent = null)
1085
- {
1086
- // Begin general search.
1087
- foreach ($this->getRules() as $_regex) {
1088
- if (empty($_regex)) {
1089
- continue;
1090
- }
1091
-
1092
- if ($this->match($_regex, $userAgent)) {
1093
- return true;
1094
- }
1095
- }
1096
-
1097
- return false;
1098
- }
1099
-
1100
- /**
1101
- * Search for a certain key in the rules array.
1102
- * If the key is found then try to match the corresponding
1103
- * regex against the User-Agent.
1104
- *
1105
- * @param string $key
1106
- *
1107
- * @return boolean
1108
- */
1109
- protected function matchUAAgainstKey($key)
1110
- {
1111
- // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
1112
- $key = strtolower($key);
1113
- if (false === isset($this->cache[$key])) {
1114
-
1115
- // change the keys to lower case
1116
- $_rules = array_change_key_case($this->getRules());
1117
-
1118
- if (false === empty($_rules[$key])) {
1119
- $this->cache[$key] = $this->match($_rules[$key]);
1120
- }
1121
-
1122
- if (false === isset($this->cache[$key])) {
1123
- $this->cache[$key] = false;
1124
- }
1125
- }
1126
-
1127
- return $this->cache[$key];
1128
- }
1129
-
1130
- /**
1131
- * Check if the device is mobile.
1132
- * Returns true if any type of mobile device detected, including special ones
1133
- * @param null $userAgent deprecated
1134
- * @param null $httpHeaders deprecated
1135
- * @return bool
1136
- */
1137
- public function isMobile($userAgent = null, $httpHeaders = null)
1138
- {
1139
-
1140
- if ($httpHeaders) {
1141
- $this->setHttpHeaders($httpHeaders);
1142
- }
1143
-
1144
- if ($userAgent) {
1145
- $this->setUserAgent($userAgent);
1146
- }
1147
-
1148
- // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
1149
- if ($this->getUserAgent() === 'Amazon CloudFront') {
1150
- $cfHeaders = $this->getCfHeaders();
1151
- if(array_key_exists('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_MOBILE_VIEWER'] === 'true') {
1152
- return true;
1153
- }
1154
- }
1155
-
1156
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1157
-
1158
- if ($this->checkHttpHeadersForMobile()) {
1159
- return true;
1160
- } else {
1161
- return $this->matchDetectionRulesAgainstUA();
1162
- }
1163
-
1164
- }
1165
-
1166
- /**
1167
- * Check if the device is a tablet.
1168
- * Return true if any type of tablet device is detected.
1169
- *
1170
- * @param string $userAgent deprecated
1171
- * @param array $httpHeaders deprecated
1172
- * @return bool
1173
- */
1174
- public function isTablet($userAgent = null, $httpHeaders = null)
1175
- {
1176
- // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
1177
- if ($this->getUserAgent() === 'Amazon CloudFront') {
1178
- $cfHeaders = $this->getCfHeaders();
1179
- if(array_key_exists('HTTP_CLOUDFRONT_IS_TABLET_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_TABLET_VIEWER'] === 'true') {
1180
- return true;
1181
- }
1182
- }
1183
-
1184
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1185
-
1186
- foreach (self::$tabletDevices as $_regex) {
1187
- if ($this->match($_regex, $userAgent)) {
1188
- return true;
1189
- }
1190
- }
1191
-
1192
- return false;
1193
- }
1194
-
1195
- /**
1196
- * This method checks for a certain property in the
1197
- * userAgent.
1198
- * @todo: The httpHeaders part is not yet used.
1199
- *
1200
- * @param string $key
1201
- * @param string $userAgent deprecated
1202
- * @param string $httpHeaders deprecated
1203
- * @return bool|int|null
1204
- */
1205
- public function is($key, $userAgent = null, $httpHeaders = null)
1206
- {
1207
- // Set the UA and HTTP headers only if needed (eg. batch mode).
1208
- if ($httpHeaders) {
1209
- $this->setHttpHeaders($httpHeaders);
1210
- }
1211
-
1212
- if ($userAgent) {
1213
- $this->setUserAgent($userAgent);
1214
- }
1215
-
1216
- $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);
1217
-
1218
- return $this->matchUAAgainstKey($key);
1219
- }
1220
-
1221
- /**
1222
- * Some detection rules are relative (not standard),
1223
- * because of the diversity of devices, vendors and
1224
- * their conventions in representing the User-Agent or
1225
- * the HTTP headers.
1226
- *
1227
- * This method will be used to check custom regexes against
1228
- * the User-Agent string.
1229
- *
1230
- * @param $regex
1231
- * @param string $userAgent
1232
- * @return bool
1233
- *
1234
- * @todo: search in the HTTP headers too.
1235
- */
1236
- public function match($regex, $userAgent = null)
1237
- {
1238
- $match = (bool) preg_match(sprintf('#%s#is', $regex), (false === empty($userAgent) ? $userAgent : $this->userAgent), $matches);
1239
- // If positive match is found, store the results for debug.
1240
- if ($match) {
1241
- $this->matchingRegex = $regex;
1242
- $this->matchesArray = $matches;
1243
- }
1244
-
1245
- return $match;
1246
- }
1247
-
1248
- /**
1249
- * Get the properties array.
1250
- *
1251
- * @return array
1252
- */
1253
- public static function getProperties()
1254
- {
1255
- return self::$properties;
1256
- }
1257
-
1258
- /**
1259
- * Prepare the version number.
1260
- *
1261
- * @todo Remove the error supression from str_replace() call.
1262
- *
1263
- * @param string $ver The string version, like "2.6.21.2152";
1264
- *
1265
- * @return float
1266
- */
1267
- public function prepareVersionNo($ver)
1268
- {
1269
- $ver = str_replace(array('_', ' ', '/'), '.', $ver);
1270
- $arrVer = explode('.', $ver, 2);
1271
-
1272
- if (isset($arrVer[1])) {
1273
- $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
1274
- }
1275
-
1276
- return (float) implode('.', $arrVer);
1277
- }
1278
-
1279
- /**
1280
- * Check the version of the given property in the User-Agent.
1281
- * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
1282
- *
1283
- * @param string $propertyName The name of the property. See self::getProperties() array
1284
- * keys for all possible properties.
1285
- * @param string $type Either self::VERSION_TYPE_STRING to get a string value or
1286
- * self::VERSION_TYPE_FLOAT indicating a float value. This parameter
1287
- * is optional and defaults to self::VERSION_TYPE_STRING. Passing an
1288
- * invalid parameter will default to the this type as well.
1289
- *
1290
- * @return string|float The version of the property we are trying to extract.
1291
- */
1292
- public function version($propertyName, $type = self::VERSION_TYPE_STRING)
1293
- {
1294
- if (empty($propertyName)) {
1295
- return false;
1296
- }
1297
-
1298
- // set the $type to the default if we don't recognize the type
1299
- if ($type !== self::VERSION_TYPE_STRING && $type !== self::VERSION_TYPE_FLOAT) {
1300
- $type = self::VERSION_TYPE_STRING;
1301
- }
1302
-
1303
- $properties = self::getProperties();
1304
-
1305
- // Check if the property exists in the properties array.
1306
- if (true === isset($properties[$propertyName])) {
1307
-
1308
- // Prepare the pattern to be matched.
1309
- // Make sure we always deal with an array (string is converted).
1310
- $properties[$propertyName] = (array) $properties[$propertyName];
1311
-
1312
- foreach ($properties[$propertyName] as $propertyMatchString) {
1313
-
1314
- $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);
1315
-
1316
- // Identify and extract the version.
1317
- preg_match(sprintf('#%s#is', $propertyPattern), $this->userAgent, $match);
1318
-
1319
- if (false === empty($match[1])) {
1320
- $version = ($type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1]);
1321
-
1322
- return $version;
1323
- }
1324
-
1325
- }
1326
-
1327
- }
1328
-
1329
- return false;
1330
- }
1331
-
1332
- /**
1333
- * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
1334
- *
1335
- * @return string One of the self::MOBILE_GRADE_* constants.
1336
- */
1337
- public function mobileGrade()
1338
- {
1339
- $isMobile = $this->isMobile();
1340
-
1341
- if (
1342
- // Apple iOS 4-7.0 – Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3 / 5.1 / 6.1), iPad 3 (5.1 / 6.0), iPad Mini (6.1), iPad Retina (7.0), iPhone 3GS (4.3), iPhone 4 (4.3 / 5.1), iPhone 4S (5.1 / 6.0), iPhone 5 (6.0), and iPhone 5S (7.0)
1343
- $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1344
- $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1345
- $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1346
-
1347
- // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5)
1348
- // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
1349
- // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
1350
- // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
1351
- ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) ||
1352
-
1353
- // Windows Phone 7.5-8 - Tested on the HTC Surround (7.5), HTC Trophy (7.5), LG-E900 (7.5), Nokia 800 (7.8), HTC Mazaa (7.8), Nokia Lumia 520 (8), Nokia Lumia 920 (8), HTC 8x (8)
1354
- $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT) >= 7.5 ||
1355
-
1356
- // Tested on the Torch 9800 (6) and Style 9670 (6), BlackBerry® Torch 9810 (7), BlackBerry Z10 (10)
1357
- $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 6.0 ||
1358
- // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
1359
- $this->match('Playbook.*Tablet') ||
1360
-
1361
- // Palm WebOS (1.4-3.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0), HP TouchPad (3.0)
1362
- ( $this->version('webOS', self::VERSION_TYPE_FLOAT) >= 1.4 && $this->match('Palm|Pre|Pixi') ) ||
1363
- // Palm WebOS 3.0 - Tested on HP TouchPad
1364
- $this->match('hp.*TouchPad') ||
1365
-
1366
- // Firefox Mobile 18 - Tested on Android 2.3 and 4.1 devices
1367
- ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 18 ) ||
1368
-
1369
- // Chrome for Android - Tested on Android 4.0, 4.1 device
1370
- ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 4.0 ) ||
1371
-
1372
- // Skyfire 4.1 - Tested on Android 2.3 device
1373
- ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT) >= 4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) ||
1374
-
1375
- // Opera Mobile 11.5-12: Tested on Android 2.3
1376
- ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11.5 && $this->is('AndroidOS') ) ||
1377
-
1378
- // Meego 1.2 - Tested on Nokia 950 and N9
1379
- $this->is('MeeGoOS') ||
1380
-
1381
- // Tizen (pre-release) - Tested on early hardware
1382
- $this->is('Tizen') ||
1383
-
1384
- // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
1385
- // @todo: more tests here!
1386
- $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT) >= 2.0 ||
1387
-
1388
- // UC Browser - Tested on Android 2.3 device
1389
- ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) ||
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1390
 
1391
- // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
1392
- ( $this->match('Kindle Fire') ||
1393
- $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT) >= 3.0 ) ||
1394
 
1395
- // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
1396
- $this->is('AndroidOS') && $this->is('NookTablet') ||
1397
 
1398
- // Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7
1399
- $this->version('Chrome', self::VERSION_TYPE_FLOAT) >= 16 && !$isMobile ||
1400
 
1401
- // Safari Desktop 5-6 - Tested on OS X 10.7 and Windows 7
1402
- $this->version('Safari', self::VERSION_TYPE_FLOAT) >= 5.0 && !$isMobile ||
 
 
 
1403
 
1404
- // Firefox Desktop 10-18 - Tested on OS X 10.7 and Windows 7
1405
- $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 10.0 && !$isMobile ||
 
 
1406
 
1407
- // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
1408
- $this->version('IE', self::VERSION_TYPE_FLOAT) >= 7.0 && !$isMobile ||
 
 
 
 
 
 
 
 
 
 
 
 
 
1409
 
1410
- // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
1411
- $this->version('Opera', self::VERSION_TYPE_FLOAT) >= 10 && !$isMobile
1412
- ){
1413
- return self::MOBILE_GRADE_A;
1414
- }
1415
 
1416
- if (
1417
- $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 ||
1418
- $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<4.3 ||
1419
- $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT)<4.3 ||
1420
 
1421
- // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
1422
- $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 ||
1423
-
1424
- //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
1425
- ($this->version('Opera Mini', self::VERSION_TYPE_FLOAT) >= 5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT) <= 7.0 &&
1426
- ($this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 || $this->is('iOS')) ) ||
1427
-
1428
- // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
1429
- $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||
1430
-
1431
- // @todo: report this (tested on Nokia N71)
1432
- $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11 && $this->is('SymbianOS')
1433
- ){
1434
- return self::MOBILE_GRADE_B;
1435
- }
1436
-
1437
- if (
1438
- // Blackberry 4.x - Tested on the Curve 8330
1439
- $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) <= 5.0 ||
1440
- // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
1441
- $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT) <= 5.2 ||
1442
-
1443
- // Tested on original iPhone (3.1), iPhone 3 (3.2)
1444
- $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1445
- $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1446
- $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1447
-
1448
- // Internet Explorer 7 and older - Tested on Windows XP
1449
- $this->version('IE', self::VERSION_TYPE_FLOAT) <= 7.0 && !$isMobile
1450
- ){
1451
- return self::MOBILE_GRADE_C;
1452
- }
1453
 
1454
- // All older smartphone platforms and featurephones - Any device that doesn't support media queries
1455
- // will receive the basic, C grade experience.
1456
- return self::MOBILE_GRADE_C;
1457
- }
1458
- }
1
  <?php
2
  /**
3
  * Mobile Detect Library
4
+ * Motto: "Every business should have a mobile detection script to detect mobile readers"
5
+ *
6
+ * EDS_Mobile_Detect is a lightweight PHP class for detecting mobile devices (including tablets).
7
+ * It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.
8
+ *
9
+ * Homepage: http://mobiledetect.net
10
+ * GitHub: https://github.com/serbanghita/Mobile-Detect
11
+ * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md
12
+ * CONTRIBUTING: https://github.com/serbanghita/Mobile-Detect/blob/master/docs/CONTRIBUTING.md
13
+ * KNOWN LIMITATIONS: https://github.com/serbanghita/Mobile-Detect/blob/master/docs/KNOWN_LIMITATIONS.md
14
+ * EXAMPLES: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples
15
+ *
16
+ * @license https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE
17
+ * @author Serban Ghita <serbanghita@gmail.com>
18
+ * @author Nick Ilyin <nick.ilyin@gmail.com>
19
+ * Original author: Victor Stanciu <vic.stanciu@gmail.com>
20
+ *
21
+ * @version 2.8.39
22
+ *
23
+ * Auto-generated isXXXX() magic methods.
24
+ * php -a examples/dump_magic_methods.php
25
+ *
26
+ * @method bool isiPhone()
27
+ * @method bool isBlackBerry()
28
+ * @method bool isPixel()
29
+ * @method bool isHTC()
30
+ * @method bool isNexus()
31
+ * @method bool isDell()
32
+ * @method bool isMotorola()
33
+ * @method bool isSamsung()
34
+ * @method bool isLG()
35
+ * @method bool isSony()
36
+ * @method bool isAsus()
37
+ * @method bool isXiaomi()
38
+ * @method bool isNokiaLumia()
39
+ * @method bool isMicromax()
40
+ * @method bool isPalm()
41
+ * @method bool isVertu()
42
+ * @method bool isPantech()
43
+ * @method bool isFly()
44
+ * @method bool isWiko()
45
+ * @method bool isiMobile()
46
+ * @method bool isSimValley()
47
+ * @method bool isWolfgang()
48
+ * @method bool isAlcatel()
49
+ * @method bool isNintendo()
50
+ * @method bool isAmoi()
51
+ * @method bool isINQ()
52
+ * @method bool isOnePlus()
53
+ * @method bool isGenericPhone()
54
+ * @method bool isiPad()
55
+ * @method bool isNexusTablet()
56
+ * @method bool isGoogleTablet()
57
+ * @method bool isSamsungTablet()
58
+ * @method bool isKindle()
59
+ * @method bool isSurfaceTablet()
60
+ * @method bool isHPTablet()
61
+ * @method bool isAsusTablet()
62
+ * @method bool isBlackBerryTablet()
63
+ * @method bool isHTCtablet()
64
+ * @method bool isMotorolaTablet()
65
+ * @method bool isNookTablet()
66
+ * @method bool isAcerTablet()
67
+ * @method bool isToshibaTablet()
68
+ * @method bool isLGTablet()
69
+ * @method bool isFujitsuTablet()
70
+ * @method bool isPrestigioTablet()
71
+ * @method bool isLenovoTablet()
72
+ * @method bool isDellTablet()
73
+ * @method bool isYarvikTablet()
74
+ * @method bool isMedionTablet()
75
+ * @method bool isArnovaTablet()
76
+ * @method bool isIntensoTablet()
77
+ * @method bool isIRUTablet()
78
+ * @method bool isMegafonTablet()
79
+ * @method bool isEbodaTablet()
80
+ * @method bool isAllViewTablet()
81
+ * @method bool isArchosTablet()
82
+ * @method bool isAinolTablet()
83
+ * @method bool isNokiaLumiaTablet()
84
+ * @method bool isSonyTablet()
85
+ * @method bool isPhilipsTablet()
86
+ * @method bool isCubeTablet()
87
+ * @method bool isCobyTablet()
88
+ * @method bool isMIDTablet()
89
+ * @method bool isMSITablet()
90
+ * @method bool isSMiTTablet()
91
+ * @method bool isRockChipTablet()
92
+ * @method bool isFlyTablet()
93
+ * @method bool isbqTablet()
94
+ * @method bool isHuaweiTablet()
95
+ * @method bool isNecTablet()
96
+ * @method bool isPantechTablet()
97
+ * @method bool isBronchoTablet()
98
+ * @method bool isVersusTablet()
99
+ * @method bool isZyncTablet()
100
+ * @method bool isPositivoTablet()
101
+ * @method bool isNabiTablet()
102
+ * @method bool isKoboTablet()
103
+ * @method bool isDanewTablet()
104
+ * @method bool isTexetTablet()
105
+ * @method bool isPlaystationTablet()
106
+ * @method bool isTrekstorTablet()
107
+ * @method bool isPyleAudioTablet()
108
+ * @method bool isAdvanTablet()
109
+ * @method bool isDanyTechTablet()
110
+ * @method bool isGalapadTablet()
111
+ * @method bool isMicromaxTablet()
112
+ * @method bool isKarbonnTablet()
113
+ * @method bool isAllFineTablet()
114
+ * @method bool isPROSCANTablet()
115
+ * @method bool isYONESTablet()
116
+ * @method bool isChangJiaTablet()
117
+ * @method bool isGUTablet()
118
+ * @method bool isPointOfViewTablet()
119
+ * @method bool isOvermaxTablet()
120
+ * @method bool isHCLTablet()
121
+ * @method bool isDPSTablet()
122
+ * @method bool isVistureTablet()
123
+ * @method bool isCrestaTablet()
124
+ * @method bool isMediatekTablet()
125
+ * @method bool isConcordeTablet()
126
+ * @method bool isGoCleverTablet()
127
+ * @method bool isModecomTablet()
128
+ * @method bool isVoninoTablet()
129
+ * @method bool isECSTablet()
130
+ * @method bool isStorexTablet()
131
+ * @method bool isVodafoneTablet()
132
+ * @method bool isEssentielBTablet()
133
+ * @method bool isRossMoorTablet()
134
+ * @method bool isiMobileTablet()
135
+ * @method bool isTolinoTablet()
136
+ * @method bool isAudioSonicTablet()
137
+ * @method bool isAMPETablet()
138
+ * @method bool isSkkTablet()
139
+ * @method bool isTecnoTablet()
140
+ * @method bool isJXDTablet()
141
+ * @method bool isiJoyTablet()
142
+ * @method bool isFX2Tablet()
143
+ * @method bool isXoroTablet()
144
+ * @method bool isViewsonicTablet()
145
+ * @method bool isVerizonTablet()
146
+ * @method bool isOdysTablet()
147
+ * @method bool isCaptivaTablet()
148
+ * @method bool isIconbitTablet()
149
+ * @method bool isTeclastTablet()
150
+ * @method bool isOndaTablet()
151
+ * @method bool isJaytechTablet()
152
+ * @method bool isBlaupunktTablet()
153
+ * @method bool isDigmaTablet()
154
+ * @method bool isEvolioTablet()
155
+ * @method bool isLavaTablet()
156
+ * @method bool isAocTablet()
157
+ * @method bool isMpmanTablet()
158
+ * @method bool isCelkonTablet()
159
+ * @method bool isWolderTablet()
160
+ * @method bool isMediacomTablet()
161
+ * @method bool isMiTablet()
162
+ * @method bool isNibiruTablet()
163
+ * @method bool isNexoTablet()
164
+ * @method bool isLeaderTablet()
165
+ * @method bool isUbislateTablet()
166
+ * @method bool isPocketBookTablet()
167
+ * @method bool isKocasoTablet()
168
+ * @method bool isHisenseTablet()
169
+ * @method bool isHudl()
170
+ * @method bool isTelstraTablet()
171
+ * @method bool isGenericTablet()
172
+ * @method bool isAndroidOS()
173
+ * @method bool isBlackBerryOS()
174
+ * @method bool isPalmOS()
175
+ * @method bool isSymbianOS()
176
+ * @method bool isWindowsMobileOS()
177
+ * @method bool isWindowsPhoneOS()
178
+ * @method bool isiOS()
179
+ * @method bool isiPadOS()
180
+ * @method bool isSailfishOS()
181
+ * @method bool isMeeGoOS()
182
+ * @method bool isMaemoOS()
183
+ * @method bool isJavaOS()
184
+ * @method bool iswebOS()
185
+ * @method bool isbadaOS()
186
+ * @method bool isBREWOS()
187
+ * @method bool isChrome()
188
+ * @method bool isDolfin()
189
+ * @method bool isOpera()
190
+ * @method bool isSkyfire()
191
+ * @method bool isEdge()
192
+ * @method bool isIE()
193
+ * @method bool isFirefox()
194
+ * @method bool isBolt()
195
+ * @method bool isTeaShark()
196
+ * @method bool isBlazer()
197
+ * @method bool isSafari()
198
+ * @method bool isWeChat()
199
+ * @method bool isUCBrowser()
200
+ * @method bool isbaiduboxapp()
201
+ * @method bool isbaidubrowser()
202
+ * @method bool isDiigoBrowser()
203
+ * @method bool isMercury()
204
+ * @method bool isObigoBrowser()
205
+ * @method bool isNetFront()
206
+ * @method bool isGenericBrowser()
207
+ * @method bool isPaleMoon()
208
+ * @method bool isBot()
209
+ * @method bool isMobileBot()
210
+ * @method bool isDesktopMode()
211
+ * @method bool isTV()
212
+ * @method bool isWebKit()
213
+ * @method bool isConsole()
214
+ * @method bool isWatch()
215
+
216
+ */
217
  class EDS_Mobile_Detect
218
  {
219
+ /**
220
+ * Mobile detection type.
221
+ *
222
+ * @deprecated since version 2.6.9
223
+ */
224
+ const DETECTION_TYPE_MOBILE = 'mobile';
225
+
226
+ /**
227
+ * Extended detection type.
228
+ *
229
+ * @deprecated since version 2.6.9
230
+ */
231
+ const DETECTION_TYPE_EXTENDED = 'extended';
232
+
233
+ /**
234
+ * A frequently used regular expression to extract version #s.
235
+ *
236
+ * @deprecated since version 2.6.9
237
+ */
238
+ const VER = '([\w._\+]+)';
239
+
240
+ /**
241
+ * Top-level device.
242
+ */
243
+ const MOBILE_GRADE_A = 'A';
244
+
245
+ /**
246
+ * Mid-level device.
247
+ */
248
+ const MOBILE_GRADE_B = 'B';
249
+
250
+ /**
251
+ * Low-level device.
252
+ */
253
+ const MOBILE_GRADE_C = 'C';
254
+
255
+ /**
256
+ * Stores the version number of the current release.
257
+ */
258
+ const VERSION = '2.8.39';
259
+
260
+ /**
261
+ * A type for the version() method indicating a string return value.
262
+ */
263
+ const VERSION_TYPE_STRING = 'text';
264
+
265
+ /**
266
+ * A type for the version() method indicating a float return value.
267
+ */
268
+ const VERSION_TYPE_FLOAT = 'float';
269
+
270
+ /**
271
+ * A cache for resolved matches
272
+ * @var array
273
+ */
274
+ protected $cache = array();
275
+
276
+ /**
277
+ * The User-Agent HTTP header is stored in here.
278
+ * @var string
279
+ */
280
+ protected $userAgent = null;
281
+
282
+ /**
283
+ * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
284
+ * @var array
285
+ */
286
+ protected $httpHeaders = array();
287
+
288
+ /**
289
+ * CloudFront headers. E.g. CloudFront-Is-Desktop-Viewer, CloudFront-Is-Mobile-Viewer & CloudFront-Is-Tablet-Viewer.
290
+ * @var array
291
+ */
292
+ protected $cloudfrontHeaders = array();
293
+
294
+ /**
295
+ * The matching Regex.
296
+ * This is good for debug.
297
+ * @var string
298
+ */
299
+ protected $matchingRegex = null;
300
+
301
+ /**
302
+ * The matches extracted from the regex expression.
303
+ * This is good for debug.
304
+ *
305
+ * @var string
306
+ */
307
+ protected $matchesArray = null;
308
+
309
+ /**
310
+ * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
311
+ *
312
+ * @deprecated since version 2.6.9
313
+ *
314
+ * @var string
315
+ */
316
+ protected $detectionType = self::DETECTION_TYPE_MOBILE;
317
+
318
+ /**
319
+ * HTTP headers that trigger the 'isMobile' detection
320
+ * to be true.
321
+ *
322
+ * @var array
323
+ */
324
+ protected static $mobileHeaders = array(
325
+
326
+ 'HTTP_ACCEPT' => array('matches' => array(
327
+ // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
328
+ 'application/x-obml2d',
329
+ // BlackBerry devices.
330
+ 'application/vnd.rim.html',
331
+ 'text/vnd.wap.wml',
332
+ 'application/vnd.wap.xhtml+xml'
333
+ )),
334
+ 'HTTP_X_WAP_PROFILE' => null,
335
+ 'HTTP_X_WAP_CLIENTID' => null,
336
+ 'HTTP_WAP_CONNECTION' => null,
337
+ 'HTTP_PROFILE' => null,
338
+ // Reported by Opera on Nokia devices (eg. C3).
339
+ 'HTTP_X_OPERAMINI_PHONE_UA' => null,
340
+ 'HTTP_X_NOKIA_GATEWAY_ID' => null,
341
+ 'HTTP_X_ORANGE_ID' => null,
342
+ 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
343
+ 'HTTP_X_HUAWEI_USERID' => null,
344
+ // Reported by Windows Smartphones.
345
+ 'HTTP_UA_OS' => null,
346
+ // Reported by Verizon, Vodafone proxy system.
347
+ 'HTTP_X_MOBILE_GATEWAY' => null,
348
+ // Seen this on HTC Sensation. SensationXE_Beats_Z715e.
349
+ 'HTTP_X_ATT_DEVICEID' => null,
350
+ // Seen this on a HTC.
351
+ 'HTTP_UA_CPU' => array('matches' => array('ARM')),
352
+ );
353
+
354
+ /**
355
+ * List of mobile devices (phones).
356
+ *
357
+ * @var array
358
+ */
359
+ protected static $phoneDevices = array(
360
+ 'iPhone' => '\biPhone\b|\biPod\b', // |\biTunes
361
+ 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+|\b(BBA100|BBB100|BBD100|BBE100|BBF100|STH100)\b-[0-9]+',
362
+ 'Pixel' => '; \bPixel\b',
363
+ 'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m|Android [0-9.]+; Pixel',
364
+ 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 5X|Nexus 6',
365
+ // @todo: Is 'Dell Streak' a tablet or a phone? ;)
366
+ 'Dell' => 'Dell[;]? (Streak|Aero|Venue|Venue Pro|Flash|Smoke|Mini 3iX)|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b',
367
+ 'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\bMoto E\b|XT1068|XT1092|XT1052',
368
+ 'Samsung' => '\bSamsung\b|SM-G950F|SM-G955F|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F|SM-G920F|SM-G920V|SM-G930F|SM-N910C|SM-A310F|GT-I9190|SM-J500FN|SM-G903F|SM-J330F|SM-G610F|SM-G981B|SM-G892A|SM-A530F|SM-G988N',
369
+ 'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323|M257)|LM-G710',
370
+ 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533|SOV34|601SO|F8332',
371
+ 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile|ASUS_Z01QD',
372
+ 'Xiaomi' => '^(?!.*\bx11\b).*xiaomi.*$|POCOPHONE F1|\bMI\b 8|\bMi\b 10|Redmi Note 9S|Redmi 5A|Redmi Note 5A Prime|Redmi Note 7 Pro|N2G47H|M2001J2G|M2001J2I|M1805E10A|M2004J11G|M1902F1G|M2002J9G|M2004J19G|M2003J6A1G|M2012K11C',
373
+ 'NokiaLumia' => 'Lumia [0-9]{3,4}',
374
+ // http://www.micromaxinfo.com/mobiles/smartphones
375
+ // Added because the codes might conflict with Acer Tablets.
376
+ 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b',
377
+ // @todo Complete the regex.
378
+ 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ;
379
+ 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
380
+ // http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
381
+ // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
382
+ 'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790',
383
+ // http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
384
+ 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
385
+ // http://fr.wikomobile.com
386
+ 'Wiko' => 'KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM',
387
+ 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)',
388
+ // Added simvalley mobile just for fun. They have some interesting devices.
389
+ // http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
390
+ 'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b',
391
+ // Wolfgang - a brand that is sold by Aldi supermarkets.
392
+ // http://www.wolfgangmobile.com/
393
+ 'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q',
394
+ 'Alcatel' => 'Alcatel',
395
+ 'Nintendo' => 'Nintendo (3DS|Switch)',
396
+ // http://en.wikipedia.org/wiki/Amoi
397
+ 'Amoi' => 'Amoi',
398
+ // http://en.wikipedia.org/wiki/INQ
399
+ 'INQ' => 'INQ',
400
+ 'OnePlus' => 'ONEPLUS',
401
+ // @Tapatalk is a mobile app; http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039
402
+ 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser',
403
+ );
404
+
405
+ /**
406
+ * List of tablet devices.
407
+ *
408
+ * @var array
409
+ */
410
+ protected static $tabletDevices = array(
411
+ // @todo: check for mobile friendly emails topic.
412
+ 'iPad' => 'iPad|iPad.*Mobile',
413
+ // Removed |^.*Android.*Nexus(?!(?:Mobile).)*$
414
+ // @see #442
415
+ // @todo Merge NexusTablet into GoogleTablet.
416
+ 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)',
417
+ // https://en.wikipedia.org/wiki/Pixel_C
418
+ 'GoogleTablet' => 'Android.*Pixel C',
419
+ 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-T116BU|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y?|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587|SM-P350|SM-P555M|SM-P355M|SM-T113NU|SM-T815Y|SM-T585|SM-T285|SM-T825|SM-W708|SM-T835|SM-T830|SM-T837V|SM-T720|SM-T510|SM-T387V|SM-P610|SM-T290|SM-T515|SM-T590|SM-T595|SM-T725|SM-T817P|SM-P585N0|SM-T395|SM-T295|SM-T865|SM-P610N|SM-P615|SM-T970|SM-T380|SM-T5950|SM-T905|SM-T231|SM-T500|SM-T860|SM-T536', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone.
420
+ // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
421
+ 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI|KFFOWI|KFGIWI|KFMEWI)\b|Android.*Silk/[0-9.]+ like Chrome/[0-9.]+ (?!Mobile)',
422
+ // Only the Surface tablets with Windows RT are considered mobile.
423
+ // http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
424
+ 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)',
425
+ // http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
426
+ 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10',
427
+ // Watch out for PadFone, see #132.
428
+ // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/
429
+ 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K01A | K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z|\bP027\b|\bP024\b|\bP00C\b',
430
+ 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
431
+ 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410',
432
+ 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
433
+ 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
434
+ // http://www.acer.ro/ac/ro/RO/content/drivers
435
+ // http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
436
+ // http://us.acer.com/ac/en/US/content/group/tablets
437
+ // http://www.acer.de/ac/de/DE/content/models/tablets/
438
+ // Can conflict with Micromax and Motorola phones codes.
439
+ 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\b|W3-810|\bA3-A10\b|\bA3-A11\b|\bA3-A20\b|\bA3-A30|A3-A40',
440
+ // http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
441
+ // http://us.toshiba.com/tablets/tablet-finder
442
+ // http://www.toshiba.co.jp/regza/tablet/
443
+ 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
444
+ // http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
445
+ // http://www.lg.com/us/tablets
446
+ 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b',
447
+ 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
448
+ // Prestigio Tablets http://www.prestigio.com/support
449
+ 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002',
450
+ // http://support.lenovo.com/en_GB/downloads/default.page?#
451
+ 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-850M|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)|TB-X103F|TB-X304X|TB-X304F|TB-X304L|TB-X505F|TB-X505L|TB-X505X|TB-X605F|TB-X605L|TB-8703F|TB-8703X|TB-8703N|TB-8704N|TB-8704F|TB-8704X|TB-8704V|TB-7304F|TB-7304I|TB-7304X|Tab2A7-10F|Tab2A7-20F|TB2-X30L|YT3-X50L|YT3-X50F|YT3-X50M|YT-X705F|YT-X703F|YT-X703L|YT-X705L|YT-X705X|TB2-X30F|TB2-X30L|TB2-X30M|A2107A-F|A2107A-H|TB3-730F|TB3-730M|TB3-730X|TB-7504F|TB-7504X|TB-X704F|TB-X104F|TB3-X70F|TB-X705F|TB-8504F|TB3-X70L|TB3-710F|TB-X704L|TB-J606F|TB-X606F|TB-X306X',
452
+ // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets
453
+ 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7',
454
+ 'XiaomiTablet' => '21051182G',
455
+ // http://www.yarvik.com/en/matrix/tablets/
456
+ 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b',
457
+ 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
458
+ 'ArnovaTablet' => '97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2',
459
+ // http://www.intenso.de/kategorie_en.php?kategorie=33
460
+ // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate
461
+ 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004',
462
+ // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
463
+ 'IRUTablet' => 'M702pro',
464
+ 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
465
+ // http://www.e-boda.ro/tablete-pc.html
466
+ 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
467
+ // http://www.allview.ro/produse/droseries/lista-tablete-pc/
468
+ 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
469
+ // http://wiki.archosfans.com/index.php?title=Main_Page
470
+ // @note Rewrite the regex format after we add more UAs.
471
+ 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|Archos5|\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|c|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\b',
472
+ // http://www.ainol.com/plugin.php?identifier=ainol&module=product
473
+ 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
474
+ 'NokiaLumiaTablet' => 'Lumia 2520',
475
+ // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
476
+ // Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
477
+ // http://www.sony.jp/support/tablet/
478
+ 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP641|SGP612|SOT31|SGP771|SGP611|SGP612|SGP712',
479
+ // http://www.support.philips.com/support/catalog/worldproducts.jsp?userLanguage=en&userCountry=cn&categoryid=3G_LTE_TABLET_SU_CN_CARE&title=3G%20tablets%20/%20LTE%20range&_dyncharset=UTF-8
480
+ 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b',
481
+ // db + http://www.cube-tablet.com/buy-products.html
482
+ 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
483
+ // http://www.cobyusa.com/?p=pcat&pcat_id=3001
484
+ 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
485
+ // http://www.match.net.cn/products.asp
486
+ 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10',
487
+ // http://www.msi.com/support
488
+ // @todo Research the Windows Tablets.
489
+ 'MSITablet' => 'MSI \b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\b',
490
+ // @todo http://www.kyoceramobile.com/support/drivers/
491
+ // 'KyoceraTablet' => null,
492
+ // @todo http://intexuae.com/index.php/category/mobile-devices/tablets-products/
493
+ // 'IntextTablet' => null,
494
+ // http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
495
+ // http://www.imp3.net/14/show.php?itemid=20454
496
+ 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
497
+ // http://www.rock-chips.com/index.php?do=prod&pid=2
498
+ 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
499
+ // http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
500
+ 'FlyTablet' => 'IQ310|Fly Vision',
501
+ // http://www.bqreaders.com/gb/tablets-prices-sale.html
502
+ 'bqTablet' => 'Android.*(bq)?.*\b(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris ([E|M]10|M8))\b|Maxwell.*Lite|Maxwell.*Plus',
503
+ // http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
504
+ // http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
505
+ 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim|M2-A01L|BAH-L09|BAH-W09|AGS-L09|CMR-AL19|KOB2-L09',
506
+ // Nec or Medias Tab
507
+ 'NecTablet' => '\bN-06D|\bN-08D',
508
+ // Pantech Tablets: http://www.pantechusa.com/phones/
509
+ 'PantechTablet' => 'Pantech.*P4100',
510
+ // Broncho Tablets: http://www.broncho.cn/ (hard to find)
511
+ 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
512
+ // http://versusuk.com/support.html
513
+ 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
514
+ // http://www.zync.in/index.php/our-products/tablet-phablets
515
+ 'ZyncTablet' => 'z1000|Z99 2G|z930|z990|z909|Z919|z900', // Removed "z999" because of https://github.com/serbanghita/Mobile-Detect/issues/717
516
+ // http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
517
+ 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
518
+ // https://www.nabitablet.com/
519
+ 'NabiTablet' => 'Android.*\bNabi',
520
+ 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
521
+ // French Danew Tablets http://www.danew.com/produits-tablette.php
522
+ 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
523
+ // Texet Tablets and Readers http://www.texet.ru/tablet/
524
+ 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE',
525
+ // Avoid detecting 'PLAYSTATION 3' as mobile.
526
+ 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
527
+ // http://www.trekstor.de/surftabs.html
528
+ 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab',
529
+ // http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets
530
+ 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
531
+ // http://www.advandigital.com/index.php?link=content-product&jns=JP001
532
+ // because of the short codenames we have to include whitespaces to reduce the possible conflicts.
533
+ 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ',
534
+ // http://www.danytech.com/category/tablet-pc
535
+ 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1',
536
+ // http://www.galapad.net/product.html ; https://github.com/serbanghita/Mobile-Detect/issues/761
537
+ 'GalapadTablet' => 'Android [0-9.]+; [a-z-]+; \bG1\b',
538
+ // http://www.micromaxinfo.com/tablet/funbook
539
+ 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
540
+ // http://www.karbonnmobiles.com/products_tablet.php
541
+ 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
542
+ // http://www.myallfine.com/Products.asp
543
+ 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
544
+ // http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
545
+ 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b',
546
+ // http://www.yonesnav.com/products/products.php
547
+ 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
548
+ // http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
549
+ // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
550
+ 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503',
551
+ // http://www.gloryunion.cn/products.asp
552
+ // http://www.allwinnertech.com/en/apply/mobile.html
553
+ // http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
554
+ // @todo: Softwiner tablets?
555
+ // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
556
+ 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G
557
+ // http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
558
+ 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10',
559
+ // http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
560
+ // @todo: add more tests.
561
+ 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)|Qualcore 1027',
562
+ // http://hclmetablet.com/India/index.php
563
+ 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync',
564
+ // http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
565
+ 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
566
+ // http://www.visture.com/index.asp
567
+ 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
568
+ // http://www.mijncresta.nl/tablet
569
+ 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
570
+ // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309
571
+ 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
572
+ // Concorde tab
573
+ 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
574
+ // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/
575
+ 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042',
576
+ // Modecom Tablets - http://www.modecom.eu/tablets/portal/
577
+ 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003',
578
+ // Vonino Tablets
579
+ 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b',
580
+ // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0
581
+ 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
582
+ // Storex Tablets - http://storex.fr/espace_client/support.html
583
+ // @note: no need to add all the tablet codes since they are guided by the first regex.
584
+ 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
585
+ // Generic Vodafone tablets.
586
+ 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497|VFD 1400',
587
+ // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb
588
+ // Aka: http://www.essentielb.fr/
589
+ 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
590
+ // Ross & Moor - http://ross-moor.ru/
591
+ 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
592
+ // i-mobile http://product.i-mobilephone.com/Mobile_Device
593
+ 'iMobileTablet' => 'i-mobile i-note',
594
+ // http://www.tolino.de/de/vergleichen/
595
+ 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
596
+ // AudioSonic - a Kmart brand
597
+ // http://www.kmart.com.au/webapp/wcs/stores/servlet/Search?langId=-1&storeId=10701&catalogId=10001&categoryId=193001&pageSize=72&currentPage=1&searchCategory=193001%2b4294965664&sortBy=p_MaxPrice%7c1
598
+ 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
599
+ // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/
600
+ // @todo: add them gradually to avoid conflicts.
601
+ 'AMPETablet' => 'Android.* A78 ',
602
+ // Skk Mobile - http://skkmobile.com.ph/product_tablets.php
603
+ 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
604
+ // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1
605
+ 'TecnoTablet' => 'TECNO P9|TECNO DP8D',
606
+ // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3
607
+ 'JXDTablet' => 'Android.* \b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b',
608
+ // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/
609
+ 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)',
610
+ // http://www.intracon.eu/tablet
611
+ 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
612
+ // http://www.xoro.de/produkte/
613
+ // @note: Might be the same brand with 'Simply tablets'
614
+ 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151',
615
+ // http://www1.viewsonic.com/products/computing/tablets/
616
+ 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
617
+ // https://www.verizonwireless.com/tablets/verizon/
618
+ 'VerizonTablet' => 'QTAQZ3|QTAIR7|QTAQTZ3|QTASUN1|QTASUN2|QTAXIA1',
619
+ // http://www.odys.de/web/internet-tablet_en.html
620
+ 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10',
621
+ // http://www.captiva-power.de/products.html#tablets-en
622
+ 'CaptivaTablet' => 'CAPTIVA PAD',
623
+ // IconBIT - http://www.iconbit.com/products/tablets/
624
+ 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S',
625
+ // http://www.teclast.com/topic.php?channelID=70&topicID=140&pid=63
626
+ 'TeclastTablet' => 'T98 4G|\bP80\b|\bX90HD\b|X98 Air|X98 Air 3G|\bX89\b|P80 3G|\bX80h\b|P98 Air|\bX89HD\b|P98 3G|\bP90HD\b|P89 3G|X98 3G|\bP70h\b|P79HD 3G|G18d 3G|\bP79HD\b|\bP89s\b|\bA88\b|\bP10HD\b|\bP19HD\b|G18 3G|\bP78HD\b|\bA78\b|\bP75\b|G17s 3G|G17h 3G|\bP85t\b|\bP90\b|\bP11\b|\bP98t\b|\bP98HD\b|\bG18d\b|\bP85s\b|\bP11HD\b|\bP88s\b|\bA80HD\b|\bA80se\b|\bA10h\b|\bP89\b|\bP78s\b|\bG18\b|\bP85\b|\bA70h\b|\bA70\b|\bG17\b|\bP18\b|\bA80s\b|\bA11s\b|\bP88HD\b|\bA80h\b|\bP76s\b|\bP76h\b|\bP98\b|\bA10HD\b|\bP78\b|\bP88\b|\bA11\b|\bA10t\b|\bP76a\b|\bP76t\b|\bP76e\b|\bP85HD\b|\bP85a\b|\bP86\b|\bP75HD\b|\bP76v\b|\bA12\b|\bP75a\b|\bA15\b|\bP76Ti\b|\bP81HD\b|\bA10\b|\bT760VE\b|\bT720HD\b|\bP76\b|\bP73\b|\bP71\b|\bP72\b|\bT720SE\b|\bC520Ti\b|\bT760\b|\bT720VE\b|T720-3GE|T720-WiFi',
627
+ // Onda - http://www.onda-tablet.com/buy-android-onda.html?dir=desc&limit=all&order=price
628
+ 'OndaTablet' => '\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\b[\s]+|V10 \b4G\b',
629
+ 'JaytechTablet' => 'TPC-PA762',
630
+ 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010',
631
+ // http://www.digma.ru/support/download/
632
+ // @todo: Ebooks also (if requested)
633
+ 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b',
634
+ // http://www.evolioshop.com/ro/tablete-pc.html
635
+ // http://www.evolio.ro/support/downloads_static.html?cat=2
636
+ // @todo: Research some more
637
+ 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b',
638
+ // @todo http://www.lavamobiles.com/tablets-data-cards
639
+ 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY|\bE-TAB\b',
640
+ // http://www.breezetablet.com/
641
+ 'AocTablet' => 'MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712',
642
+ // http://www.mpmaneurope.com/en/products/internet-tablets-14/android-tablets-14/
643
+ 'MpmanTablet' => 'MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\bMPG7\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010',
644
+ // https://www.celkonmobiles.com/?_a=categoryphones&sid=2
645
+ 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b',
646
+ // http://www.wolderelectronics.com/productos/manuales-y-guias-rapidas/categoria-2-miTab
647
+ 'WolderTablet' => 'miTab \b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\b',
648
+ 'MediacomTablet' => 'M-MPI10C3G|M-SP10EG|M-SP10EGP|M-SP10HXAH|M-SP7HXAH|M-SP10HXBH|M-SP8HXAH|M-SP8MXA',
649
+ // http://www.mi.com/en
650
+ 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b',
651
+ // http://www.nbru.cn/index.html
652
+ 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One',
653
+ // http://navroad.com/products/produkty/tablety/
654
+ // http://navroad.com/products/produkty/tablety/
655
+ 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI',
656
+ // http://leader-online.com/new_site/product-category/tablets/
657
+ // http://www.leader-online.net.au/List/Tablet
658
+ 'LeaderTablet' => 'TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100',
659
+ // http://www.datawind.com/ubislate/
660
+ 'UbislateTablet' => 'UbiSlate[\s]?7C',
661
+ // http://www.pocketbook-int.com/ru/support
662
+ 'PocketBookTablet' => 'Pocketbook',
663
+ // http://www.kocaso.com/product_tablet.html
664
+ 'KocasoTablet' => '\b(TB-1207)\b',
665
+ // http://global.hisense.com/product/asia/tablet/Sero7/201412/t20141215_91832.htm
666
+ 'HisenseTablet' => '\b(F5281|E2371)\b',
667
+ // http://www.tesco.com/direct/hudl/
668
+ 'Hudl' => 'Hudl HT7S3|Hudl 2',
669
+ // http://www.telstra.com.au/home-phone/thub-2/
670
+ 'TelstraTablet' => 'T-Hub2',
671
+ 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b|\bQTAQZ3\b|WVT101|TM1088|KT107'
672
+ );
673
+
674
+ /**
675
+ * List of mobile Operating Systems.
676
+ *
677
+ * @var array
678
+ */
679
+ protected static $operatingSystems = array(
680
+ 'AndroidOS' => 'Android',
681
+ 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
682
+ 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
683
+ 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
684
+ // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
685
+ 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Windows Mobile|Windows Phone [0-9.]+|WCE;',
686
+ // @reference: http://en.wikipedia.org/wiki/Windows_Phone
687
+ // http://wifeng.cn/?r=blog&a=view&id=106
688
+ // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
689
+ // http://msdn.microsoft.com/library/ms537503.aspx
690
+ // https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
691
+ 'WindowsPhoneOS' => 'Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;',
692
+ 'iOS' => '\biPhone.*Mobile|\biPod|\biPad|AppleCoreMedia',
693
+ // https://en.wikipedia.org/wiki/IPadOS
694
+ 'iPadOS' => 'CPU OS 13',
695
+ // @reference https://en.m.wikipedia.org/wiki/Sailfish_OS
696
+ // https://sailfishos.org/
697
+ 'SailfishOS' => 'Sailfish',
698
+ // http://en.wikipedia.org/wiki/MeeGo
699
+ // @todo: research MeeGo in UAs
700
+ 'MeeGoOS' => 'MeeGo',
701
+ // http://en.wikipedia.org/wiki/Maemo
702
+ // @todo: research Maemo in UAs
703
+ 'MaemoOS' => 'Maemo',
704
+ 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
705
+ 'webOS' => 'webOS|hpwOS',
706
+ 'badaOS' => '\bBada\b',
707
+ 'BREWOS' => 'BREW',
708
+ );
709
+
710
+ /**
711
+ * List of mobile User Agents.
712
+ *
713
+ * IMPORTANT: This is a list of only mobile browsers.
714
+ * Mobile Detect 2.x supports only mobile browsers,
715
+ * it was never designed to detect all browsers.
716
+ * The change will come in 2017 in the 3.x release for PHP7.
717
+ *
718
+ * @var array
719
+ */
720
+ protected static $browsers = array(
721
+ //'Vivaldi' => 'Vivaldi',
722
+ // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
723
+ 'Chrome' => '\bCrMo\b|CriOS.*Mobile|Android.*Chrome/[.0-9]* Mobile',
724
+ 'Dolfin' => '\bDolfin\b',
725
+ 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+$|Coast/[0-9.]+',
726
+ 'Skyfire' => 'Skyfire',
727
+ // Added "Edge on iOS" https://github.com/serbanghita/Mobile-Detect/issues/764
728
+ 'Edge' => 'EdgiOS.*Mobile|Mobile Safari/[.0-9]* Edge',
729
+ 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
730
+ 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS.*Mobile',
731
+ 'Bolt' => 'bolt',
732
+ 'TeaShark' => 'teashark',
733
+ 'Blazer' => 'Blazer',
734
+ // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
735
+ // Excluded "Edge on iOS" https://github.com/serbanghita/Mobile-Detect/issues/764
736
+ 'Safari' => 'Version((?!\bEdgiOS\b).)*Mobile.*Safari|Safari.*Mobile|MobileSafari',
737
+ // http://en.wikipedia.org/wiki/Midori_(web_browser)
738
+ //'Midori' => 'midori',
739
+ //'Tizen' => 'Tizen',
740
+ 'WeChat' => '\bMicroMessenger\b',
741
+ 'UCBrowser' => 'UC.*Browser|UCWEB',
742
+ 'baiduboxapp' => 'baiduboxapp',
743
+ 'baidubrowser' => 'baidubrowser',
744
+ // https://github.com/serbanghita/Mobile-Detect/issues/7
745
+ 'DiigoBrowser' => 'DiigoBrowser',
746
+ // http://www.puffinbrowser.com/index.php
747
+ // https://github.com/serbanghita/Mobile-Detect/issues/752
748
+ // 'Puffin' => 'Puffin',
749
+ // http://mercury-browser.com/index.html
750
+ 'Mercury' => '\bMercury\b',
751
+ // http://en.wikipedia.org/wiki/Obigo_Browser
752
+ 'ObigoBrowser' => 'Obigo',
753
+ // http://en.wikipedia.org/wiki/NetFront
754
+ 'NetFront' => 'NF-Browser',
755
+ // @reference: http://en.wikipedia.org/wiki/Minimo
756
+ // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
757
+ 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger',
758
+ // @reference: https://en.wikipedia.org/wiki/Pale_Moon_(web_browser)
759
+ 'PaleMoon' => 'Android.*PaleMoon|Mobile.*PaleMoon',
760
+ );
761
+
762
+ /**
763
+ * Utilities.
764
+ *
765
+ * @var array
766
+ */
767
+ protected static $utilities = array(
768
+ // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
769
+ // http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
770
+ // https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
771
+ // https://developers.facebook.com/docs/sharing/webmasters/crawler/
772
+ 'Bot' => 'Googlebot|facebookexternalhit|Google-AMPHTML|s~amp-validator|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom|contentkingapp|AspiegelBot',
773
+ 'MobileBot' => 'Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2',
774
+ 'DesktopMode' => 'WPDesktop',
775
+ 'TV' => 'SonyDTV|HbbTV', // experimental
776
+ 'WebKit' => '(webkit)[ /]([\w.]+)',
777
+ // @todo: Include JXD consoles.
778
+ 'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|Nintendo Switch|PLAYSTATION|Xbox)\b',
779
+ 'Watch' => 'SM-V700',
780
+ );
781
+
782
+ /**
783
+ * All possible HTTP headers that represent the
784
+ * User-Agent string.
785
+ *
786
+ * @var array
787
+ */
788
+ protected static $uaHttpHeaders = array(
789
+ // The default User-Agent string.
790
+ 'HTTP_USER_AGENT',
791
+ // Header can occur on devices using Opera Mini.
792
+ 'HTTP_X_OPERAMINI_PHONE_UA',
793
+ // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
794
+ 'HTTP_X_DEVICE_USER_AGENT',
795
+ 'HTTP_X_ORIGINAL_USER_AGENT',
796
+ 'HTTP_X_SKYFIRE_PHONE',
797
+ 'HTTP_X_BOLT_PHONE_UA',
798
+ 'HTTP_DEVICE_STOCK_UA',
799
+ 'HTTP_X_UCBROWSER_DEVICE_UA'
800
+ );
801
+
802
+ /**
803
+ * The individual segments that could exist in a User-Agent string. VER refers to the regular
804
+ * expression defined in the constant self::VER.
805
+ *
806
+ * @var array
807
+ */
808
+ protected static $properties = array(
809
+
810
+ // Build
811
+ 'Mobile' => 'Mobile/[VER]',
812
+ 'Build' => 'Build/[VER]',
813
+ 'Version' => 'Version/[VER]',
814
+ 'VendorID' => 'VendorID/[VER]',
815
+
816
+ // Devices
817
+ 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
818
+ 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
819
+ 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
820
+ //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
821
+ 'Kindle' => 'Kindle/[VER]',
822
+
823
+ // Browser
824
+ 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
825
+ 'Coast' => array('Coast/[VER]'),
826
+ 'Dolfin' => 'Dolfin/[VER]',
827
+ // @reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
828
+ 'Firefox' => array('Firefox/[VER]', 'FxiOS/[VER]'),
829
+ 'Fennec' => 'Fennec/[VER]',
830
+ // http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
831
+ // https://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx
832
+ 'Edge' => 'Edge/[VER]',
833
+ 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];', 'Trident/[0-9.]+;.*rv:[VER]'),
834
+ // http://en.wikipedia.org/wiki/NetFront
835
+ 'NetFront' => 'NetFront/[VER]',
836
+ 'NokiaBrowser' => 'NokiaBrowser/[VER]',
837
+ 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),
838
+ 'Opera Mini' => 'Opera Mini/[VER]',
839
+ 'Opera Mobi' => 'Version/[VER]',
840
+ 'UCBrowser' => array( 'UCWEB[VER]', 'UC.*Browser/[VER]' ),
841
+ 'MQQBrowser' => 'MQQBrowser/[VER]',
842
+ 'MicroMessenger' => 'MicroMessenger/[VER]',
843
+ 'baiduboxapp' => 'baiduboxapp/[VER]',
844
+ 'baidubrowser' => 'baidubrowser/[VER]',
845
+ 'SamsungBrowser' => 'SamsungBrowser/[VER]',
846
+ 'Iron' => 'Iron/[VER]',
847
+ // @note: Safari 7534.48.3 is actually Version 5.1.
848
+ // @note: On BlackBerry the Version is overwriten by the OS.
849
+ 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ),
850
+ 'Skyfire' => 'Skyfire/[VER]',
851
+ 'Tizen' => 'Tizen/[VER]',
852
+ 'Webkit' => 'webkit[ /][VER]',
853
+ 'PaleMoon' => 'PaleMoon/[VER]',
854
+ 'SailfishBrowser' => 'SailfishBrowser/[VER]',
855
+
856
+ // Engine
857
+ 'Gecko' => 'Gecko/[VER]',
858
+ 'Trident' => 'Trident/[VER]',
859
+ 'Presto' => 'Presto/[VER]',
860
+ 'Goanna' => 'Goanna/[VER]',
861
+
862
+ // OS
863
+ 'iOS' => ' \bi?OS\b [VER][ ;]{1}',
864
+ 'Android' => 'Android [VER]',
865
+ 'Sailfish' => 'Sailfish [VER]',
866
+ 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),
867
+ 'BREW' => 'BREW [VER]',
868
+ 'Java' => 'Java/[VER]',
869
+ // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
870
+ // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
871
+ 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'),
872
+ 'Windows Phone' => 'Windows Phone [VER]',
873
+ 'Windows CE' => 'Windows CE/[VER]',
874
+ // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
875
+ 'Windows NT' => 'Windows NT [VER]',
876
+ 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
877
+ 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
878
+ );
879
+
880
+ /**
881
+ * Construct an instance of this class.
882
+ *
883
+ * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored.
884
+ * If left empty, will use the global _SERVER['HTTP_*'] vars instead.
885
+ * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
886
+ * from the $headers array instead.
887
+ */
888
+ public function __construct(
889
+ array $headers = null,
890
+ $userAgent = null
891
+ ) {
892
+ $this->setHttpHeaders($headers);
893
+ $this->setUserAgent($userAgent);
894
+ }
895
+
896
+ /**
897
+ * Get the current script version.
898
+ * This is useful for the demo.php file,
899
+ * so people can check on what version they are testing
900
+ * for mobile devices.
901
+ *
902
+ * @return string The version number in semantic version format.
903
+ */
904
+ public static function getScriptVersion()
905
+ {
906
+ return self::VERSION;
907
+ }
908
+
909
+ /**
910
+ * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
911
+ *
912
+ * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
913
+ * the headers. The default null is left for backwards compatibility.
914
+ */
915
+ public function setHttpHeaders($httpHeaders = null)
916
+ {
917
+ // use global _SERVER if $httpHeaders aren't defined
918
+ if (!is_array($httpHeaders) || !count($httpHeaders)) {
919
+ $httpHeaders = $_SERVER;
920
+ }
921
+
922
+ // clear existing headers
923
+ $this->httpHeaders = array();
924
+
925
+ // Only save HTTP headers. In PHP land, that means only _SERVER vars that
926
+ // start with HTTP_.
927
+ foreach ($httpHeaders as $key => $value) {
928
+ if (substr($key, 0, 5) === 'HTTP_') {
929
+ $this->httpHeaders[sanitize_text_field( $key )] = sanitize_text_field( $value );
930
+ }
931
+ }
932
+
933
+ // In case we're dealing with CloudFront, we need to know.
934
+ $this->setCfHeaders($httpHeaders);
935
+ }
936
+
937
+ /**
938
+ * Retrieves the HTTP headers.
939
+ *
940
+ * @return array
941
+ */
942
+ public function getHttpHeaders()
943
+ {
944
+ return $this->httpHeaders;
945
+ }
946
+
947
+ /**
948
+ * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
949
+ * Simply null is returned.
950
+ *
951
+ * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
952
+ * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
953
+ * all-caps, HTTP_ prefixed, underscore seperated awesomeness.
954
+ *
955
+ * @return string|null The value of the header.
956
+ */
957
+ public function getHttpHeader($header)
958
+ {
959
+ // are we using PHP-flavored headers?
960
+ if (strpos($header, '_') === false) {
961
+ $header = str_replace('-', '_', $header);
962
+ $header = strtoupper($header);
963
+ }
964
+
965
+ // test the alternate, too
966
+ $altHeader = 'HTTP_' . $header;
967
+
968
+ //Test both the regular and the HTTP_ prefix
969
+ if (isset($this->httpHeaders[$header])) {
970
+ return $this->httpHeaders[$header];
971
+ } elseif (isset($this->httpHeaders[$altHeader])) {
972
+ return $this->httpHeaders[$altHeader];
973
+ }
974
+
975
+ return null;
976
+ }
977
+
978
+ public function getMobileHeaders()
979
+ {
980
+ return self::$mobileHeaders;
981
+ }
982
+
983
+ /**
984
+ * Get all possible HTTP headers that
985
+ * can contain the User-Agent string.
986
+ *
987
+ * @return array List of HTTP headers.
988
+ */
989
+ public function getUaHttpHeaders()
990
+ {
991
+ return self::$uaHttpHeaders;
992
+ }
993
+
994
+
995
+ /**
996
+ * Set CloudFront headers
997
+ * http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-device
998
+ *
999
+ * @param array $cfHeaders List of HTTP headers
1000
+ *
1001
+ * @return boolean If there were CloudFront headers to be set
1002
+ */
1003
+ public function setCfHeaders($cfHeaders = null) {
1004
+ // use global _SERVER if $cfHeaders aren't defined
1005
+ if (!is_array($cfHeaders) || !count($cfHeaders)) {
1006
+ $cfHeaders = $_SERVER;
1007
+ }
1008
+
1009
+ // clear existing headers
1010
+ $this->cloudfrontHeaders = array();
1011
+
1012
+ // Only save CLOUDFRONT headers. In PHP land, that means only _SERVER vars that
1013
+ // start with cloudfront-.
1014
+ $response = false;
1015
+ foreach ($cfHeaders as $key => $value) {
1016
+ if (substr(strtolower($key), 0, 16) === 'http_cloudfront_') {
1017
+ $this->cloudfrontHeaders[sanitize_text_field( strtoupper($key) )] = sanitize_text_field( $value );
1018
+ $response = true;
1019
+ }
1020
+ }
1021
+
1022
+ return $response;
1023
+ }
1024
+
1025
+ /**
1026
+ * Retrieves the cloudfront headers.
1027
+ *
1028
+ * @return array
1029
+ */
1030
+ public function getCfHeaders()
1031
+ {
1032
+ return $this->cloudfrontHeaders;
1033
+ }
1034
+
1035
+ /**
1036
+ * @param string $userAgent
1037
+ * @return string
1038
+ */
1039
+ private function prepareUserAgent($userAgent) {
1040
+ $userAgent = trim($userAgent);
1041
+ $userAgent = substr($userAgent, 0, 500);
1042
+ return $userAgent;
1043
+ }
1044
+
1045
+ /**
1046
+ * Set the User-Agent to be used.
1047
+ *
1048
+ * @param string $userAgent The user agent string to set.
1049
+ *
1050
+ * @return string|null
1051
+ */
1052
+ public function setUserAgent($userAgent = null)
1053
+ {
1054
+ // Invalidate cache due to #375
1055
+ $this->cache = array();
1056
+
1057
+ if (false === empty($userAgent)) {
1058
+ return $this->userAgent = $this->prepareUserAgent($userAgent);
1059
+ } else {
1060
+ $this->userAgent = null;
1061
+ foreach ($this->getUaHttpHeaders() as $altHeader) {
1062
+ if (false === empty($this->httpHeaders[$altHeader])) { // @todo: should use getHttpHeader(), but it would be slow. (Serban)
1063
+ $this->userAgent .= $this->httpHeaders[$altHeader] . " ";
1064
+ }
1065
+ }
1066
+
1067
+ if (!empty($this->userAgent)) {
1068
+ return $this->userAgent = $this->prepareUserAgent($this->userAgent);
1069
+ }
1070
+ }
1071
+
1072
+ if (count($this->getCfHeaders()) > 0) {
1073
+ return $this->userAgent = 'Amazon CloudFront';
1074
+ }
1075
+ return $this->userAgent = null;
1076
+ }
1077
+
1078
+ /**
1079
+ * Retrieve the User-Agent.
1080
+ *
1081
+ * @return string|null The user agent if it's set.
1082
+ */
1083
+ public function getUserAgent()
1084
+ {
1085
+ return $this->userAgent;
1086
+ }
1087
+
1088
+ /**
1089
+ * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
1090
+ * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
1091
+ *
1092
+ * @deprecated since version 2.6.9
1093
+ *
1094
+ * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
1095
+ * parameter is null which will default to self::DETECTION_TYPE_MOBILE.
1096
+ */
1097
+ public function setDetectionType($type = null)
1098
+ {
1099
+ if ($type === null) {
1100
+ $type = self::DETECTION_TYPE_MOBILE;
1101
+ }
1102
+
1103
+ if ($type !== self::DETECTION_TYPE_MOBILE && $type !== self::DETECTION_TYPE_EXTENDED) {
1104
+ return;
1105
+ }
1106
+
1107
+ $this->detectionType = $type;
1108
+ }
1109
+
1110
+ public function getMatchingRegex()
1111
+ {
1112
+ return $this->matchingRegex;
1113
+ }
1114
+
1115
+ public function getMatchesArray()
1116
+ {
1117
+ return $this->matchesArray;
1118
+ }
1119
+
1120
+ /**
1121
+ * Retrieve the list of known phone devices.
1122
+ *
1123
+ * @return array List of phone devices.
1124
+ */
1125
+ public static function getPhoneDevices()
1126
+ {
1127
+ return self::$phoneDevices;
1128
+ }
1129
+
1130
+ /**
1131
+ * Retrieve the list of known tablet devices.
1132
+ *
1133
+ * @return array List of tablet devices.
1134
+ */
1135
+ public static function getTabletDevices()
1136
+ {
1137
+ return self::$tabletDevices;
1138
+ }
1139
+
1140
+ /**
1141
+ * Alias for getBrowsers() method.
1142
+ *
1143
+ * @return array List of user agents.
1144
+ */
1145
+ public static function getUserAgents()
1146
+ {
1147
+ return self::getBrowsers();
1148
+ }
1149
+
1150
+ /**
1151
+ * Retrieve the list of known browsers. Specifically, the user agents.
1152
+ *
1153
+ * @return array List of browsers / user agents.
1154
+ */
1155
+ public static function getBrowsers()
1156
+ {
1157
+ return self::$browsers;
1158
+ }
1159
+
1160
+ /**
1161
+ * Retrieve the list of known utilities.
1162
+ *
1163
+ * @return array List of utilities.
1164
+ */
1165
+ public static function getUtilities()
1166
+ {
1167
+ return self::$utilities;
1168
+ }
1169
+
1170
+ /**
1171
+ * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
1172
+ *
1173
+ * @deprecated since version 2.6.9
1174
+ *
1175
+ * @return array All the rules (but not extended).
1176
+ */
1177
+ public static function getMobileDetectionRules()
1178
+ {
1179
+ static $rules;
1180
+
1181
+ if (!$rules) {
1182
+ $rules = array_merge(
1183
+ self::$phoneDevices,
1184
+ self::$tabletDevices,
1185
+ self::$operatingSystems,
1186
+ self::$browsers
1187
+ );
1188
+ }
1189
+
1190
+ return $rules;
1191
+
1192
+ }
1193
+
1194
+ /**
1195
+ * Method gets the mobile detection rules + utilities.
1196
+ * The reason this is separate is because utilities rules
1197
+ * don't necessary imply mobile. This method is used inside
1198
+ * the new $detect->is('stuff') method.
1199
+ *
1200
+ * @deprecated since version 2.6.9
1201
+ *
1202
+ * @return array All the rules + extended.
1203
+ */
1204
+ public function getMobileDetectionRulesExtended()
1205
+ {
1206
+ static $rules;
1207
+
1208
+ if (!$rules) {
1209
+ // Merge all rules together.
1210
+ $rules = array_merge(
1211
+ self::$phoneDevices,
1212
+ self::$tabletDevices,
1213
+ self::$operatingSystems,
1214
+ self::$browsers,
1215
+ self::$utilities
1216
+ );
1217
+ }
1218
+
1219
+ return $rules;
1220
+ }
1221
+
1222
+ /**
1223
+ * Retrieve the current set of rules.
1224
+ *
1225
+ * @deprecated since version 2.6.9
1226
+ *
1227
+ * @return array
1228
+ */
1229
+ public function getRules()
1230
+ {
1231
+ if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {
1232
+ return self::getMobileDetectionRulesExtended();
1233
+ } else {
1234
+ return self::getMobileDetectionRules();
1235
+ }
1236
+ }
1237
+
1238
+ /**
1239
+ * Retrieve the list of mobile operating systems.
1240
+ *
1241
+ * @return array The list of mobile operating systems.
1242
+ */
1243
+ public static function getOperatingSystems()
1244
+ {
1245
+ return self::$operatingSystems;
1246
+ }
1247
+
1248
+ /**
1249
+ * Check the HTTP headers for signs of mobile.
1250
+ * This is the fastest mobile check possible; it's used
1251
+ * inside isMobile() method.
1252
+ *
1253
+ * @return bool
1254
+ */
1255
+ public function checkHttpHeadersForMobile()
1256
+ {
1257
+
1258
+ foreach ($this->getMobileHeaders() as $mobileHeader => $matchType) {
1259
+ if (isset($this->httpHeaders[$mobileHeader])) {
1260
+ if (isset($matchType['matches']) && is_array($matchType['matches'])) {
1261
+ foreach ($matchType['matches'] as $_match) {
1262
+ if (strpos($this->httpHeaders[$mobileHeader], $_match) !== false) {
1263
+ return true;
1264
+ }
1265
+ }
1266
+
1267
+ return false;
1268
+ } else {
1269
+ return true;
1270
+ }
1271
+ }
1272
+ }
1273
+
1274
+ return false;
1275
+
1276
+ }
1277
+
1278
+ /**
1279
+ * Magic overloading method.
1280
+ *
1281
+ * @method boolean is[...]()
1282
+ * @param string $name
1283
+ * @param array $arguments
1284
+ * @return mixed
1285
+ * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
1286
+ */
1287
+ public function __call($name, $arguments)
1288
+ {
1289
+ // make sure the name starts with 'is', otherwise
1290
+ if (substr($name, 0, 2) !== 'is') {
1291
+ throw new BadMethodCallException("No such method exists: $name");
1292
+ }
1293
+
1294
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1295
+
1296
+ $key = substr($name, 2);
1297
+
1298
+ return $this->matchUAAgainstKey($key);
1299
+ }
1300
+
1301
+ /**
1302
+ * Find a detection rule that matches the current User-agent.
1303
+ *
1304
+ * @param null $userAgent deprecated
1305
+ * @return boolean
1306
+ */
1307
+ protected function matchDetectionRulesAgainstUA($userAgent = null)
1308
+ {
1309
+ // Begin general search.
1310
+ foreach ($this->getRules() as $_regex) {
1311
+ if (empty($_regex)) {
1312
+ continue;
1313
+ }
1314
+
1315
+ if ($this->match($_regex, $userAgent)) {
1316
+ return true;
1317
+ }
1318
+ }
1319
+
1320
+ return false;
1321
+ }
1322
+
1323
+ /**
1324
+ * Search for a certain key in the rules array.
1325
+ * If the key is found then try to match the corresponding
1326
+ * regex against the User-Agent.
1327
+ *
1328
+ * @param string $key
1329
+ *
1330
+ * @return boolean
1331
+ */
1332
+ protected function matchUAAgainstKey($key)
1333
+ {
1334
+ // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
1335
+ $key = strtolower($key);
1336
+ if (false === isset($this->cache[$key])) {
1337
+
1338
+ // change the keys to lower case
1339
+ $_rules = array_change_key_case($this->getRules());
1340
+
1341
+ if (false === empty($_rules[$key])) {
1342
+ $this->cache[$key] = $this->match($_rules[$key]);
1343
+ }
1344
+
1345
+ if (false === isset($this->cache[$key])) {
1346
+ $this->cache[$key] = false;
1347
+ }
1348
+ }
1349
+
1350
+ return $this->cache[$key];
1351
+ }
1352
+
1353
+ /**
1354
+ * Check if the device is mobile.
1355
+ * Returns true if any type of mobile device detected, including special ones
1356
+ * @param null $userAgent deprecated
1357
+ * @param null $httpHeaders deprecated
1358
+ * @return bool
1359
+ */
1360
+ public function isMobile($userAgent = null, $httpHeaders = null)
1361
+ {
1362
+
1363
+ if ($httpHeaders) {
1364
+ $this->setHttpHeaders($httpHeaders);
1365
+ }
1366
+
1367
+ if ($userAgent) {
1368
+ $this->setUserAgent($userAgent);
1369
+ }
1370
+
1371
+ // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
1372
+ if ($this->getUserAgent() === 'Amazon CloudFront') {
1373
+ $cfHeaders = $this->getCfHeaders();
1374
+ if(array_key_exists('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_MOBILE_VIEWER'] === 'true') {
1375
+ return true;
1376
+ }
1377
+ }
1378
+
1379
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1380
+
1381
+ if ($this->checkHttpHeadersForMobile()) {
1382
+ return true;
1383
+ } else {
1384
+ return $this->matchDetectionRulesAgainstUA();
1385
+ }
1386
+
1387
+ }
1388
+
1389
+ /**
1390
+ * Check if the device is a tablet.
1391
+ * Return true if any type of tablet device is detected.
1392
+ *
1393
+ * @param string $userAgent deprecated
1394
+ * @param array $httpHeaders deprecated
1395
+ * @return bool
1396
+ */
1397
+ public function isTablet($userAgent = null, $httpHeaders = null)
1398
+ {
1399
+ // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
1400
+ if ($this->getUserAgent() === 'Amazon CloudFront') {
1401
+ $cfHeaders = $this->getCfHeaders();
1402
+ if(array_key_exists('HTTP_CLOUDFRONT_IS_TABLET_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_TABLET_VIEWER'] === 'true') {
1403
+ return true;
1404
+ }
1405
+ }
1406
+
1407
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1408
+
1409
+ foreach (self::$tabletDevices as $_regex) {
1410
+ if ($this->match($_regex, $userAgent)) {
1411
+ return true;
1412
+ }
1413
+ }
1414
+
1415
+ return false;
1416
+ }
1417
+
1418
+ /**
1419
+ * This method checks for a certain property in the
1420
+ * userAgent.
1421
+ * @todo: The httpHeaders part is not yet used.
1422
+ *
1423
+ * @param string $key
1424
+ * @param string $userAgent deprecated
1425
+ * @param string $httpHeaders deprecated
1426
+ * @return bool|int|null
1427
+ */
1428
+ public function is($key, $userAgent = null, $httpHeaders = null)
1429
+ {
1430
+ // Set the UA and HTTP headers only if needed (eg. batch mode).
1431
+ if ($httpHeaders) {
1432
+ $this->setHttpHeaders($httpHeaders);
1433
+ }
1434
+
1435
+ if ($userAgent) {
1436
+ $this->setUserAgent($userAgent);
1437
+ }
1438
+
1439
+ $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);
1440
+
1441
+ return $this->matchUAAgainstKey($key);
1442
+ }
1443
+
1444
+ /**
1445
+ * Some detection rules are relative (not standard),
1446
+ * because of the diversity of devices, vendors and
1447
+ * their conventions in representing the User-Agent or
1448
+ * the HTTP headers.
1449
+ *
1450
+ * This method will be used to check custom regexes against
1451
+ * the User-Agent string.
1452
+ *
1453
+ * @param $regex
1454
+ * @param string $userAgent
1455
+ * @return bool
1456
+ *
1457
+ * @todo: search in the HTTP headers too.
1458
+ */
1459
+ public function match($regex, $userAgent = null)
1460
+ {
1461
+ if (!\is_string($userAgent) && !\is_string($this->userAgent)) {
1462
+ return false;
1463
+ }
1464
+
1465
+ $match = (bool) preg_match(sprintf('#%s#is', $regex), (false === empty($userAgent) ? $userAgent : $this->userAgent), $matches);
1466
+ // If positive match is found, store the results for debug.
1467
+ if ($match) {
1468
+ $this->matchingRegex = $regex;
1469
+ $this->matchesArray = $matches;
1470
+ }
1471
+
1472
+ return $match;
1473
+ }
1474
+
1475
+ /**
1476
+ * Get the properties array.
1477
+ *
1478
+ * @return array
1479
+ */
1480
+ public static function getProperties()
1481
+ {
1482
+ return self::$properties;
1483
+ }
1484
+
1485
+ /**
1486
+ * Prepare the version number.
1487
+ *
1488
+ * @todo Remove the error supression from str_replace() call.
1489
+ *
1490
+ * @param string $ver The string version, like "2.6.21.2152";
1491
+ *
1492
+ * @return float
1493
+ */
1494
+ public function prepareVersionNo($ver)
1495
+ {
1496
+ $ver = str_replace(array('_', ' ', '/'), '.', $ver);
1497
+ $arrVer = explode('.', $ver, 2);
1498
+
1499
+ if (isset($arrVer[1])) {
1500
+ $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
1501
+ }
1502
+
1503
+ return (float) implode('.', $arrVer);
1504
+ }
1505
+
1506
+ /**
1507
+ * Check the version of the given property in the User-Agent.
1508
+ * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
1509
+ *
1510
+ * @param string $propertyName The name of the property. See self::getProperties() array
1511
+ * keys for all possible properties.
1512
+ * @param string $type Either self::VERSION_TYPE_STRING to get a string value or
1513
+ * self::VERSION_TYPE_FLOAT indicating a float value. This parameter
1514
+ * is optional and defaults to self::VERSION_TYPE_STRING. Passing an
1515
+ * invalid parameter will default to the this type as well.
1516
+ *
1517
+ * @return string|float The version of the property we are trying to extract.
1518
+ */
1519
+ public function version($propertyName, $type = self::VERSION_TYPE_STRING)
1520
+ {
1521
+ if (empty($propertyName)) {
1522
+ return false;
1523
+ }
1524
+
1525
+ if (!\is_string($this->userAgent)) {
1526
+ return false;
1527
+ }
1528
+
1529
+ // set the $type to the default if we don't recognize the type
1530
+ if ($type !== self::VERSION_TYPE_STRING && $type !== self::VERSION_TYPE_FLOAT) {
1531
+ $type = self::VERSION_TYPE_STRING;
1532
+ }
1533
+
1534
+ $properties = self::getProperties();
1535
+
1536
+ // Check if the property exists in the properties array.
1537
+ if (true === isset($properties[$propertyName])) {
1538
+
1539
+ // Prepare the pattern to be matched.
1540
+ // Make sure we always deal with an array (string is converted).
1541
+ $properties[$propertyName] = (array) $properties[$propertyName];
1542
+
1543
+ foreach ($properties[$propertyName] as $propertyMatchString) {
1544
+
1545
+ $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);
1546
+
1547
+ // Identify and extract the version.
1548
+ preg_match(sprintf('#%s#is', $propertyPattern), $this->userAgent, $match);
1549
+
1550
+ if (false === empty($match[1])) {
1551
+ $version = ($type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1]);
1552
+
1553
+ return $version;
1554
+ }
1555
+
1556
+ }
1557
+
1558
+ }
1559
+
1560
+ return false;
1561
+ }
1562
+
1563
+ /**
1564
+ * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
1565
+ * @deprecated This is no longer being maintained, it was an experiment at the time.
1566
+ * @return string One of the self::MOBILE_GRADE_* constants.
1567
+ */
1568
+ public function mobileGrade()
1569
+ {
1570
+ $isMobile = $this->isMobile();
1571
+
1572
+ if (
1573
+ // Apple iOS 4-7.0 Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3 / 5.1 / 6.1), iPad 3 (5.1 / 6.0), iPad Mini (6.1), iPad Retina (7.0), iPhone 3GS (4.3), iPhone 4 (4.3 / 5.1), iPhone 4S (5.1 / 6.0), iPhone 5 (6.0), and iPhone 5S (7.0)
1574
+ $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1575
+ $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1576
+ $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1577
+
1578
+ // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5)
1579
+ // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
1580
+ // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
1581
+ // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
1582
+ ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) ||
1583
+
1584
+ // Windows Phone 7.5-8 - Tested on the HTC Surround (7.5), HTC Trophy (7.5), LG-E900 (7.5), Nokia 800 (7.8), HTC Mazaa (7.8), Nokia Lumia 520 (8), Nokia Lumia 920 (8), HTC 8x (8)
1585
+ $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT) >= 7.5 ||
1586
+
1587
+ // Tested on the Torch 9800 (6) and Style 9670 (6), BlackBerry® Torch 9810 (7), BlackBerry Z10 (10)
1588
+ $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 6.0 ||
1589
+ // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
1590
+ $this->match('Playbook.*Tablet') ||
1591
+
1592
+ // Palm WebOS (1.4-3.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0), HP TouchPad (3.0)
1593
+ ( $this->version('webOS', self::VERSION_TYPE_FLOAT) >= 1.4 && $this->match('Palm|Pre|Pixi') ) ||
1594
+ // Palm WebOS 3.0 - Tested on HP TouchPad
1595
+ $this->match('hp.*TouchPad') ||
1596
+
1597
+ // Firefox Mobile 18 - Tested on Android 2.3 and 4.1 devices
1598
+ ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 18 ) ||
1599
+
1600
+ // Chrome for Android - Tested on Android 4.0, 4.1 device
1601
+ ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 4.0 ) ||
1602
+
1603
+ // Skyfire 4.1 - Tested on Android 2.3 device
1604
+ ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT) >= 4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) ||
1605
+
1606
+ // Opera Mobile 11.5-12: Tested on Android 2.3
1607
+ ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11.5 && $this->is('AndroidOS') ) ||
1608
+
1609
+ // Meego 1.2 - Tested on Nokia 950 and N9
1610
+ $this->is('MeeGoOS') ||
1611
+
1612
+ // Sailfish OS
1613
+ $this->is('SailfishOS') ||
1614
+
1615
+ // Tizen (pre-release) - Tested on early hardware
1616
+ $this->is('Tizen') ||
1617
+
1618
+ // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
1619
+ // @todo: more tests here!
1620
+ $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT) >= 2.0 ||
1621
+
1622
+ // UC Browser - Tested on Android 2.3 device
1623
+ ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) ||
1624
+
1625
+ // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
1626
+ ( $this->match('Kindle Fire') ||
1627
+ $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT) >= 3.0 ) ||
1628
+
1629
+ // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
1630
+ $this->is('AndroidOS') && $this->is('NookTablet') ||
1631
+
1632
+ // Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7
1633
+ $this->version('Chrome', self::VERSION_TYPE_FLOAT) >= 16 && !$isMobile ||
1634
 
1635
+ // Safari Desktop 5-6 - Tested on OS X 10.7 and Windows 7
1636
+ $this->version('Safari', self::VERSION_TYPE_FLOAT) >= 5.0 && !$isMobile ||
 
1637
 
1638
+ // Firefox Desktop 10-18 - Tested on OS X 10.7 and Windows 7
1639
+ $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 10.0 && !$isMobile ||
1640
 
1641
+ // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
1642
+ $this->version('IE', self::VERSION_TYPE_FLOAT) >= 7.0 && !$isMobile ||
1643
 
1644
+ // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
1645
+ $this->version('Opera', self::VERSION_TYPE_FLOAT) >= 10 && !$isMobile
1646
+ ){
1647
+ return self::MOBILE_GRADE_A;
1648
+ }
1649
 
1650
+ if (
1651
+ $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 ||
1652
+ $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<4.3 ||
1653
+ $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT)<4.3 ||
1654
 
1655
+ // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
1656
+ $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 ||
1657
+
1658
+ //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
1659
+ ($this->version('Opera Mini', self::VERSION_TYPE_FLOAT) >= 5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT) <= 7.0 &&
1660
+ ($this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 || $this->is('iOS')) ) ||
1661
+
1662
+ // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
1663
+ $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||
1664
+
1665
+ // @todo: report this (tested on Nokia N71)
1666
+ $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11 && $this->is('SymbianOS')
1667
+ ){
1668
+ return self::MOBILE_GRADE_B;
1669
+ }
1670
 
1671
+ if (
1672
+ // Blackberry 4.x - Tested on the Curve 8330
1673
+ $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) <= 5.0 ||
1674
+ // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
1675
+ $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT) <= 5.2 ||
1676
 
1677
+ // Tested on original iPhone (3.1), iPhone 3 (3.2)
1678
+ $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1679
+ $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1680
+ $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1681
 
1682
+ // Internet Explorer 7 and older - Tested on Windows XP
1683
+ $this->version('IE', self::VERSION_TYPE_FLOAT) <= 7.0 && !$isMobile
1684
+ ){
1685
+ return self::MOBILE_GRADE_C;
1686
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1687
 
1688
+ // All older smartphone platforms and featurephones - Any device that doesn't support media queries
1689
+ // will receive the basic, C grade experience.
1690
+ return self::MOBILE_GRADE_C;
1691
+ }
1692
+ }
edsanimate.php CHANGED
@@ -5,7 +5,7 @@
5
  * Domain Path: /lang
6
  * Plugin URI: http://www.eleopard.in
7
  * Description: Add cool CSS3 animations to your content.
8
- * Version: 2.4.0
9
  * Author: eLEOPARD Design Studios
10
  * Author URI: http://www.eleopard.in
11
  * License: GNU General Public License version 2 or later; see LICENSE.txt
5
  * Domain Path: /lang
6
  * Plugin URI: http://www.eleopard.in
7
  * Description: Add cool CSS3 animations to your content.
8
+ * Version: 2.4.1
9
  * Author: eLEOPARD Design Studios
10
  * Author URI: http://www.eleopard.in
11
  * License: GNU General Public License version 2 or later; see LICENSE.txt
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: eleopard
3
  Tags: css3 animation, animate.css, jquery, on scroll animation, delay, infinite, entry exit, iteration
4
  Requires at least: 4.7.0
5
- Tested up to: 5.9.2
6
  Stable tag: 2.4.0
7
  License: GNU General Public License version 2 or later
8
  License URI: http://www.gnu.org/copyleft/gpl.html
@@ -82,6 +82,9 @@ Add duration class ( duration1 to duration20 ) along with the other classes. or
82
 
83
  == Changelog ==
84
 
 
 
 
85
  = Version 2.4.0 =
86
  * Security Fixes
87
 
2
  Contributors: eleopard
3
  Tags: css3 animation, animate.css, jquery, on scroll animation, delay, infinite, entry exit, iteration
4
  Requires at least: 4.7.0
5
+ Tested up to: 6.0.1
6
  Stable tag: 2.4.0
7
  License: GNU General Public License version 2 or later
8
  License URI: http://www.gnu.org/copyleft/gpl.html
82
 
83
  == Changelog ==
84
 
85
+ = Version 2.4.1 =
86
+ * Fixes related to mobile detect functionality
87
+
88
  = Version 2.4.0 =
89
  * Security Fixes
90