Easy Facebook Like Box (Facebook Page Plugin) – Custom Facebook Feed – Auto PopUp - Version 4.2.5

Version Description

Upadte to ensuer the maximum compatiblity with other themes and plugins.

Download this release

Release Info

Developer sjaved
Plugin Icon 128x128 Easy Facebook Like Box (Facebook Page Plugin) – Custom Facebook Feed – Auto PopUp
Version 4.2.5
Comparing to
See all releases

Code changes from version 4.2.4 to 4.2.5

README.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: sjaved, DaNish Ali
3
  Tags: easy custom facebook feed, facebook feed, facebook page plugin, page plugin, adoptive, facebook, facebook like box,, like box, facebook like box, facebook like box widget, facebook like box shortcodes, shortcodes, facebook like box plugin, facebook like box wordpress plugin, plugin, responsive facebook like box, responsive, facebook like box in 75 locales, facebook like box in 75 languages, custom facebook feed, facebook like box in PopUp, PopUp, Auto PopUp, like box in PopUp, fancybox, lightbox, seo, social media, facebook badge, facebook button, facebook connect, facebook facepile, Facebook fan page, wordpress facebook like box, facebook share, facebook integration, shortcode generator, advanced responsive facebook likebox, facebook wall, facebook sidebar, facebook recommend, like box facebook, open graph, facebook page, facebook group, rt facebook like box, sharebar
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=sjaved786%40gmail%2ecom&lc=US&item_name=Easy%20Facebook%20Like%20Box%20WordPress%20Plugin&item_number=efbl&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted
5
  Requires at least: 3.3
6
- Tested up to: 4.5
7
- Stable tag: 4.2.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -82,6 +82,9 @@ You can use easy facebook like box in number of ways:
82
  3. Navigate to "Appearance > Widgets" and drag and drop "Easy Facebook Likebox" in desired widget area or use the shortcode in page/post generated by widget.
83
 
84
  == Upgrade Notice ==
 
 
 
85
  = 4.2.2 =
86
  Update if you see any issue with security plugin
87
 
@@ -127,16 +130,22 @@ To submit your feedback, suggestions and features request follow the below link.
127
  http://wordpress.org/support/topic/need-feed-back-on-plugin-feature/
128
 
129
  == Screenshots ==
130
- 1. Facebook like box in light color scheme.
131
- 2. Facebook like box in dark color scheme.
132
- 3. Facebook like box with posts and faces.
133
- 4. Facebook like box with posts only.
134
- 5. Facebook like box in page using shortcode with all options.
135
- 6. Facebook like box backend view with options description.
136
-
 
 
137
 
138
 
139
  == Changelog ==
 
 
 
 
140
  = 4.2.2 =
141
  * Delete a unnecessary file
142
 
3
  Tags: easy custom facebook feed, facebook feed, facebook page plugin, page plugin, adoptive, facebook, facebook like box,, like box, facebook like box, facebook like box widget, facebook like box shortcodes, shortcodes, facebook like box plugin, facebook like box wordpress plugin, plugin, responsive facebook like box, responsive, facebook like box in 75 locales, facebook like box in 75 languages, custom facebook feed, facebook like box in PopUp, PopUp, Auto PopUp, like box in PopUp, fancybox, lightbox, seo, social media, facebook badge, facebook button, facebook connect, facebook facepile, Facebook fan page, wordpress facebook like box, facebook share, facebook integration, shortcode generator, advanced responsive facebook likebox, facebook wall, facebook sidebar, facebook recommend, like box facebook, open graph, facebook page, facebook group, rt facebook like box, sharebar
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=sjaved786%40gmail%2ecom&lc=US&item_name=Easy%20Facebook%20Like%20Box%20WordPress%20Plugin&item_number=efbl&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted
5
  Requires at least: 3.3
6
+ Tested up to: 4.5.2
7
+ Stable tag: 4.2.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
82
  3. Navigate to "Appearance > Widgets" and drag and drop "Easy Facebook Likebox" in desired widget area or use the shortcode in page/post generated by widget.
83
 
84
  == Upgrade Notice ==
85
+ = 4.2.5 =
86
+ Upadte to ensuer the maximum compatiblity with other themes and plugins.
87
+
88
  = 4.2.2 =
89
  Update if you see any issue with security plugin
90
 
130
  http://wordpress.org/support/topic/need-feed-back-on-plugin-feature/
131
 
132
  == Screenshots ==
133
+ 1. Custom Facebook Feed with thumnail.
134
+ 2. Custom Facebook Feed in PopUp.
135
+ 3. Responsive Custom Facebook Feed.
136
+ 4. Facebook Like Box/ Page Plugin in Auto PopUp.
137
+ 5. Facebook Like Box/ Page Plugin in sidebar with post feed.
138
+ 6. Facebook Like Box/ Page Plugin widget settings.
139
+ 7. Custom Facebook Feed widget settings.
140
+ 8. Easy Facebook Like Box settings dashboard.
141
+ 9. Auto PopUp settings panel.
142
 
143
 
144
  == Changelog ==
145
+ = 4.2.5 =
146
+ * Mobile_Detect redclare class error.
147
+ * Other optimzation of code to reduce the size.
148
+
149
  = 4.2.2 =
150
  * Delete a unnecessary file
151
 
