My client has asked me to implement a browser detection system for the admin login with the following criteria, allow these:
- Internet Explorer 8 or newer
- Firefox 3.6 or newer
- Safari 5 or newer for Mac only
And everything else should be blocked. They want me to implement a page telling the user what browser they need to upgrade/switch to in order to access the CMS.
Basically I need to know the best way to detect these browsers with PHP, distinct from any other browsers, and I've read that browser sniffing per se is not a good idea.
The CMS is WordPress but this is not a WordPress question (FYI I am a moderator on the WordPress Answers site.) Once I figure out the right technique to detect the browser I'm fully capable to make WordPress react as my client wants, I just need to know what the best ways are with PHP (or worse case jQuery, but I much prefer to do on the server) to figure how what works and what doesn't.
Please understand that "Don't do it" is not an acceptable answer for this question. I know this client too well and when they ask me to implement something I need to do it (they are a really good client so I'm happy to do what they ask.)
Thanks in advance for your expertise.
UPDATE
This requirement is for the admin console, not the public site; we'll support everything on the public site but we've heavily modified the WordPress admin console and we only want to have to test on the main three (3) browsers. So feature detection is not really relevant here; this is a testing and support requirement, not a requirement for supporting specific features.
And the project does not have the funding to support all browsers; it's just not realistic when there are probably only going to be 25 or 50 users of the admin console in total.
UPDATE #2
For the benefit of anyone with the same requirements here's the solution I came up with:
$min_versions = array(
'safari' => 5,
'firefox' => 3.6,
'msie' => 8,
);
$good_browser = false;
$user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
if (preg_match("#applewebkit/.*?version/([0-9]+)\..*?safari/#", $user_agent, $match)) {
$good_browser = intval($match[1])>=self::$min_versions['safari'];
} else {
foreach(array('firefox','msie') as $browser) {
if (preg_match("#{$browser}/([0-9]+)\.#", $user_agent, $match)) {
$good_browser = intval($match[1])>=self::$min_versions[$browser];
break;
}
}
}
if (!$good_browser) {
// Do redirect to an upgrade page
}
And this is the solution packaged as a standalone file designed to be included in a WordPress plugin or by the functions.php
file of a WordPress theme:
<?php
/* my-clients-browser-detect.php */
if (!class_exists('MyClients_BrowserDetector')) {
class MyClients_BrowserDetector {
static $min_versions = array(
'safari' => 5,
'firefox' => 3.6,
'msie' => 8,
);
static function admin_init() {
$good_browser = false;
$user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
if (preg_match("#applewebkit/.*?version/([0-9]+)\..*?safari/#", $user_agent, $match)) {
$good_browser = intval($match[1])>=self::$min_versions['safari'];
} else {
foreach(array('firefox','msie') as $browser) {
if (preg_match("#{$browser}/([0-9]+)\.#", $user_agent, $match)) {
$good_browser = intval($match[1])>=self::$min_versions[$browser];
break;
}
}
}
if (!$good_browser) {
$pages = self::get_pages('page-upgrade-browser.php');
if (count($pages)==0) {
echo "<p>Please upgrade your browser to one of the following:</p><ul>";
foreach(self::$min_versions as $browser => $version) {
echo "<li>{$browser}: {$version}</li>";
}
echo "</ul>";
exit;
}
$permalink = get_page_link(get_post($pages[0])->ID);
wp_safe_redirect($permalink,302);
}
}
static function get_pages($template) {
global $wpdb;
$sql = $wpdb->prepare("SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='_wp_page_template' AND meta_value='%s'",$template);
$pages = $wpdb->get_col($sql);
foreach($pages as $index => $page_id)
$pages[$index] = get_post($page_id);
return $pages;
}
static function on_load() {
add_action('admin_init', array(__CLASS__,'admin_init'));
}
}
MyClients_BrowserDetector::on_load();
}
As several people have mentioned feature detection is usually considered a better approach but for this use-case we really didn't have specific features we cared about, we had specific named browsers we cared about so feature detection wasn't a viable option. FYI, the client knows that we may have to revise this script in the future if we can false negatives or false positives.
-Mike