AdRotate Banner Manager - Version 5.4

Version Description

FREE = * [change] Now uses wp_is_mobile instead of Mobile Detect * [change] Updated Settings Dashboards * [removed] Obsolete "Responsive Advert" code and database column

Download this release

Release Info

Developer adegans
Plugin Icon 128x128 AdRotate Banner Manager
Version 5.4
Comparing to
See all releases

Code changes from version 5.3 to 5.4

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