admin/easy-facebook-likebox-admin.php CHANGED
@@ -273,6 +273,9 @@ class Easy_Facebook_Likebox_Admin {
273
  if ( get_site_option( $version_key ) == $plugin_verstion && get_site_option( $notice_key ) == 1 ) return;
274
 
275
  $msg = sprintf(__('Thanks for installting/upgrading the Easy Facebook Likebox Plugin! If you like this plugin, please consider some <a href="%s" target="_blank">donation</a> and/or <a href="%s" target="_blank">rating it</a>!
 
 
 
276
  Support us by liking our facebook fan page and/or become follower at twitter!
277
 
278
  <div id="fb-root"></div>
273
  if ( get_site_option( $version_key ) == $plugin_verstion && get_site_option( $notice_key ) == 1 ) return;
274
 
275
  $msg = sprintf(__('Thanks for installting/upgrading the Easy Facebook Likebox Plugin! If you like this plugin, please consider some <a href="%s" target="_blank">donation</a> and/or <a href="%s" target="_blank">rating it</a>!
276
+
277
+ I would really appreciate if you could spare 30 to <a href="https://apps.facebook.com/my-polls/form/what-feature-you-use-mostly-in-plugin?from=admin_wall" target="_blank">answer a simple question</a>.
278
+
279
  Support us by liking our facebook fan page and/or become follower at twitter!
280
 
281
  <div id="fb-root"></div>
admin/views/support-us.php CHANGED
@@ -29,3 +29,5 @@
29
  <h1> Follow me at twitter</h1>
30
  <a href="https://twitter.com/SajidJavaid" class="twitter-follow-button" data-show-count="false">Follow @SajidJavaid</a>
31
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?"http":"https";if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document, "script", "twitter-wjs");</script>
 
 
29
  <h1> Follow me at twitter</h1>
30
  <a href="https://twitter.com/SajidJavaid" class="twitter-follow-button" data-show-count="false">Follow @SajidJavaid</a>
31
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?"http":"https";if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document, "script", "twitter-wjs");</script>
32
+
33
+ I would really appreciate if you could spare 30 to <a href="https://apps.facebook.com/my-polls/form/what-feature-you-use-mostly-in-plugin?from=admin_wall" target="_blank">answer a simple question</a>.
easy-facebook-likebox.php CHANGED
@@ -2,8 +2,8 @@
2
  /**
3
  * Plugin Name: Easy Facebook Likebox
4
  * Plugin URI: httt://wordpress.org/plugins/easy-facebook-likebox
5
- * Description: Easy Facebook like box WordPress plugin allows you to easly display facebook like box fan page on your website using either widget or shortcode to increase facbook fan page likes. You can use the shortcode generated after saving the facebook like box widget. Its completely customizable with lots of optional settings. Its also responsive facebook like box at the same time.
6
- * Version: 4.2.4
7
  * Author: Sajid Javed
8
  * Author URI: http://jwebsol.com
9
  * Text Domain: easy-facebook-likebox
2
  /**
3
  * Plugin Name: Easy Facebook Likebox
4
  * Plugin URI: httt://wordpress.org/plugins/easy-facebook-likebox
5
+ * Description: Easy Facebook like box WordPress plugin allows you to easly display facebook like box fan page on your website using either widget or shortcode to increase facbook fan page likes. You can use the shortcode generated after saving the facebook like box widget. Additionally it also now allows you to dipslay the cusetomized facebook feed on your website using the same color scheme of your website. Its completely customizable with lots of optional settings. Its also responsive facebook like box at the same time.
6
+ * Version: 4.2.5
7
  * Author: Sajid Javed
8
  * Author URI: http://jwebsol.com
9
  * Text Domain: easy-facebook-likebox
public/easy-facebook-likebox.php CHANGED
@@ -2,10 +2,10 @@
2
  /**
3
  * Plugin Name.
4
  *
5
- * @package Plugin_Name
6
- * @author Your Name <email@example.com>
7
  * @license GPL-2.0+
8
- * @link http://example.com
9
  * @copyright 2014 Your Name or Company Name
10
  */
11
 
@@ -18,12 +18,12 @@
18
  *
19
  * @TODO: Rename this class to a proper name for your plugin.
20
  *
21
- * @package Plugin_Name
22
- * @author Your Name <email@example.com>
23
  */
24
  // Include and instantiate the class.
25
  require_once 'includes/Mobile_Detect.php';
26
- $mDetect = new Mobile_Detect;
27
 
28
  class Easy_Facebook_Likebox {
29
 
@@ -34,7 +34,7 @@ class Easy_Facebook_Likebox {
34
  *
35
  * @var string
36
  */
37
- const VERSION = '4.2.4';
38
 
39
  /**
40
  * @TODO - Rename "plugin-name" to the name your your plugin
2
  /**
3
  * Plugin Name.
4
  *
5
+ * @package EasyFacebookLikeBox
6
+ * @author Sajid Javed <sjaved_87@yahoo.compact>
7
  * @license GPL-2.0+
8
+ * @link http://jwesolb.com
9
  * @copyright 2014 Your Name or Company Name
10
  */
11
 
18
  *
19
  * @TODO: Rename this class to a proper name for your plugin.
20
  *
21
+ * @package EasyFacebookLikeBox
22
+ * @author Sajid Javed <sjaved_87@yahoo.compact>
23
  */
24
  // Include and instantiate the class.
25
  require_once 'includes/Mobile_Detect.php';
26
+ $mDetect = new EFBL_Mobile_Detect;
27
 
28
  class Easy_Facebook_Likebox {
29
 
34
  *
35
  * @var string
36
  */
37
+ const VERSION = '4.2.5';
38
 
39
  /**
40
  * @TODO - Rename "plugin-name" to the name your your plugin
public/includes/Mobile_Detect.php CHANGED
@@ -25,1317 +25,1319 @@
25
  * @version 2.8.11
26
  */
27
 
28
- class 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.11';
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
- * The User-Agent HTTP header is stored in here.
83
- * @var string
84
- */
85
- protected $userAgent = null;
86
-
87
- /**
88
- * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
89
- * @var array
90
- */
91
- protected $httpHeaders = array();
92
-
93
- /**
94
- * The matching Regex.
95
- * This is good for debug.
96
- * @var string
97
- */
98
- protected $matchingRegex = null;
99
-
100
- /**
101
- * The matches extracted from the regex expression.
102
- * This is good for debug.
103
- * @var string
104
- */
105
- protected $matchesArray = null;
106
-
107
- /**
108
- * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
109
- *
110
- * @deprecated since version 2.6.9
111
- *
112
- * @var string
113
- */
114
- protected $detectionType = self::DETECTION_TYPE_MOBILE;
115
-
116
- /**
117
- * HTTP headers that trigger the 'isMobile' detection
118
- * to be true.
119
- *
120
- * @var array
121
- */
122
- protected static $mobileHeaders = array(
123
-
124
- 'HTTP_ACCEPT' => array('matches' => array(
125
- // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
126
- 'application/x-obml2d',
127
- // BlackBerry devices.
128
- 'application/vnd.rim.html',
129
- 'text/vnd.wap.wml',
130
- 'application/vnd.wap.xhtml+xml'
131
- )),
132
- 'HTTP_X_WAP_PROFILE' => null,
133
- 'HTTP_X_WAP_CLIENTID' => null,
134
- 'HTTP_WAP_CONNECTION' => null,
135
- 'HTTP_PROFILE' => null,
136
- // Reported by Opera on Nokia devices (eg. C3).
137
- 'HTTP_X_OPERAMINI_PHONE_UA' => null,
138
- 'HTTP_X_NOKIA_GATEWAY_ID' => null,
139
- 'HTTP_X_ORANGE_ID' => null,
140
- 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
141
- 'HTTP_X_HUAWEI_USERID' => null,
142
- // Reported by Windows Smartphones.
143
- 'HTTP_UA_OS' => null,
144
- // Reported by Verizon, Vodafone proxy system.
145
- 'HTTP_X_MOBILE_GATEWAY' => null,
146
- // Seen this on HTC Sensation. SensationXE_Beats_Z715e.
147
- 'HTTP_X_ATT_DEVICEID' => null,
148
- // Seen this on a HTC.
149
- 'HTTP_UA_CPU' => array('matches' => array('ARM')),
150
- );
151
-
152
- /**
153
- * List of mobile devices (phones).
154
- *
155
- * @var array
156
- */
157
- protected static $phoneDevices = array(
158
- 'iPhone' => '\biPhone\b|\biPod\b', // |\biTunes
159
- 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
160
- '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',
161
- 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6',
162
- // @todo: Is 'Dell Streak' a tablet or a phone? ;)
163
- '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',
164
- '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',
165
- 'Samsung' => 'Samsung|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',
166
- '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)',
167
- 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533',
168
- 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile',
169
- // http://www.micromaxinfo.com/mobiles/smartphones
170
- // Added because the codes might conflict with Acer Tablets.
171
- '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',
172
- // @todo Complete the regex.
173
- 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ;
174
- 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
175
- // http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
176
- // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
177
- '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',
178
- // http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
179
- 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
180
- 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)',
181
- // Added simvalley mobile just for fun. They have some interesting devices.
182
- // http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
183
- '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',
184
- // Wolfgang - a brand that is sold by Aldi supermarkets.
185
- // http://www.wolfgangmobile.com/
186
- 'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q',
187
- 'Alcatel' => 'Alcatel',
188
- 'Nintendo' => 'Nintendo 3DS',
189
- // http://en.wikipedia.org/wiki/Amoi
190
- 'Amoi' => 'Amoi',
191
- // http://en.wikipedia.org/wiki/INQ
192
- 'INQ' => 'INQ',
193
- // @Tapatalk is a mobile app; http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039
194
- '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',
195
- );
196
-
197
- /**
198
- * List of tablet devices.
199
- *
200
- * @var array
201
- */
202
- protected static $tabletDevices = array(
203
- 'iPad' => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic.
204
- 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)|^.*Android.*Nexus(?:(?!Mobile).)*$',
205
- '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-I9205|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-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T707A|SM-T807A|SM-T237P|SM-T807P|SM-P607T|SM-T217T|SM-T337T', // SCH-P709|SCH-P729|SM-T2558 - Samsung Mega - treat them like a regular phone.
206
- // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
207
- 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI)\b',
208
- // Only the Surface tablets with Windows RT are considered mobile.
209
- // http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
210
- 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)',
211
- // http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
212
- 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10',
213
- // Watch out for PadFone, see #132.
214
- // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/
215
- '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',
216
- 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
217
- 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410',
218
- 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
219
- 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
220
- // http://www.acer.ro/ac/ro/RO/content/drivers
221
- // http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
222
- // http://us.acer.com/ac/en/US/content/group/tablets
223
- // http://www.acer.de/ac/de/DE/content/models/tablets/
224
- // Can conflict with Micromax and Motorola phones codes.
225
- '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',
226
- // http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
227
- // http://us.toshiba.com/tablets/tablet-finder
228
- // http://www.toshiba.co.jp/regza/tablet/
229
- 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
230
- // http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
231
- // http://www.lg.com/us/tablets
232
- 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b',
233
- 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
234
- // Prestigio Tablets http://www.prestigio.com/support
235
- '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',
236
- // http://support.lenovo.com/en_GB/downloads/default.page?#
237
- 'LenovoTablet' => 'Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)',
238
- // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets
239
- 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7',
240
- // http://www.yarvik.com/en/matrix/tablets/
241
- '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',
242
- 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
243
- 'ArnovaTablet' => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2',
244
- // http://www.intenso.de/kategorie_en.php?kategorie=33
245
- // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate
246
- 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004',
247
- // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
248
- 'IRUTablet' => 'M702pro',
249
- 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
250
- // http://www.e-boda.ro/tablete-pc.html
251
- 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
252
- // http://www.allview.ro/produse/droseries/lista-tablete-pc/
253
- 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
254
- // http://wiki.archosfans.com/index.php?title=Main_Page
255
- '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',
256
- // http://www.ainol.com/plugin.php?identifier=ainol&module=product
257
- 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
258
- // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
259
- // Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
260
- // http://www.sony.jp/support/tablet/
261
- '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',
262
- // 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
263
- 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b',
264
- // db + http://www.cube-tablet.com/buy-products.html
265
- 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
266
- // http://www.cobyusa.com/?p=pcat&pcat_id=3001
267
- 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
268
- // http://www.match.net.cn/products.asp
269
- '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',
270
- // http://www.msi.com/support
271
- // @todo Research the Windows Tablets.
272
- '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',
273
- // @todo http://www.kyoceramobile.com/support/drivers/
274
- // 'KyoceraTablet' => null,
275
- // @todo http://intexuae.com/index.php/category/mobile-devices/tablets-products/
276
- // 'IntextTablet' => null,
277
- // http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
278
- // http://www.imp3.net/14/show.php?itemid=20454
279
- 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
280
- // http://www.rock-chips.com/index.php?do=prod&pid=2
281
- 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
282
- // http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
283
- 'FlyTablet' => 'IQ310|Fly Vision',
284
- // http://www.bqreaders.com/gb/tablets-prices-sale.html
285
- 'bqTablet' => 'bq.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant)|Maxwell.*Lite|Maxwell.*Plus',
286
- // http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
287
- // http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
288
- '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',
289
- // Nec or Medias Tab
290
- 'NecTablet' => '\bN-06D|\bN-08D',
291
- // Pantech Tablets: http://www.pantechusa.com/phones/
292
- 'PantechTablet' => 'Pantech.*P4100',
293
- // Broncho Tablets: http://www.broncho.cn/ (hard to find)
294
- 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
295
- // http://versusuk.com/support.html
296
- 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
297
- // http://www.zync.in/index.php/our-products/tablet-phablets
298
- 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
299
- // http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
300
- 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
301
- // https://www.nabitablet.com/
302
- 'NabiTablet' => 'Android.*\bNabi',
303
- 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
304
- // French Danew Tablets http://www.danew.com/produits-tablette.php
305
- 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
306
- // Texet Tablets and Readers http://www.texet.ru/tablet/
307
- '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',
308
- // Avoid detecting 'PLAYSTATION 3' as mobile.
309
- 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
310
- // http://www.trekstor.de/surftabs.html
311
- 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab',
312
- // http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets
313
- 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
314
- // http://www.advandigital.com/index.php?link=content-product&jns=JP001
315
- // because of the short codenames we have to include whitespaces to reduce the possible conflicts.
316
- '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 ',
317
- // http://www.danytech.com/category/tablet-pc
318
- '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',
319
- // http://www.galapad.net/product.html
320
- 'GalapadTablet' => 'Android.*\bG1\b',
321
- // http://www.micromaxinfo.com/tablet/funbook
322
- 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
323
- // http://www.karbonnmobiles.com/products_tablet.php
324
- 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
325
- // http://www.myallfine.com/Products.asp
326
- 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
327
- // http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
328
- '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',
329
- // http://www.yonesnav.com/products/products.php
330
- 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
331
- // http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
332
- // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
333
- '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',
334
- // http://www.gloryunion.cn/products.asp
335
- // http://www.allwinnertech.com/en/apply/mobile.html
336
- // http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
337
- // @todo: Softwiner tablets?
338
- // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
339
- '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
340
- // http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
341
- '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',
342
- // http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
343
- // @todo: add more tests.
344
- 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)',
345
- // http://hclmetablet.com/India/index.php
346
- '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',
347
- // http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
348
- 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
349
- // http://www.visture.com/index.asp
350
- 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
351
- // http://www.mijncresta.nl/tablet
352
- 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
353
- // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309
354
- 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
355
- // Concorde tab
356
- 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
357
- // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/
358
- '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',
359
- // Modecom Tablets - http://www.modecom.eu/tablets/portal/
360
- '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',
361
- // Vonino Tablets - http://www.vonino.eu/tablets
362
- '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',
363
- // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0
364
- 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
365
- // Storex Tablets - http://storex.fr/espace_client/support.html
366
- // @note: no need to add all the tablet codes since they are guided by the first regex.
367
- 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
368
- // Generic Vodafone tablets.
369
- 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7',
370
- // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb
371
- // Aka: http://www.essentielb.fr/
372
- 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
373
- // Ross & Moor - http://ross-moor.ru/
374
- 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
375
- // i-mobile http://product.i-mobilephone.com/Mobile_Device
376
- 'iMobileTablet' => 'i-mobile i-note',
377
- // http://www.tolino.de/de/vergleichen/
378
- 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
379
- // AudioSonic - a Kmart brand
380
- // 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
381
- 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
382
- // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/
383
- // @todo: add them gradually to avoid conflicts.
384
- 'AMPETablet' => 'Android.* A78 ',
385
- // Skk Mobile - http://skkmobile.com.ph/product_tablets.php
386
- 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
387
- // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1
388
- 'TecnoTablet' => 'TECNO P9',
389
- // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3
390
- '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',
391
- // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/
392
- '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)',
393
- // http://www.intracon.eu/tablet
394
- 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
395
- // http://www.xoro.de/produkte/
396
- // @note: Might be the same brand with 'Simply tablets'
397
- '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',
398
- // http://www1.viewsonic.com/products/computing/tablets/
399
- 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
400
- // http://www.odys.de/web/internet-tablet_en.html
401
- 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10',
402
- // http://www.captiva-power.de/products.html#tablets-en
403
- 'CaptivaTablet' => 'CAPTIVA PAD',
404
- // IconBIT - http://www.iconbit.com/products/tablets/
405
- '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',
406
- // http://www.teclast.com/topic.php?channelID=70&topicID=140&pid=63
407
- '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',
408
- 'JaytechTablet' => 'TPC-PA762',
409
- 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010',
410
- // http://www.digma.ru/support/download/
411
- // @todo: Ebooks also (if requested)
412
- 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b',
413
- // http://www.evolioshop.com/ro/tablete-pc.html
414
- // http://www.evolio.ro/support/downloads_static.html?cat=2
415
- // @todo: Research some more
416
- 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b',
417
- // @todo http://www.lavamobiles.com/tablets-data-cards
418
- 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY',
419
- // https://www.celkonmobiles.com/?_a=categoryphones&sid=2
420
- 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b',
421
- // http://www.mi.com/en
422
- 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b',
423
- // http://www.nbru.cn/index.html
424
- 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One',
425
- // http://navroad.com/products/produkty/tablety/
426
- 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI',
427
- // http://www.datawind.com/ubislate/
428
- 'UbislateTablet' => 'UbiSlate[\s]?7C',
429
- // http://www.pocketbook-int.com/ru/support
430
- 'PocketBookTablet' => 'Pocketbook',
431
- // http://www.tesco.com/direct/hudl/
432
- 'Hudl' => 'Hudl HT7S3',
433
- // http://www.telstra.com.au/home-phone/thub-2/
434
- 'TelstraTablet' => 'T-Hub2',
435
- '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|\bJolla\b'
436
- );
437
-
438
- /**
439
- * List of mobile Operating Systems.
440
- *
441
- * @var array
442
- */
443
- protected static $operatingSystems = array(
444
- 'AndroidOS' => 'Android',
445
- 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
446
- 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
447
- 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
448
- // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
449
- 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
450
- // @reference: http://en.wikipedia.org/wiki/Windows_Phone
451
- // http://wifeng.cn/?r=blog&a=view&id=106
452
- // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
453
- // http://msdn.microsoft.com/library/ms537503.aspx
454
- 'WindowsPhoneOS' => 'Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;',
455
- 'iOS' => '\biPhone.*Mobile|\biPod|\biPad',
456
- // http://en.wikipedia.org/wiki/MeeGo
457
- // @todo: research MeeGo in UAs
458
- 'MeeGoOS' => 'MeeGo',
459
- // http://en.wikipedia.org/wiki/Maemo
460
- // @todo: research Maemo in UAs
461
- 'MaemoOS' => 'Maemo',
462
- 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
463
- 'webOS' => 'webOS|hpwOS',
464
- 'badaOS' => '\bBada\b',
465
- 'BREWOS' => 'BREW',
466
- );
467
-
468
- /**
469
- * List of mobile User Agents.
470
- *
471
- * @var array
472
- */
473
- protected static $browsers = array(
474
- // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
475
- 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
476
- 'Dolfin' => '\bDolfin\b',
477
- 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+',
478
- 'Skyfire' => 'Skyfire',
479
- 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
480
- 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile',
481
- 'Bolt' => 'bolt',
482
- 'TeaShark' => 'teashark',
483
- 'Blazer' => 'Blazer',
484
- // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
485
- 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari',
486
- // http://en.wikipedia.org/wiki/Midori_(web_browser)
487
- //'Midori' => 'midori',
488
- 'Tizen' => 'Tizen',
489
- 'UCBrowser' => 'UC.*Browser|UCWEB',
490
- 'baiduboxapp' => 'baiduboxapp',
491
- 'baidubrowser' => 'baidubrowser',
492
- // https://github.com/serbanghita/Mobile-Detect/issues/7
493
- 'DiigoBrowser' => 'DiigoBrowser',
494
- // http://www.puffinbrowser.com/index.php
495
- 'Puffin' => 'Puffin',
496
- // http://mercury-browser.com/index.html
497
- 'Mercury' => '\bMercury\b',
498
- // http://en.wikipedia.org/wiki/Obigo_Browser
499
- 'ObigoBrowser' => 'Obigo',
500
- // http://en.wikipedia.org/wiki/NetFront
501
- 'NetFront' => 'NF-Browser',
502
- // @reference: http://en.wikipedia.org/wiki/Minimo
503
- // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
504
- 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger',
505
- );
506
-
507
- /**
508
- * Utilities.
509
- *
510
- * @var array
511
- */
512
- protected static $utilities = array(
513
- // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
514
- // http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
515
- // https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
516
- 'DesktopMode' => 'WPDesktop',
517
- 'TV' => 'SonyDTV|HbbTV', // experimental
518
- 'WebKit' => '(webkit)[ /]([\w.]+)',
519
- 'Bot' => 'Googlebot|YandexBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|facebookexternalhit',
520
- 'MobileBot' => 'Googlebot-Mobile|YahooSeeker/M1A1-R2D2',
521
- // @todo: Include JXD consoles.
522
- 'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|PLAYSTATION|Xbox)\b',
523
- 'Watch' => 'SM-V700',
524
- );
525
-
526
- /**
527
- * All possible HTTP headers that represent the
528
- * User-Agent string.
529
- *
530
- * @var array
531
- */
532
- protected static $uaHttpHeaders = array(
533
- // The default User-Agent string.
534
- 'HTTP_USER_AGENT',
535
- // Header can occur on devices using Opera Mini.
536
- 'HTTP_X_OPERAMINI_PHONE_UA',
537
- // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
538
- 'HTTP_X_DEVICE_USER_AGENT',
539
- 'HTTP_X_ORIGINAL_USER_AGENT',
540
- 'HTTP_X_SKYFIRE_PHONE',
541
- 'HTTP_X_BOLT_PHONE_UA',
542
- 'HTTP_DEVICE_STOCK_UA',
543
- 'HTTP_X_UCBROWSER_DEVICE_UA'
544
- );
545
-
546
- /**
547
- * The individual segments that could exist in a User-Agent string. VER refers to the regular
548
- * expression defined in the constant self::VER.
549
- *
550
- * @var array
551
- */
552
- protected static $properties = array(
553
-
554
- // Build
555
- 'Mobile' => 'Mobile/[VER]',
556
- 'Build' => 'Build/[VER]',
557
- 'Version' => 'Version/[VER]',
558
- 'VendorID' => 'VendorID/[VER]',
559
-
560
- // Devices
561
- 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
562
- 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
563
- 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
564
- //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
565
- 'Kindle' => 'Kindle/[VER]',
566
-
567
- // Browser
568
- 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
569
- 'Coast' => array('Coast/[VER]'),
570
- 'Dolfin' => 'Dolfin/[VER]',
571
- // @reference: https://developer.mozilla.org/en-US/docs/User_Agent_Strings_Reference
572
- 'Firefox' => 'Firefox/[VER]',
573
- 'Fennec' => 'Fennec/[VER]',
574
- // @reference: http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
575
- 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];'),
576
- // http://en.wikipedia.org/wiki/NetFront
577
- 'NetFront' => 'NetFront/[VER]',
578
- 'NokiaBrowser' => 'NokiaBrowser/[VER]',
579
- 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),
580
- 'Opera Mini' => 'Opera Mini/[VER]',
581
- 'Opera Mobi' => 'Version/[VER]',
582
- 'UC Browser' => 'UC Browser[VER]',
583
- 'MQQBrowser' => 'MQQBrowser/[VER]',
584
- 'MicroMessenger' => 'MicroMessenger/[VER]',
585
- 'baiduboxapp' => 'baiduboxapp/[VER]',
586
- 'baidubrowser' => 'baidubrowser/[VER]',
587
- 'Iron' => 'Iron/[VER]',
588
- // @note: Safari 7534.48.3 is actually Version 5.1.
589
- // @note: On BlackBerry the Version is overwriten by the OS.
590
- 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ),
591
- 'Skyfire' => 'Skyfire/[VER]',
592
- 'Tizen' => 'Tizen/[VER]',
593
- 'Webkit' => 'webkit[ /][VER]',
594
-
595
- // Engine
596
- 'Gecko' => 'Gecko/[VER]',
597
- 'Trident' => 'Trident/[VER]',
598
- 'Presto' => 'Presto/[VER]',
599
-
600
- // OS
601
- 'iOS' => ' \bOS\b [VER] ',
602
- 'Android' => 'Android [VER]',
603
- 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),
604
- 'BREW' => 'BREW [VER]',
605
- 'Java' => 'Java/[VER]',
606
- // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
607
- // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
608
- 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'),
609
- 'Windows Phone' => 'Windows Phone [VER]',
610
- 'Windows CE' => 'Windows CE/[VER]',
611
- // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
612
- 'Windows NT' => 'Windows NT [VER]',
613
- 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
614
- 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
615
- );
616
-
617
- /**
618
- * Construct an instance of this class.
619
- *
620
- * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored.
621
- * If left empty, will use the global _SERVER['HTTP_*'] vars instead.
622
- * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
623
- * from the $headers array instead.
624
- */
625
- public function __construct(
626
- array $headers = null,
627
- $userAgent = null
628
- ) {
629
- $this->setHttpHeaders($headers);
630
- $this->setUserAgent($userAgent);
631
- }
632
-
633
- /**
634
- * Get the current script version.
635
- * This is useful for the demo.php file,
636
- * so people can check on what version they are testing
637
- * for mobile devices.
638
- *
639
- * @return string The version number in semantic version format.
640
- */
641
- public static function getScriptVersion()
642
- {
643
- return self::VERSION;
644
- }
645
-
646
- /**
647
- * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
648
- *
649
- * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
650
- * the headers. The default null is left for backwards compatibilty.
651
- */
652
- public function setHttpHeaders($httpHeaders = null)
653
  {
654
- //use global _SERVER if $httpHeaders aren't defined
655
- if (!is_array($httpHeaders) || !count($httpHeaders)) {
656
- $httpHeaders = $_SERVER;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
657
  }
658
 
659
- //clear existing headers
660
- $this->httpHeaders = array();
 
 
 
 
 
 
 
 
 
 
661
 
662
- //Only save HTTP headers. In PHP land, that means only _SERVER vars that
663
- //start with HTTP_.
664
- foreach ($httpHeaders as $key => $value) {
665
- if (substr($key,0,5) == 'HTTP_') {
666
- $this->httpHeaders[$key] = $value;
 
 
 
 
 
 
667
  }
668
- }
669
- }
670
 
671
- /**
672
- * Retrieves the HTTP headers.
673
- *
674
- * @return array
675
- */
676
- public function getHttpHeaders()
677
- {
678
- return $this->httpHeaders;
679
- }
680
 
681
- /**
682
- * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
683
- * Simply null is returned.
684
- *
685
- * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
686
- * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
687
- * all-caps, HTTP_ prefixed, underscore seperated awesomeness.
688
- *
689
- * @return string|null The value of the header.
690
- */
691
- public function getHttpHeader($header)
692
- {
693
- //are we using PHP-flavored headers?
694
- if (strpos($header, '_') === false) {
695
- $header = str_replace('-', '_', $header);
696
- $header = strtoupper($header);
697
  }
698
 
699
- //test the alternate, too
700
- $altHeader = 'HTTP_' . $header;
701
-
702
- //Test both the regular and the HTTP_ prefix
703
- if (isset($this->httpHeaders[$header])) {
704
- return $this->httpHeaders[$header];
705
- } elseif (isset($this->httpHeaders[$altHeader])) {
706
- return $this->httpHeaders[$altHeader];
707
  }
708
 
709
- return null;
710
- }
711
-
712
- public function getMobileHeaders()
713
- {
714
- return self::$mobileHeaders;
715
- }
 
 
 
 
 
 
 
 
 
 
716
 
717
- /**
718
- * Get all possible HTTP headers that
719
- * can contain the User-Agent string.
720
- *
721
- * @return array List of HTTP headers.
722
- */
723
- public function getUaHttpHeaders()
724
- {
725
- return self::$uaHttpHeaders;
726
- }
727
 
728
- /**
729
- * Set the User-Agent to be used.
730
- *
731
- * @param string $userAgent The user agent string to set.
732
- *
733
- * @return string|null
734
- */
735
- public function setUserAgent($userAgent = null)
736
- {
737
- if (!empty($userAgent)) {
738
- return $this->userAgent = $userAgent;
739
- } else {
740
- $this->userAgent = null;
741
- foreach ($this->getUaHttpHeaders() as $altHeader) {
742
- if (!empty($this->httpHeaders[$altHeader])) { // @todo: should use getHttpHeader(), but it would be slow. (Serban)
743
- $this->userAgent .= $this->httpHeaders[$altHeader] . " ";
744
- }
745
  }
746
 
747
- return $this->userAgent = (!empty($this->userAgent) ? trim($this->userAgent) : null);
748
-
749
  }
750
- }
751
-
752
- /**
753
- * Retrieve the User-Agent.
754
- *
755
- * @return string|null The user agent if it's set.
756
- */
757
- public function getUserAgent()
758
- {
759
- return $this->userAgent;
760
- }
761
 
762
- /**
763
- * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
764
- * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
765
- *
766
- * @deprecated since version 2.6.9
767
- *
768
- * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
769
- * parameter is null which will default to self::DETECTION_TYPE_MOBILE.
770
- */
771
- public function setDetectionType($type = null)
772
- {
773
- if ($type === null) {
774
- $type = self::DETECTION_TYPE_MOBILE;
775
  }
776
 
777
- if ($type != self::DETECTION_TYPE_MOBILE && $type != self::DETECTION_TYPE_EXTENDED) {
778
- return;
 
 
 
 
 
 
 
779
  }
780
 
781
- $this->detectionType = $type;
782
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
783
 
784
- public function getMatchingRegex()
785
- {
786
- return $this->matchingRegex;
787
- }
788
 
789
- public function getMatchesArray()
790
- {
791
- return $this->matchesArray;
792
- }
793
 
794
- /**
795
- * Retrieve the list of known phone devices.
796
- *
797
- * @return array List of phone devices.
798
- */
799
- public static function getPhoneDevices()
800
- {
801
- return self::$phoneDevices;
802
- }
803
 
804
- /**
805
- * Retrieve the list of known tablet devices.
806
- *
807
- * @return array List of tablet devices.
808
- */
809
- public static function getTabletDevices()
810
- {
811
- return self::$tabletDevices;
812
- }
 
 
 
 
 
813
 
814
- /**
815
- * Alias for getBrowsers() method.
816
- *
817
- * @return array List of user agents.
818
- */
819
- public static function getUserAgents()
820
- {
821
- return self::getBrowsers();
822
- }
823
 
824
- /**
825
- * Retrieve the list of known browsers. Specifically, the user agents.
826
- *
827
- * @return array List of browsers / user agents.
828
- */
829
- public static function getBrowsers()
830
- {
831
- return self::$browsers;
832
- }
833
 
834
- /**
835
- * Retrieve the list of known utilities.
836
- *
837
- * @return array List of utilities.
838
- */
839
- public static function getUtilities()
840
- {
841
- return self::$utilities;
842
- }
843
 
844
- /**
845
- * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
846
- *
847
- * @deprecated since version 2.6.9
848
- *
849
- * @return array All the rules (but not extended).
850
- */
851
- public static function getMobileDetectionRules()
852
- {
853
- static $rules;
854
-
855
- if (!$rules) {
856
- $rules = array_merge(
857
- self::$phoneDevices,
858
- self::$tabletDevices,
859
- self::$operatingSystems,
860
- self::$browsers
861
- );
862
  }
863
 
864
- return $rules;
 
 
 
 
 
 
 
 
865
 
866
- }
 
 
 
 
 
 
 
 
867
 
868
- /**
869
- * Method gets the mobile detection rules + utilities.
870
- * The reason this is separate is because utilities rules
871
- * don't necessary imply mobile. This method is used inside
872
- * the new $detect->is('stuff') method.
873
- *
874
- * @deprecated since version 2.6.9
875
- *
876
- * @return array All the rules + extended.
877
- */
878
- public function getMobileDetectionRulesExtended()
879
- {
880
- static $rules;
881
-
882
- if (!$rules) {
883
- // Merge all rules together.
884
- $rules = array_merge(
885
- self::$phoneDevices,
886
- self::$tabletDevices,
887
- self::$operatingSystems,
888
- self::$browsers,
889
- self::$utilities
890
- );
891
  }
892
 
893
- return $rules;
894
- }
 
 
 
 
 
 
 
895
 
896
- /**
897
- * Retrieve the current set of rules.
898
- *
899
- * @deprecated since version 2.6.9
900
- *
901
- * @return array
902
- */
903
- public function getRules()
904
- {
905
- if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {
906
- return self::getMobileDetectionRulesExtended();
907
- } else {
908
- return self::getMobileDetectionRules();
909
  }
910
- }
911
 
912
- /**
913
- * Retrieve the list of mobile operating systems.
914
- *
915
- * @return array The list of mobile operating systems.
916
- */
917
- public static function getOperatingSystems()
918
- {
919
- return self::$operatingSystems;
920
- }
 
 
 
 
 
 
 
 
 
 
921
 
922
- /**
923
- * Check the HTTP headers for signs of mobile.
924
- * This is the fastest mobile check possible; it's used
925
- * inside isMobile() method.
926
- *
927
- * @return bool
928
- */
929
- public function checkHttpHeadersForMobile()
930
- {
931
 
932
- foreach ($this->getMobileHeaders() as $mobileHeader => $matchType) {
933
- if ( isset($this->httpHeaders[$mobileHeader]) ) {
934
- if ( is_array($matchType['matches']) ) {
935
- foreach ($matchType['matches'] as $_match) {
936
- if ( strpos($this->httpHeaders[$mobileHeader], $_match) !== false ) {
937
- return true;
938
- }
939
- }
940
 
941
- return false;
942
- } else {
943
- return true;
944
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
945
  }
946
- }
947
 
948
- return false;
 
949
 
950
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
951
 
952
- /**
953
- * Magic overloading method.
954
- *
955
- * @method boolean is[...]()
956
- * @param string $name
957
- * @param array $arguments
958
- * @return mixed
959
- * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
960
- */
961
- public function __call($name, $arguments)
962
- {
963
- //make sure the name starts with 'is', otherwise
964
- if (substr($name, 0, 2) != 'is') {
965
- throw new BadMethodCallException("No such method exists: $name");
966
  }
967
 
968
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
969
 
970
- $key = substr($name, 2);
 
 
 
 
 
971
 
972
- return $this->matchUAAgainstKey($key);
973
- }
974
 
975
- /**
976
- * Find a detection rule that matches the current User-agent.
977
- *
978
- * @param null $userAgent deprecated
979
- * @return boolean
980
- */
981
- protected function matchDetectionRulesAgainstUA($userAgent = null)
982
- {
983
- // Begin general search.
984
- foreach ($this->getRules() as $_regex) {
985
- if (empty($_regex)) {
986
- continue;
987
- }
988
- if ($this->match($_regex, $userAgent)) {
989
- return true;
990
- }
991
  }
992
 
993
- return false;
994
- }
995
-
996
- /**
997
- * Search for a certain key in the rules array.
998
- * If the key is found the try to match the corresponding
999
- * regex agains the User-Agent.
1000
- *
1001
- * @param string $key
1002
- * @param null $userAgent deprecated
1003
- * @return mixed
1004
- */
1005
- protected function matchUAAgainstKey($key, $userAgent = null)
1006
- {
1007
- // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
1008
- $key = strtolower($key);
1009
 
1010
- //change the keys to lower case
1011
- $_rules = array_change_key_case($this->getRules());
1012
 
1013
- if (array_key_exists($key, $_rules)) {
1014
- if (empty($_rules[$key])) {
1015
- return null;
1016
- }
1017
 
1018
- return $this->match($_rules[$key], $userAgent);
1019
  }
1020
 
1021
- return false;
1022
- }
1023
-
1024
- /**
1025
- * Check if the device is mobile.
1026
- * Returns true if any type of mobile device detected, including special ones
1027
- * @param null $userAgent deprecated
1028
- * @param null $httpHeaders deprecated
1029
- * @return bool
1030
- */
1031
- public function isMobile($userAgent = null, $httpHeaders = null)
1032
- {
 
 
 
 
 
1033
 
1034
- if ($httpHeaders) {
1035
- $this->setHttpHeaders($httpHeaders);
1036
  }
1037
 
1038
- if ($userAgent) {
1039
- $this->setUserAgent($userAgent);
1040
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1041
 
1042
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
 
1043
 
1044
- if ($this->checkHttpHeadersForMobile()) {
1045
- return true;
1046
- } else {
1047
- return $this->matchDetectionRulesAgainstUA();
1048
  }
1049
 
1050
- }
 
 
 
 
 
 
 
 
 
 
 
 
1051
 
1052
- /**
1053
- * Check if the device is a tablet.
1054
- * Return true if any type of tablet device is detected.
1055
- *
1056
- * @param string $userAgent deprecated
1057
- * @param array $httpHeaders deprecated
1058
- * @return bool
1059
- */
1060
- public function isTablet($userAgent = null, $httpHeaders = null)
1061
- {
1062
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1063
 
1064
- foreach (self::$tabletDevices as $_regex) {
1065
- if ($this->match($_regex, $userAgent)) {
 
1066
  return true;
 
 
1067
  }
 
1068
  }
1069
 
1070
- return false;
1071
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1072
 
1073
- /**
1074
- * This method checks for a certain property in the
1075
- * userAgent.
1076
- * @todo: The httpHeaders part is not yet used.
1077
- *
1078
- * @param string $key
1079
- * @param string $userAgent deprecated
1080
- * @param string $httpHeaders deprecated
1081
- * @return bool|int|null
1082
- */
1083
- public function is($key, $userAgent = null, $httpHeaders = null)
1084
- {
1085
- // Set the UA and HTTP headers only if needed (eg. batch mode).
1086
- if ($httpHeaders) {
1087
- $this->setHttpHeaders($httpHeaders);
1088
  }
1089
 
1090
- if ($userAgent) {
1091
- $this->setUserAgent($userAgent);
1092
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
1093
 
1094
- $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);
 
 
1095
 
1096
- return $this->matchUAAgainstKey($key);
1097
- }
1098
 
1099
- /**
1100
- * Some detection rules are relative (not standard),
1101
- * because of the diversity of devices, vendors and
1102
- * their conventions in representing the User-Agent or
1103
- * the HTTP headers.
1104
- *
1105
- * This method will be used to check custom regexes against
1106
- * the User-Agent string.
1107
- *
1108
- * @param $regex
1109
- * @param string $userAgent
1110
- * @return bool
1111
- *
1112
- * @todo: search in the HTTP headers too.
1113
- */
1114
- public function match($regex, $userAgent = null)
1115
- {
1116
- // Escape the special character which is the delimiter.
1117
- $regex = str_replace('/', '\/', $regex);
1118
- $match = (bool) preg_match('/'.$regex.'/is', (!empty($userAgent) ? $userAgent : $this->userAgent), $matches);
1119
- // If positive match is found, store the results for debug.
1120
- if ($match) {
1121
- $this->matchingRegex = $regex;
1122
- $this->matchesArray = $matches;
1123
  }
1124
 
1125
- return $match;
1126
- }
1127
-
1128
- /**
1129
- * Get the properties array.
1130
- *
1131
- * @return array
1132
- */
1133
- public static function getProperties()
1134
- {
1135
- return self::$properties;
1136
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
1137
 
1138
- /**
1139
- * Prepare the version number.
1140
- *
1141
- * @todo Remove the error supression from str_replace() call.
1142
- *
1143
- * @param string $ver The string version, like "2.6.21.2152";
1144
- *
1145
- * @return float
1146
- */
1147
- public function prepareVersionNo($ver)
1148
- {
1149
- $ver = str_replace(array('_', ' ', '/'), '.', $ver);
1150
- $arrVer = explode('.', $ver, 2);
1151
 
1152
- if (isset($arrVer[1])) {
1153
- $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
 
 
 
 
 
 
1154
  }
1155
 
1156
- return (float) implode('.', $arrVer);
1157
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1158
 
1159
- /**
1160
- * Check the version of the given property in the User-Agent.
1161
- * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
1162
- *
1163
- * @param string $propertyName The name of the property. See self::getProperties() array
1164
- * keys for all possible properties.
1165
- * @param string $type Either self::VERSION_TYPE_STRING to get a string value or
1166
- * self::VERSION_TYPE_FLOAT indicating a float value. This parameter
1167
- * is optional and defaults to self::VERSION_TYPE_STRING. Passing an
1168
- * invalid parameter will default to the this type as well.
1169
- *
1170
- * @return string|float The version of the property we are trying to extract.
1171
- */
1172
- public function version($propertyName, $type = self::VERSION_TYPE_STRING)
1173
- {
1174
- if (empty($propertyName)) {
1175
- return false;
1176
  }
1177
 
1178
- //set the $type to the default if we don't recognize the type
1179
- if ($type != self::VERSION_TYPE_STRING && $type != self::VERSION_TYPE_FLOAT) {
1180
- $type = self::VERSION_TYPE_STRING;
1181
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1182
 
1183
- $properties = self::getProperties();
 
1184
 
1185
- // Check if the property exists in the properties array.
1186
- if (array_key_exists($propertyName, $properties)) {
 
1187
 
1188
- // Prepare the pattern to be matched.
1189
- // Make sure we always deal with an array (string is converted).
1190
- $properties[$propertyName] = (array) $properties[$propertyName];
1191
 
1192
- foreach ($properties[$propertyName] as $propertyMatchString) {
1193
 
1194
- $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);
 
1195
 
1196
- // Escape the special character which is the delimiter.
1197
- $propertyPattern = str_replace('/', '\/', $propertyPattern);
1198
 
1199
- // Identify and extract the version.
1200
- preg_match('/'.$propertyPattern.'/is', $this->userAgent, $match);
1201
 
1202
- if (!empty($match[1])) {
1203
- $version = ( $type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1] );
1204
 
1205
- return $version;
1206
  }
1207
 
1208
  }
1209
 
 
1210
  }
1211
 
1212
- return false;
1213
- }
 
 
 
 
 
 
1214
 
1215
- /**
1216
- * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
1217
- *
1218
- * @return string One of the self::MOBILE_GRADE_* constants.
1219
- */
1220
- public function mobileGrade()
1221
- {
1222
- $isMobile = $this->isMobile();
1223
-
1224
- if (
1225
- // 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)
1226
- $this->isIOS() && $this->version('iPad', self::VERSION_TYPE_FLOAT)>=4.3 ||
1227
- $this->isIOS() && $this->version('iPhone', self::VERSION_TYPE_FLOAT)>=4.3 ||
1228
- $this->isIOS() && $this->version('iPod', self::VERSION_TYPE_FLOAT)>=4.3 ||
1229
 
1230
- // 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)
1231
- // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
1232
- // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
1233
- // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
1234
- ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) ||
1235
 
1236
- // 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)
1237
- $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT)>=7.5 ||
1238
 
1239
- // Tested on the Torch 9800 (6) and Style 9670 (6), BlackBerry® Torch 9810 (7), BlackBerry Z10 (10)
1240
- $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=6.0 ||
1241
- // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
1242
- $this->match('Playbook.*Tablet') ||
1243
 
1244
- // Palm WebOS (1.4-3.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0), HP TouchPad (3.0)
1245
- ( $this->version('webOS', self::VERSION_TYPE_FLOAT)>=1.4 && $this->match('Palm|Pre|Pixi') ) ||
1246
- // Palm WebOS 3.0 - Tested on HP TouchPad
1247
- $this->match('hp.*TouchPad') ||
1248
 
1249
- // Firefox Mobile 18 - Tested on Android 2.3 and 4.1 devices
1250
- ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=18 ) ||
1251
 
1252
- // Chrome for Android - Tested on Android 4.0, 4.1 device
1253
- ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=4.0 ) ||
1254
 
1255
- // Skyfire 4.1 - Tested on Android 2.3 device
1256
- ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT)>=4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) ||
1257
 
1258
- // Opera Mobile 11.5-12: Tested on Android 2.3
1259
- ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>=11.5 && $this->is('AndroidOS') ) ||
1260
 
1261
- // Meego 1.2 - Tested on Nokia 950 and N9
1262
- $this->is('MeeGoOS') ||
1263
 
1264
- // Tizen (pre-release) - Tested on early hardware
1265
- $this->is('Tizen') ||
1266
 
1267
- // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
1268
- // @todo: more tests here!
1269
- $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT)>=2.0 ||
1270
 
1271
- // UC Browser - Tested on Android 2.3 device
1272
- ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) ||
1273
 
1274
- // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
1275
- ( $this->match('Kindle Fire') ||
1276
- $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT)>=3.0 ) ||
1277
 
1278
- // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
1279
- $this->is('AndroidOS') && $this->is('NookTablet') ||
1280
 
1281
- // Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7
1282
- $this->version('Chrome', self::VERSION_TYPE_FLOAT)>=16 && !$isMobile ||
1283
 
1284
- // Safari Desktop 5-6 - Tested on OS X 10.7 and Windows 7
1285
- $this->version('Safari', self::VERSION_TYPE_FLOAT)>=5.0 && !$isMobile ||
1286
 
1287
- // Firefox Desktop 10-18 - Tested on OS X 10.7 and Windows 7
1288
- $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=10.0 && !$isMobile ||
1289
 
1290
- // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
1291
- $this->version('IE', self::VERSION_TYPE_FLOAT)>=7.0 && !$isMobile ||
1292
 
1293
- // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
1294
- $this->version('Opera', self::VERSION_TYPE_FLOAT)>=10 && !$isMobile
1295
- ){
1296
- return self::MOBILE_GRADE_A;
1297
- }
1298
 
1299
- if (
1300
- $this->isIOS() && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 ||
1301
- $this->isIOS() && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<4.3 ||
1302
- $this->isIOS() && $this->version('iPod', self::VERSION_TYPE_FLOAT)<4.3 ||
1303
 
1304
- // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
1305
- $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 ||
1306
 
1307
- //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
1308
- ($this->version('Opera Mini', self::VERSION_TYPE_FLOAT)>=5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT)<=7.0 &&
1309
- ($this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 || $this->is('iOS')) ) ||
1310
 
1311
- // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
1312
- $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||
1313
 
1314
- // @todo: report this (tested on Nokia N71)
1315
- $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>=11 && $this->is('SymbianOS')
1316
- ){
1317
- return self::MOBILE_GRADE_B;
1318
- }
1319
-
1320
- if (
1321
- // Blackberry 4.x - Tested on the Curve 8330
1322
- $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<=5.0 ||
1323
- // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
1324
- $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT)<=5.2 ||
1325
 
1326
- // Tested on original iPhone (3.1), iPhone 3 (3.2)
1327
- $this->isIOS() && $this->version('iPad', self::VERSION_TYPE_FLOAT)<=3.2 ||
1328
- $this->isIOS() && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<=3.2 ||
1329
- $this->isIOS() && $this->version('iPod', self::VERSION_TYPE_FLOAT)<=3.2 ||
 
 
 
 
 
 
 
 
 
 
 
 
1330
 
1331
- // Internet Explorer 7 and older - Tested on Windows XP
1332
- $this->version('IE', self::VERSION_TYPE_FLOAT)<=7.0 && !$isMobile
1333
- ){
1334
  return self::MOBILE_GRADE_C;
1335
  }
1336
-
1337
- //All older smartphone platforms and featurephones - Any device that doesn't support media queries
1338
- //will receive the basic, C grade experience.
1339
- return self::MOBILE_GRADE_C;
1340
  }
1341
- }
25
  * @version 2.8.11
26
  */
27
 
28
+ if( !class_exists('EFBL_Mobile_Detect') ) :
29
+ class EFBL_Mobile_Detect
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  {
31
+ /**
32
+ * Mobile detection type.
33
+ *
34
+ * @deprecated since version 2.6.9
35
+ */
36
+ const DETECTION_TYPE_MOBILE = 'mobile';
37
+
38
+ /**
39
+ * Extended detection type.
40
+ *
41
+ * @deprecated since version 2.6.9
42
+ */
43
+ const DETECTION_TYPE_EXTENDED = 'extended';
44
+
45
+ /**
46
+ * A frequently used regular expression to extract version #s.
47
+ *
48
+ * @deprecated since version 2.6.9
49
+ */
50
+ const VER = '([\w._\+]+)';
51
+
52
+ /**
53
+ * Top-level device.
54
+ */
55
+ const MOBILE_GRADE_A = 'A';
56
+
57
+ /**
58
+ * Mid-level device.
59
+ */
60
+ const MOBILE_GRADE_B = 'B';
61
+
62
+ /**
63
+ * Low-level device.
64
+ */
65
+ const MOBILE_GRADE_C = 'C';
66
+
67
+ /**
68
+ * Stores the version number of the current release.
69
+ */
70
+ const VERSION = '2.8.11';
71
+
72
+ /**
73
+ * A type for the version() method indicating a string return value.
74
+ */
75
+ const VERSION_TYPE_STRING = 'text';
76
+
77
+ /**
78
+ * A type for the version() method indicating a float return value.
79
+ */
80
+ const VERSION_TYPE_FLOAT = 'float';
81
+
82
+ /**
83
+ * The User-Agent HTTP header is stored in here.
84
+ * @var string
85
+ */
86
+ protected $userAgent = null;
87
+
88
+ /**
89
+ * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
90
+ * @var array
91
+ */
92
+ protected $httpHeaders = array();
93
+
94
+ /**
95
+ * The matching Regex.
96
+ * This is good for debug.
97
+ * @var string
98
+ */
99
+ protected $matchingRegex = null;
100
+
101
+ /**
102
+ * The matches extracted from the regex expression.
103
+ * This is good for debug.
104
+ * @var string
105
+ */
106
+ protected $matchesArray = null;
107
+
108
+ /**
109
+ * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
110
+ *
111
+ * @deprecated since version 2.6.9
112
+ *
113
+ * @var string
114
+ */
115
+ protected $detectionType = self::DETECTION_TYPE_MOBILE;
116
+
117
+ /**
118
+ * HTTP headers that trigger the 'isMobile' detection
119
+ * to be true.
120
+ *
121
+ * @var array
122
+ */
123
+ protected static $mobileHeaders = array(
124
+
125
+ 'HTTP_ACCEPT' => array('matches' => array(
126
+ // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
127
+ 'application/x-obml2d',
128
+ // BlackBerry devices.
129
+ 'application/vnd.rim.html',
130
+ 'text/vnd.wap.wml',
131
+ 'application/vnd.wap.xhtml+xml'
132
+ )),
133
+ 'HTTP_X_WAP_PROFILE' => null,
134
+ 'HTTP_X_WAP_CLIENTID' => null,
135
+ 'HTTP_WAP_CONNECTION' => null,
136
+ 'HTTP_PROFILE' => null,
137
+ // Reported by Opera on Nokia devices (eg. C3).
138
+ 'HTTP_X_OPERAMINI_PHONE_UA' => null,
139
+ 'HTTP_X_NOKIA_GATEWAY_ID' => null,
140
+ 'HTTP_X_ORANGE_ID' => null,
141
+ 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
142
+ 'HTTP_X_HUAWEI_USERID' => null,
143
+ // Reported by Windows Smartphones.
144
+ 'HTTP_UA_OS' => null,
145
+ // Reported by Verizon, Vodafone proxy system.
146
+ 'HTTP_X_MOBILE_GATEWAY' => null,
147
+ // Seen this on HTC Sensation. SensationXE_Beats_Z715e.
148
+ 'HTTP_X_ATT_DEVICEID' => null,
149
+ // Seen this on a HTC.
150
+ 'HTTP_UA_CPU' => array('matches' => array('ARM')),
151
+ );
152
+
153
+ /**
154
+ * List of mobile devices (phones).
155
+ *
156
+ * @var array
157
+ */
158
+ protected static $phoneDevices = array(
159
+ 'iPhone' => '\biPhone\b|\biPod\b', // |\biTunes
160
+ 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
161
+ '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',
162
+ 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6',
163
+ // @todo: Is 'Dell Streak' a tablet or a phone? ;)
164
+ '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',
165
+ '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',
166
+ 'Samsung' => 'Samsung|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',
167
+ '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)',
168
+ 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533',
169
+ 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile',
170
+ // http://www.micromaxinfo.com/mobiles/smartphones
171
+ // Added because the codes might conflict with Acer Tablets.
172
+ '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',
173
+ // @todo Complete the regex.
174
+ 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ;
175
+ 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
176
+ // http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
177
+ // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
178
+ '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',
179
+ // http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
180
+ 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
181
+ 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)',
182
+ // Added simvalley mobile just for fun. They have some interesting devices.
183
+ // http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
184
+ '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',
185
+ // Wolfgang - a brand that is sold by Aldi supermarkets.
186
+ // http://www.wolfgangmobile.com/
187
+ 'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q',
188
+ 'Alcatel' => 'Alcatel',
189
+ 'Nintendo' => 'Nintendo 3DS',
190
+ // http://en.wikipedia.org/wiki/Amoi
191
+ 'Amoi' => 'Amoi',
192
+ // http://en.wikipedia.org/wiki/INQ
193
+ 'INQ' => 'INQ',
194
+ // @Tapatalk is a mobile app; http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039
195
+ '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',
196
+ );
197
+
198
+ /**
199
+ * List of tablet devices.
200
+ *
201
+ * @var array
202
+ */
203
+ protected static $tabletDevices = array(
204
+ 'iPad' => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic.
205
+ 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)|^.*Android.*Nexus(?:(?!Mobile).)*$',
206
+ '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-I9205|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-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T707A|SM-T807A|SM-T237P|SM-T807P|SM-P607T|SM-T217T|SM-T337T', // SCH-P709|SCH-P729|SM-T2558 - Samsung Mega - treat them like a regular phone.
207
+ // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
208
+ 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI)\b',
209
+ // Only the Surface tablets with Windows RT are considered mobile.
210
+ // http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
211
+ 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)',
212
+ // http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
213
+ 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10',
214
+ // Watch out for PadFone, see #132.
215
+ // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/
216
+ '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',
217
+ 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
218
+ 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410',
219
+ 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
220
+ 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
221
+ // http://www.acer.ro/ac/ro/RO/content/drivers
222
+ // http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
223
+ // http://us.acer.com/ac/en/US/content/group/tablets
224
+ // http://www.acer.de/ac/de/DE/content/models/tablets/
225
+ // Can conflict with Micromax and Motorola phones codes.
226
+ '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',
227
+ // http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
228
+ // http://us.toshiba.com/tablets/tablet-finder
229
+ // http://www.toshiba.co.jp/regza/tablet/
230
+ 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
231
+ // http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
232
+ // http://www.lg.com/us/tablets
233
+ 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b',
234
+ 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
235
+ // Prestigio Tablets http://www.prestigio.com/support
236
+ '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',
237
+ // http://support.lenovo.com/en_GB/downloads/default.page?#
238
+ 'LenovoTablet' => 'Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)',
239
+ // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets
240
+ 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7',
241
+ // http://www.yarvik.com/en/matrix/tablets/
242
+ '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',
243
+ 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
244
+ 'ArnovaTablet' => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2',
245
+ // http://www.intenso.de/kategorie_en.php?kategorie=33
246
+ // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate
247
+ 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004',
248
+ // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
249
+ 'IRUTablet' => 'M702pro',
250
+ 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
251
+ // http://www.e-boda.ro/tablete-pc.html
252
+ 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
253
+ // http://www.allview.ro/produse/droseries/lista-tablete-pc/
254
+ 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
255
+ // http://wiki.archosfans.com/index.php?title=Main_Page
256
+ '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',
257
+ // http://www.ainol.com/plugin.php?identifier=ainol&module=product
258
+ 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
259
+ // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
260
+ // Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
261
+ // http://www.sony.jp/support/tablet/
262
+ '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',
263
+ // 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
264
+ 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b',
265
+ // db + http://www.cube-tablet.com/buy-products.html
266
+ 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
267
+ // http://www.cobyusa.com/?p=pcat&pcat_id=3001
268
+ 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
269
+ // http://www.match.net.cn/products.asp
270
+ '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',
271
+ // http://www.msi.com/support
272
+ // @todo Research the Windows Tablets.
273
+ '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',
274
+ // @todo http://www.kyoceramobile.com/support/drivers/
275
+ // 'KyoceraTablet' => null,
276
+ // @todo http://intexuae.com/index.php/category/mobile-devices/tablets-products/
277
+ // 'IntextTablet' => null,
278
+ // http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
279
+ // http://www.imp3.net/14/show.php?itemid=20454
280
+ 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
281
+ // http://www.rock-chips.com/index.php?do=prod&pid=2
282
+ 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
283
+ // http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
284
+ 'FlyTablet' => 'IQ310|Fly Vision',
285
+ // http://www.bqreaders.com/gb/tablets-prices-sale.html
286
+ 'bqTablet' => 'bq.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant)|Maxwell.*Lite|Maxwell.*Plus',
287
+ // http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
288
+ // http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
289
+ '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',
290
+ // Nec or Medias Tab
291
+ 'NecTablet' => '\bN-06D|\bN-08D',
292
+ // Pantech Tablets: http://www.pantechusa.com/phones/
293
+ 'PantechTablet' => 'Pantech.*P4100',
294
+ // Broncho Tablets: http://www.broncho.cn/ (hard to find)
295
+ 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
296
+ // http://versusuk.com/support.html
297
+ 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
298
+ // http://www.zync.in/index.php/our-products/tablet-phablets
299
+ 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
300
+ // http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
301
+ 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
302
+ // https://www.nabitablet.com/
303
+ 'NabiTablet' => 'Android.*\bNabi',
304
+ 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
305
+ // French Danew Tablets http://www.danew.com/produits-tablette.php
306
+ 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
307
+ // Texet Tablets and Readers http://www.texet.ru/tablet/
308
+ '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',
309
+ // Avoid detecting 'PLAYSTATION 3' as mobile.
310
+ 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
311
+ // http://www.trekstor.de/surftabs.html
312
+ 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab',
313
+ // http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets
314
+ 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
315
+ // http://www.advandigital.com/index.php?link=content-product&jns=JP001
316
+ // because of the short codenames we have to include whitespaces to reduce the possible conflicts.
317
+ '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 ',
318
+ // http://www.danytech.com/category/tablet-pc
319
+ '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',
320
+ // http://www.galapad.net/product.html
321
+ 'GalapadTablet' => 'Android.*\bG1\b',
322
+ // http://www.micromaxinfo.com/tablet/funbook
323
+ 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
324
+ // http://www.karbonnmobiles.com/products_tablet.php
325
+ 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
326
+ // http://www.myallfine.com/Products.asp
327
+ 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
328
+ // http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
329
+ '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',
330
+ // http://www.yonesnav.com/products/products.php
331
+ 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
332
+ // http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
333
+ // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
334
+ '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',
335
+ // http://www.gloryunion.cn/products.asp
336
+ // http://www.allwinnertech.com/en/apply/mobile.html
337
+ // http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
338
+ // @todo: Softwiner tablets?
339
+ // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
340
+ '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
341
+ // http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
342
+ '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',
343
+ // http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
344
+ // @todo: add more tests.
345
+ 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)',
346
+ // http://hclmetablet.com/India/index.php
347
+ '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',
348
+ // http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
349
+ 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
350
+ // http://www.visture.com/index.asp
351
+ 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
352
+ // http://www.mijncresta.nl/tablet
353
+ 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
354
+ // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309
355
+ 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
356
+ // Concorde tab
357
+ 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
358
+ // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/
359
+ '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',
360
+ // Modecom Tablets - http://www.modecom.eu/tablets/portal/
361
+ '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',
362
+ // Vonino Tablets - http://www.vonino.eu/tablets
363
+ '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',
364
+ // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0
365
+ 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
366
+ // Storex Tablets - http://storex.fr/espace_client/support.html
367
+ // @note: no need to add all the tablet codes since they are guided by the first regex.
368
+ 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
369
+ // Generic Vodafone tablets.
370
+ 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7',
371
+ // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb
372
+ // Aka: http://www.essentielb.fr/
373
+ 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
374
+ // Ross & Moor - http://ross-moor.ru/
375
+ 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
376
+ // i-mobile http://product.i-mobilephone.com/Mobile_Device
377
+ 'iMobileTablet' => 'i-mobile i-note',
378
+ // http://www.tolino.de/de/vergleichen/
379
+ 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
380
+ // AudioSonic - a Kmart brand
381
+ // 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
382
+ 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
383
+ // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/
384
+ // @todo: add them gradually to avoid conflicts.
385
+ 'AMPETablet' => 'Android.* A78 ',
386
+ // Skk Mobile - http://skkmobile.com.ph/product_tablets.php
387
+ 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
388
+ // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1
389
+ 'TecnoTablet' => 'TECNO P9',
390
+ // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3
391
+ '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',
392
+ // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/
393
+ '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)',
394
+ // http://www.intracon.eu/tablet
395
+ 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
396
+ // http://www.xoro.de/produkte/
397
+ // @note: Might be the same brand with 'Simply tablets'
398
+ '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',
399
+ // http://www1.viewsonic.com/products/computing/tablets/
400
+ 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
401
+ // http://www.odys.de/web/internet-tablet_en.html
402
+ 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10',
403
+ // http://www.captiva-power.de/products.html#tablets-en
404
+ 'CaptivaTablet' => 'CAPTIVA PAD',
405
+ // IconBIT - http://www.iconbit.com/products/tablets/
406
+ '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',
407
+ // http://www.teclast.com/topic.php?channelID=70&topicID=140&pid=63
408
+ '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',
409
+ 'JaytechTablet' => 'TPC-PA762',
410
+ 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010',
411
+ // http://www.digma.ru/support/download/
412
+ // @todo: Ebooks also (if requested)
413
+ 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b',
414
+ // http://www.evolioshop.com/ro/tablete-pc.html
415
+ // http://www.evolio.ro/support/downloads_static.html?cat=2
416
+ // @todo: Research some more
417
+ 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b',
418
+ // @todo http://www.lavamobiles.com/tablets-data-cards
419
+ 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY',
420
+ // https://www.celkonmobiles.com/?_a=categoryphones&sid=2
421
+ 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b',
422
+ // http://www.mi.com/en
423
+ 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b',
424
+ // http://www.nbru.cn/index.html
425
+ 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One',
426
+ // http://navroad.com/products/produkty/tablety/
427
+ 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI',
428
+ // http://www.datawind.com/ubislate/
429
+ 'UbislateTablet' => 'UbiSlate[\s]?7C',
430
+ // http://www.pocketbook-int.com/ru/support
431
+ 'PocketBookTablet' => 'Pocketbook',
432
+ // http://www.tesco.com/direct/hudl/
433
+ 'Hudl' => 'Hudl HT7S3',
434
+ // http://www.telstra.com.au/home-phone/thub-2/
435
+ 'TelstraTablet' => 'T-Hub2',
436
+ '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|\bJolla\b'
437
+ );
438
+
439
+ /**
440
+ * List of mobile Operating Systems.
441
+ *
442
+ * @var array
443
+ */
444
+ protected static $operatingSystems = array(
445
+ 'AndroidOS' => 'Android',
446
+ 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
447
+ 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
448
+ 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
449
+ // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
450
+ 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
451
+ // @reference: http://en.wikipedia.org/wiki/Windows_Phone
452
+ // http://wifeng.cn/?r=blog&a=view&id=106
453
+ // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
454
+ // http://msdn.microsoft.com/library/ms537503.aspx
455
+ 'WindowsPhoneOS' => 'Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;',
456
+ 'iOS' => '\biPhone.*Mobile|\biPod|\biPad',
457
+ // http://en.wikipedia.org/wiki/MeeGo
458
+ // @todo: research MeeGo in UAs
459
+ 'MeeGoOS' => 'MeeGo',
460
+ // http://en.wikipedia.org/wiki/Maemo
461
+ // @todo: research Maemo in UAs
462
+ 'MaemoOS' => 'Maemo',
463
+ 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
464
+ 'webOS' => 'webOS|hpwOS',
465
+ 'badaOS' => '\bBada\b',
466
+ 'BREWOS' => 'BREW',
467
+ );
468
+
469
+ /**
470
+ * List of mobile User Agents.
471
+ *
472
+ * @var array
473
+ */
474
+ protected static $browsers = array(
475
+ // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
476
+ 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
477
+ 'Dolfin' => '\bDolfin\b',
478
+ 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+',
479
+ 'Skyfire' => 'Skyfire',
480
+ 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
481
+ 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile',
482
+ 'Bolt' => 'bolt',
483
+ 'TeaShark' => 'teashark',
484
+ 'Blazer' => 'Blazer',
485
+ // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
486
+ 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari',
487
+ // http://en.wikipedia.org/wiki/Midori_(web_browser)
488
+ //'Midori' => 'midori',
489
+ 'Tizen' => 'Tizen',
490
+ 'UCBrowser' => 'UC.*Browser|UCWEB',
491
+ 'baiduboxapp' => 'baiduboxapp',
492
+ 'baidubrowser' => 'baidubrowser',
493
+ // https://github.com/serbanghita/Mobile-Detect/issues/7
494
+ 'DiigoBrowser' => 'DiigoBrowser',
495
+ // http://www.puffinbrowser.com/index.php
496
+ 'Puffin' => 'Puffin',
497
+ // http://mercury-browser.com/index.html
498
+ 'Mercury' => '\bMercury\b',
499
+ // http://en.wikipedia.org/wiki/Obigo_Browser
500
+ 'ObigoBrowser' => 'Obigo',
501
+ // http://en.wikipedia.org/wiki/NetFront
502
+ 'NetFront' => 'NF-Browser',
503
+ // @reference: http://en.wikipedia.org/wiki/Minimo
504
+ // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
505
+ 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger',
506
+ );
507
+
508
+ /**
509
+ * Utilities.
510
+ *
511
+ * @var array
512
+ */
513
+ protected static $utilities = array(
514
+ // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
515
+ // http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
516
+ // https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
517
+ 'DesktopMode' => 'WPDesktop',
518
+ 'TV' => 'SonyDTV|HbbTV', // experimental
519
+ 'WebKit' => '(webkit)[ /]([\w.]+)',
520
+ 'Bot' => 'Googlebot|YandexBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|facebookexternalhit',
521
+ 'MobileBot' => 'Googlebot-Mobile|YahooSeeker/M1A1-R2D2',
522
+ // @todo: Include JXD consoles.
523
+ 'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|PLAYSTATION|Xbox)\b',
524
+ 'Watch' => 'SM-V700',
525
+ );
526
+
527
+ /**
528
+ * All possible HTTP headers that represent the
529
+ * User-Agent string.
530
+ *
531
+ * @var array
532
+ */
533
+ protected static $uaHttpHeaders = array(
534
+ // The default User-Agent string.
535
+ 'HTTP_USER_AGENT',
536
+ // Header can occur on devices using Opera Mini.
537
+ 'HTTP_X_OPERAMINI_PHONE_UA',
538
+ // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
539
+ 'HTTP_X_DEVICE_USER_AGENT',
540
+ 'HTTP_X_ORIGINAL_USER_AGENT',
541
+ 'HTTP_X_SKYFIRE_PHONE',
542
+ 'HTTP_X_BOLT_PHONE_UA',
543
+ 'HTTP_DEVICE_STOCK_UA',
544
+ 'HTTP_X_UCBROWSER_DEVICE_UA'
545
+ );
546
+
547
+ /**
548
+ * The individual segments that could exist in a User-Agent string. VER refers to the regular
549
+ * expression defined in the constant self::VER.
550
+ *
551
+ * @var array
552
+ */
553
+ protected static $properties = array(
554
+
555
+ // Build
556
+ 'Mobile' => 'Mobile/[VER]',
557
+ 'Build' => 'Build/[VER]',
558
+ 'Version' => 'Version/[VER]',
559
+ 'VendorID' => 'VendorID/[VER]',
560
+
561
+ // Devices
562
+ 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
563
+ 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
564
+ 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
565
+ //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
566
+ 'Kindle' => 'Kindle/[VER]',
567
+
568
+ // Browser
569
+ 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
570
+ 'Coast' => array('Coast/[VER]'),
571
+ 'Dolfin' => 'Dolfin/[VER]',
572
+ // @reference: https://developer.mozilla.org/en-US/docs/User_Agent_Strings_Reference
573
+ 'Firefox' => 'Firefox/[VER]',
574
+ 'Fennec' => 'Fennec/[VER]',
575
+ // @reference: http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
576
+ 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];'),
577
+ // http://en.wikipedia.org/wiki/NetFront
578
+ 'NetFront' => 'NetFront/[VER]',
579
+ 'NokiaBrowser' => 'NokiaBrowser/[VER]',
580
+ 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),
581
+ 'Opera Mini' => 'Opera Mini/[VER]',
582
+ 'Opera Mobi' => 'Version/[VER]',
583
+ 'UC Browser' => 'UC Browser[VER]',
584
+ 'MQQBrowser' => 'MQQBrowser/[VER]',
585
+ 'MicroMessenger' => 'MicroMessenger/[VER]',
586
+ 'baiduboxapp' => 'baiduboxapp/[VER]',
587
+ 'baidubrowser' => 'baidubrowser/[VER]',
588
+ 'Iron' => 'Iron/[VER]',
589
+ // @note: Safari 7534.48.3 is actually Version 5.1.
590
+ // @note: On BlackBerry the Version is overwriten by the OS.
591
+ 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ),
592
+ 'Skyfire' => 'Skyfire/[VER]',
593
+ 'Tizen' => 'Tizen/[VER]',
594
+ 'Webkit' => 'webkit[ /][VER]',
595
+
596
+ // Engine
597
+ 'Gecko' => 'Gecko/[VER]',
598
+ 'Trident' => 'Trident/[VER]',
599
+ 'Presto' => 'Presto/[VER]',
600
+
601
+ // OS
602
+ 'iOS' => ' \bOS\b [VER] ',
603
+ 'Android' => 'Android [VER]',
604
+ 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),
605
+ 'BREW' => 'BREW [VER]',
606
+ 'Java' => 'Java/[VER]',
607
+ // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
608
+ // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
609
+ 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'),
610
+ 'Windows Phone' => 'Windows Phone [VER]',
611
+ 'Windows CE' => 'Windows CE/[VER]',
612
+ // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
613
+ 'Windows NT' => 'Windows NT [VER]',
614
+ 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
615
+ 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
616
+ );
617
+
618
+ /**
619
+ * Construct an instance of this class.
620
+ *
621
+ * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored.
622
+ * If left empty, will use the global _SERVER['HTTP_*'] vars instead.
623
+ * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
624
+ * from the $headers array instead.
625
+ */
626
+ public function __construct(
627
+ array $headers = null,
628
+ $userAgent = null
629
+ ) {
630
+ $this->setHttpHeaders($headers);
631
+ $this->setUserAgent($userAgent);
632
  }
633
 
634
+ /**
635
+ * Get the current script version.
636
+ * This is useful for the demo.php file,
637
+ * so people can check on what version they are testing
638
+ * for mobile devices.
639
+ *
640
+ * @return string The version number in semantic version format.
641
+ */
642
+ public static function getScriptVersion()
643
+ {
644
+ return self::VERSION;
645
+ }
646
 
647
+ /**
648
+ * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
649
+ *
650
+ * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
651
+ * the headers. The default null is left for backwards compatibilty.
652
+ */
653
+ public function setHttpHeaders($httpHeaders = null)
654
+ {
655
+ //use global _SERVER if $httpHeaders aren't defined
656
+ if (!is_array($httpHeaders) || !count($httpHeaders)) {
657
+ $httpHeaders = $_SERVER;
658
  }
 
 
659
 
660
+ //clear existing headers
661
+ $this->httpHeaders = array();
 
 
 
 
 
 
 
662
 
663
+ //Only save HTTP headers. In PHP land, that means only _SERVER vars that
664
+ //start with HTTP_.
665
+ foreach ($httpHeaders as $key => $value) {
666
+ if (substr($key,0,5) == 'HTTP_') {
667
+ $this->httpHeaders[$key] = $value;
668
+ }
669
+ }
 
 
 
 
 
 
 
 
 
670
  }
671
 
672
+ /**
673
+ * Retrieves the HTTP headers.
674
+ *
675
+ * @return array
676
+ */
677
+ public function getHttpHeaders()
678
+ {
679
+ return $this->httpHeaders;
680
  }
681
 
682
+ /**
683
+ * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
684
+ * Simply null is returned.
685
+ *
686
+ * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
687
+ * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
688
+ * all-caps, HTTP_ prefixed, underscore seperated awesomeness.
689
+ *
690
+ * @return string|null The value of the header.
691
+ */
692
+ public function getHttpHeader($header)
693
+ {
694
+ //are we using PHP-flavored headers?
695
+ if (strpos($header, '_') === false) {
696
+ $header = str_replace('-', '_', $header);
697
+ $header = strtoupper($header);
698
+ }
699
 
700
+ //test the alternate, too
701
+ $altHeader = 'HTTP_' . $header;
 
 
 
 
 
 
 
 
702
 
703
+ //Test both the regular and the HTTP_ prefix
704
+ if (isset($this->httpHeaders[$header])) {
705
+ return $this->httpHeaders[$header];
706
+ } elseif (isset($this->httpHeaders[$altHeader])) {
707
+ return $this->httpHeaders[$altHeader];
 
 
 
 
 
 
 
 
 
 
 
 
708
  }
709
 
710
+ return null;
 
711
  }
 
 
 
 
 
 
 
 
 
 
 
712
 
713
+ public function getMobileHeaders()
714
+ {
715
+ return self::$mobileHeaders;
 
 
 
 
 
 
 
 
 
 
716
  }
717
 
718
+ /**
719
+ * Get all possible HTTP headers that
720
+ * can contain the User-Agent string.
721
+ *
722
+ * @return array List of HTTP headers.
723
+ */
724
+ public function getUaHttpHeaders()
725
+ {
726
+ return self::$uaHttpHeaders;
727
  }
728
 
729
+ /**
730
+ * Set the User-Agent to be used.
731
+ *
732
+ * @param string $userAgent The user agent string to set.
733
+ *
734
+ * @return string|null
735
+ */
736
+ public function setUserAgent($userAgent = null)
737
+ {
738
+ if (!empty($userAgent)) {
739
+ return $this->userAgent = $userAgent;
740
+ } else {
741
+ $this->userAgent = null;
742
+ foreach ($this->getUaHttpHeaders() as $altHeader) {
743
+ if (!empty($this->httpHeaders[$altHeader])) { // @todo: should use getHttpHeader(), but it would be slow. (Serban)
744
+ $this->userAgent .= $this->httpHeaders[$altHeader] . " ";
745
+ }
746
+ }
747
 
748
+ return $this->userAgent = (!empty($this->userAgent) ? trim($this->userAgent) : null);
 
 
 
749
 
750
+ }
751
+ }
 
 
752
 
753
+ /**
754
+ * Retrieve the User-Agent.
755
+ *
756
+ * @return string|null The user agent if it's set.
757
+ */
758
+ public function getUserAgent()
759
+ {
760
+ return $this->userAgent;
761
+ }
762
 
763
+ /**
764
+ * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
765
+ * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
766
+ *
767
+ * @deprecated since version 2.6.9
768
+ *
769
+ * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
770
+ * parameter is null which will default to self::DETECTION_TYPE_MOBILE.
771
+ */
772
+ public function setDetectionType($type = null)
773
+ {
774
+ if ($type === null) {
775
+ $type = self::DETECTION_TYPE_MOBILE;
776
+ }
777
 
778
+ if ($type != self::DETECTION_TYPE_MOBILE && $type != self::DETECTION_TYPE_EXTENDED) {
779
+ return;
780
+ }
 
 
 
 
 
 
781
 
782
+ $this->detectionType = $type;
783
+ }
 
 
 
 
 
 
 
784
 
785
+ public function getMatchingRegex()
786
+ {
787
+ return $this->matchingRegex;
788
+ }
 
 
 
 
 
789
 
790
+ public function getMatchesArray()
791
+ {
792
+ return $this->matchesArray;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
793
  }
794
 
795
+ /**
796
+ * Retrieve the list of known phone devices.
797
+ *
798
+ * @return array List of phone devices.
799
+ */
800
+ public static function getPhoneDevices()
801
+ {
802
+ return self::$phoneDevices;
803
+ }
804
 
805
+ /**
806
+ * Retrieve the list of known tablet devices.
807
+ *
808
+ * @return array List of tablet devices.
809
+ */
810
+ public static function getTabletDevices()
811
+ {
812
+ return self::$tabletDevices;
813
+ }
814
 
815
+ /**
816
+ * Alias for getBrowsers() method.
817
+ *
818
+ * @return array List of user agents.
819
+ */
820
+ public static function getUserAgents()
821
+ {
822
+ return self::getBrowsers();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
823
  }
824
 
825
+ /**
826
+ * Retrieve the list of known browsers. Specifically, the user agents.
827
+ *
828
+ * @return array List of browsers / user agents.
829
+ */
830
+ public static function getBrowsers()
831
+ {
832
+ return self::$browsers;
833
+ }
834
 
835
+ /**
836
+ * Retrieve the list of known utilities.
837
+ *
838
+ * @return array List of utilities.
839
+ */
840
+ public static function getUtilities()
841
+ {
842
+ return self::$utilities;
 
 
 
 
 
843
  }
 
844
 
845
+ /**
846
+ * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
847
+ *
848
+ * @deprecated since version 2.6.9
849
+ *
850
+ * @return array All the rules (but not extended).
851
+ */
852
+ public static function getMobileDetectionRules()
853
+ {
854
+ static $rules;
855
+
856
+ if (!$rules) {
857
+ $rules = array_merge(
858
+ self::$phoneDevices,
859
+ self::$tabletDevices,
860
+ self::$operatingSystems,
861
+ self::$browsers
862
+ );
863
+ }
864
 
865
+ return $rules;
 
 
 
 
 
 
 
 
866
 
867
+ }
 
 
 
 
 
 
 
868
 
869
+ /**
870
+ * Method gets the mobile detection rules + utilities.
871
+ * The reason this is separate is because utilities rules
872
+ * don't necessary imply mobile. This method is used inside
873
+ * the new $detect->is('stuff') method.
874
+ *
875
+ * @deprecated since version 2.6.9
876
+ *
877
+ * @return array All the rules + extended.
878
+ */
879
+ public function getMobileDetectionRulesExtended()
880
+ {
881
+ static $rules;
882
+
883
+ if (!$rules) {
884
+ // Merge all rules together.
885
+ $rules = array_merge(
886
+ self::$phoneDevices,
887
+ self::$tabletDevices,
888
+ self::$operatingSystems,
889
+ self::$browsers,
890
+ self::$utilities
891
+ );
892
  }
 
893
 
894
+ return $rules;
895
+ }
896
 
897
+ /**
898
+ * Retrieve the current set of rules.
899
+ *
900
+ * @deprecated since version 2.6.9
901
+ *
902
+ * @return array
903
+ */
904
+ public function getRules()
905
+ {
906
+ if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {
907
+ return self::getMobileDetectionRulesExtended();
908
+ } else {
909
+ return self::getMobileDetectionRules();
910
+ }
911
+ }
912
 
913
+ /**
914
+ * Retrieve the list of mobile operating systems.
915
+ *
916
+ * @return array The list of mobile operating systems.
917
+ */
918
+ public static function getOperatingSystems()
919
+ {
920
+ return self::$operatingSystems;
 
 
 
 
 
 
921
  }
922
 
923
+ /**
924
+ * Check the HTTP headers for signs of mobile.
925
+ * This is the fastest mobile check possible; it's used
926
+ * inside isMobile() method.
927
+ *
928
+ * @return bool
929
+ */
930
+ public function checkHttpHeadersForMobile()
931
+ {
932
+
933
+ foreach ($this->getMobileHeaders() as $mobileHeader => $matchType) {
934
+ if ( isset($this->httpHeaders[$mobileHeader]) ) {
935
+ if ( is_array($matchType['matches']) ) {
936
+ foreach ($matchType['matches'] as $_match) {
937
+ if ( strpos($this->httpHeaders[$mobileHeader], $_match) !== false ) {
938
+ return true;
939
+ }
940
+ }
941
 
942
+ return false;
943
+ } else {
944
+ return true;
945
+ }
946
+ }
947
+ }
948
 
949
+ return false;
 
950
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
951
  }
952
 
953
+ /**
954
+ * Magic overloading method.
955
+ *
956
+ * @method boolean is[...]()
957
+ * @param string $name
958
+ * @param array $arguments
959
+ * @return mixed
960
+ * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
961
+ */
962
+ public function __call($name, $arguments)
963
+ {
964
+ //make sure the name starts with 'is', otherwise
965
+ if (substr($name, 0, 2) != 'is') {
966
+ throw new BadMethodCallException("No such method exists: $name");
967
+ }
 
968
 
969
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
 
970
 
971
+ $key = substr($name, 2);
 
 
 
972
 
973
+ return $this->matchUAAgainstKey($key);
974
  }
975
 
976
+ /**
977
+ * Find a detection rule that matches the current User-agent.
978
+ *
979
+ * @param null $userAgent deprecated
980
+ * @return boolean
981
+ */
982
+ protected function matchDetectionRulesAgainstUA($userAgent = null)
983
+ {
984
+ // Begin general search.
985
+ foreach ($this->getRules() as $_regex) {
986
+ if (empty($_regex)) {
987
+ continue;
988
+ }
989
+ if ($this->match($_regex, $userAgent)) {
990
+ return true;
991
+ }
992
+ }
993
 
994
+ return false;
 
995
  }
996
 
997
+ /**
998
+ * Search for a certain key in the rules array.
999
+ * If the key is found the try to match the corresponding
1000
+ * regex agains the User-Agent.
1001
+ *
1002
+ * @param string $key
1003
+ * @param null $userAgent deprecated
1004
+ * @return mixed
1005
+ */
1006
+ protected function matchUAAgainstKey($key, $userAgent = null)
1007
+ {
1008
+ // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
1009
+ $key = strtolower($key);
1010
+
1011
+ //change the keys to lower case
1012
+ $_rules = array_change_key_case($this->getRules());
1013
+
1014
+ if (array_key_exists($key, $_rules)) {
1015
+ if (empty($_rules[$key])) {
1016
+ return null;
1017
+ }
1018
 
1019
+ return $this->match($_rules[$key], $userAgent);
1020
+ }
1021
 
1022
+ return false;
 
 
 
1023
  }
1024
 
1025
+ /**
1026
+ * Check if the device is mobile.
1027
+ * Returns true if any type of mobile device detected, including special ones
1028
+ * @param null $userAgent deprecated
1029
+ * @param null $httpHeaders deprecated
1030
+ * @return bool
1031
+ */
1032
+ public function isMobile($userAgent = null, $httpHeaders = null)
1033
+ {
1034
+
1035
+ if ($httpHeaders) {
1036
+ $this->setHttpHeaders($httpHeaders);
1037
+ }
1038
 
1039
+ if ($userAgent) {
1040
+ $this->setUserAgent($userAgent);
1041
+ }
 
 
 
 
 
 
 
 
1042
 
1043
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1044
+
1045
+ if ($this->checkHttpHeadersForMobile()) {
1046
  return true;
1047
+ } else {
1048
+ return $this->matchDetectionRulesAgainstUA();
1049
  }
1050
+
1051
  }
1052
 
1053
+ /**
1054
+ * Check if the device is a tablet.
1055
+ * Return true if any type of tablet device is detected.
1056
+ *
1057
+ * @param string $userAgent deprecated
1058
+ * @param array $httpHeaders deprecated
1059
+ * @return bool
1060
+ */
1061
+ public function isTablet($userAgent = null, $httpHeaders = null)
1062
+ {
1063
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1064
+
1065
+ foreach (self::$tabletDevices as $_regex) {
1066
+ if ($this->match($_regex, $userAgent)) {
1067
+ return true;
1068
+ }
1069
+ }
1070
 
1071
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1072
  }
1073
 
1074
+ /**
1075
+ * This method checks for a certain property in the
1076
+ * userAgent.
1077
+ * @todo: The httpHeaders part is not yet used.
1078
+ *
1079
+ * @param string $key
1080
+ * @param string $userAgent deprecated
1081
+ * @param string $httpHeaders deprecated
1082
+ * @return bool|int|null
1083
+ */
1084
+ public function is($key, $userAgent = null, $httpHeaders = null)
1085
+ {
1086
+ // Set the UA and HTTP headers only if needed (eg. batch mode).
1087
+ if ($httpHeaders) {
1088
+ $this->setHttpHeaders($httpHeaders);
1089
+ }
1090
 
1091
+ if ($userAgent) {
1092
+ $this->setUserAgent($userAgent);
1093
+ }
1094
 
1095
+ $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);
 
1096
 
1097
+ return $this->matchUAAgainstKey($key);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1098
  }
1099
 
1100
+ /**
1101
+ * Some detection rules are relative (not standard),
1102
+ * because of the diversity of devices, vendors and
1103
+ * their conventions in representing the User-Agent or
1104
+ * the HTTP headers.
1105
+ *
1106
+ * This method will be used to check custom regexes against
1107
+ * the User-Agent string.
1108
+ *
1109
+ * @param $regex
1110
+ * @param string $userAgent
1111
+ * @return bool
1112
+ *
1113
+ * @todo: search in the HTTP headers too.
1114
+ */
1115
+ public function match($regex, $userAgent = null)
1116
+ {
1117
+ // Escape the special character which is the delimiter.
1118
+ $regex = str_replace('/', '\/', $regex);
1119
+ $match = (bool) preg_match('/'.$regex.'/is', (!empty($userAgent) ? $userAgent : $this->userAgent), $matches);
1120
+ // If positive match is found, store the results for debug.
1121
+ if ($match) {
1122
+ $this->matchingRegex = $regex;
1123
+ $this->matchesArray = $matches;
1124
+ }
1125
 
1126
+ return $match;
1127
+ }
 
 
 
 
 
 
 
 
 
 
 
1128
 
1129
+ /**
1130
+ * Get the properties array.
1131
+ *
1132
+ * @return array
1133
+ */
1134
+ public static function getProperties()
1135
+ {
1136
+ return self::$properties;
1137
  }
1138
 
1139
+ /**
1140
+ * Prepare the version number.
1141
+ *
1142
+ * @todo Remove the error supression from str_replace() call.
1143
+ *
1144
+ * @param string $ver The string version, like "2.6.21.2152";
1145
+ *
1146
+ * @return float
1147
+ */
1148
+ public function prepareVersionNo($ver)
1149
+ {
1150
+ $ver = str_replace(array('_', ' ', '/'), '.', $ver);
1151
+ $arrVer = explode('.', $ver, 2);
1152
+
1153
+ if (isset($arrVer[1])) {
1154
+ $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
1155
+ }
1156
 
1157
+ return (float) implode('.', $arrVer);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1158
  }
1159
 
1160
+ /**
1161
+ * Check the version of the given property in the User-Agent.
1162
+ * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
1163
+ *
1164
+ * @param string $propertyName The name of the property. See self::getProperties() array
1165
+ * keys for all possible properties.
1166
+ * @param string $type Either self::VERSION_TYPE_STRING to get a string value or
1167
+ * self::VERSION_TYPE_FLOAT indicating a float value. This parameter
1168
+ * is optional and defaults to self::VERSION_TYPE_STRING. Passing an
1169
+ * invalid parameter will default to the this type as well.
1170
+ *
1171
+ * @return string|float The version of the property we are trying to extract.
1172
+ */
1173
+ public function version($propertyName, $type = self::VERSION_TYPE_STRING)
1174
+ {
1175
+ if (empty($propertyName)) {
1176
+ return false;
1177
+ }
1178
+
1179
+ //set the $type to the default if we don't recognize the type
1180
+ if ($type != self::VERSION_TYPE_STRING && $type != self::VERSION_TYPE_FLOAT) {
1181
+ $type = self::VERSION_TYPE_STRING;
1182
+ }
1183
+
1184
+ $properties = self::getProperties();
1185
 
1186
+ // Check if the property exists in the properties array.
1187
+ if (array_key_exists($propertyName, $properties)) {
1188
 
1189
+ // Prepare the pattern to be matched.
1190
+ // Make sure we always deal with an array (string is converted).
1191
+ $properties[$propertyName] = (array) $properties[$propertyName];
1192
 
1193
+ foreach ($properties[$propertyName] as $propertyMatchString) {
 
 
1194
 
1195
+ $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);
1196
 
1197
+ // Escape the special character which is the delimiter.
1198
+ $propertyPattern = str_replace('/', '\/', $propertyPattern);
1199
 
1200
+ // Identify and extract the version.
1201
+ preg_match('/'.$propertyPattern.'/is', $this->userAgent, $match);
1202
 
1203
+ if (!empty($match[1])) {
1204
+ $version = ( $type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1] );
1205
 
1206
+ return $version;
1207
+ }
1208
 
 
1209
  }
1210
 
1211
  }
1212
 
1213
+ return false;
1214
  }
1215
 
1216
+ /**
1217
+ * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
1218
+ *
1219
+ * @return string One of the self::MOBILE_GRADE_* constants.
1220
+ */
1221
+ public function mobileGrade()
1222
+ {
1223
+ $isMobile = $this->isMobile();
1224
 
1225
+ if (
1226
+ // 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)
1227
+ $this->isIOS() && $this->version('iPad', self::VERSION_TYPE_FLOAT)>=4.3 ||
1228
+ $this->isIOS() && $this->version('iPhone', self::VERSION_TYPE_FLOAT)>=4.3 ||
1229
+ $this->isIOS() && $this->version('iPod', self::VERSION_TYPE_FLOAT)>=4.3 ||
 
 
 
 
 
 
 
 
 
1230
 
1231
+ // 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)
1232
+ // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
1233
+ // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
1234
+ // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
1235
+ ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) ||
1236
 
1237
+ // 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)
1238
+ $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT)>=7.5 ||
1239
 
1240
+ // Tested on the Torch 9800 (6) and Style 9670 (6), BlackBerry® Torch 9810 (7), BlackBerry Z10 (10)
1241
+ $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=6.0 ||
1242
+ // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
1243
+ $this->match('Playbook.*Tablet') ||
1244
 
1245
+ // Palm WebOS (1.4-3.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0), HP TouchPad (3.0)
1246
+ ( $this->version('webOS', self::VERSION_TYPE_FLOAT)>=1.4 && $this->match('Palm|Pre|Pixi') ) ||
1247
+ // Palm WebOS 3.0 - Tested on HP TouchPad
1248
+ $this->match('hp.*TouchPad') ||
1249
 
1250
+ // Firefox Mobile 18 - Tested on Android 2.3 and 4.1 devices
1251
+ ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=18 ) ||
1252
 
1253
+ // Chrome for Android - Tested on Android 4.0, 4.1 device
1254
+ ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=4.0 ) ||
1255
 
1256
+ // Skyfire 4.1 - Tested on Android 2.3 device
1257
+ ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT)>=4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) ||
1258
 
1259
+ // Opera Mobile 11.5-12: Tested on Android 2.3
1260
+ ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>=11.5 && $this->is('AndroidOS') ) ||
1261
 
1262
+ // Meego 1.2 - Tested on Nokia 950 and N9
1263
+ $this->is('MeeGoOS') ||
1264
 
1265
+ // Tizen (pre-release) - Tested on early hardware
1266
+ $this->is('Tizen') ||
1267
 
1268
+ // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
1269
+ // @todo: more tests here!
1270
+ $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT)>=2.0 ||
1271
 
1272
+ // UC Browser - Tested on Android 2.3 device
1273
+ ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) ||
1274
 
1275
+ // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
1276
+ ( $this->match('Kindle Fire') ||
1277
+ $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT)>=3.0 ) ||
1278
 
1279
+ // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
1280
+ $this->is('AndroidOS') && $this->is('NookTablet') ||
1281
 
1282
+ // Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7
1283
+ $this->version('Chrome', self::VERSION_TYPE_FLOAT)>=16 && !$isMobile ||
1284
 
1285
+ // Safari Desktop 5-6 - Tested on OS X 10.7 and Windows 7
1286
+ $this->version('Safari', self::VERSION_TYPE_FLOAT)>=5.0 && !$isMobile ||
1287
 
1288
+ // Firefox Desktop 10-18 - Tested on OS X 10.7 and Windows 7
1289
+ $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=10.0 && !$isMobile ||
1290
 
1291
+ // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
1292
+ $this->version('IE', self::VERSION_TYPE_FLOAT)>=7.0 && !$isMobile ||
1293
 
1294
+ // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
1295
+ $this->version('Opera', self::VERSION_TYPE_FLOAT)>=10 && !$isMobile
1296
+ ){
1297
+ return self::MOBILE_GRADE_A;
1298
+ }
1299
 
1300
+ if (
1301
+ $this->isIOS() && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 ||
1302
+ $this->isIOS() && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<4.3 ||
1303
+ $this->isIOS() && $this->version('iPod', self::VERSION_TYPE_FLOAT)<4.3 ||
1304
 
1305
+ // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
1306
+ $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 ||
1307
 
1308
+ //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
1309
+ ($this->version('Opera Mini', self::VERSION_TYPE_FLOAT)>=5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT)<=7.0 &&
1310
+ ($this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 || $this->is('iOS')) ) ||
1311
 
1312
+ // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
1313
+ $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||
1314
 
1315
+ // @todo: report this (tested on Nokia N71)
1316
+ $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>=11 && $this->is('SymbianOS')
1317
+ ){
1318
+ return self::MOBILE_GRADE_B;
1319
+ }
 
 
 
 
 
 
1320
 
1321
+ if (
1322
+ // Blackberry 4.x - Tested on the Curve 8330
1323
+ $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<=5.0 ||
1324
+ // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
1325
+ $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT)<=5.2 ||
1326
+
1327
+ // Tested on original iPhone (3.1), iPhone 3 (3.2)
1328
+ $this->isIOS() && $this->version('iPad', self::VERSION_TYPE_FLOAT)<=3.2 ||
1329
+ $this->isIOS() && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<=3.2 ||
1330
+ $this->isIOS() && $this->version('iPod', self::VERSION_TYPE_FLOAT)<=3.2 ||
1331
+
1332
+ // Internet Explorer 7 and older - Tested on Windows XP
1333
+ $this->version('IE', self::VERSION_TYPE_FLOAT)<=7.0 && !$isMobile
1334
+ ){
1335
+ return self::MOBILE_GRADE_C;
1336
+ }
1337
 
1338
+ //All older smartphone platforms and featurephones - Any device that doesn't support media queries
1339
+ //will receive the basic, C grade experience.
 
1340
  return self::MOBILE_GRADE_C;
1341
  }
 
 
 
 
1342
  }
1343
+ endif;