: Detecting Browser Types? 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
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
More posts by @Nickens628
4 Comments
Sorted by latest first Latest Oldest Best
Adapt PPK's JavaScript-based browser detection script
Note that most browsers have ways (natively or through add-ons) to report their user-agent as something else. So there may not be a 100% foolproof way to detect browsers.
If what you're trying to do is to identify the dominant browsers being used so you can test with those specific browsers, then recording user-agent strings should be enough. Sure, there will be an error margin due to spoofed user-agent strings, but you don't need total accuracy for your application. What difference does it make if IE6 represents 10% of your userbase or 10.5%? If 1-2% of users have obscure or unidentifiable browsers, that's probably not enough to shift the browsers you'll officially support.
And there's a reason why many browsers lie about their identities or try to disguise themselves as someone else. It's precisely because of this kind of preemptive exclusion that they need to do this. If there's some obscure browser out there that uses the same Trident engine as IE8, then why should they be turned away from sites or served a more basic version of the page just because the web developer has never heard of that particular browser? If it can render the page just as well as IE8, it's not your place to tell the user that their browser is insufficient and that they need to "upgrade" to some other browser. That's why feature detection is preferred (and is still completely relevant to your situation). It avoids arbitrarily treating unknown/future browsers as second-class citizens and it sidesteps the problems with browser detection.
Lastly, given that you now say there are only 50 users total that will be using this admin area, there is all the more reason to just identify browser usage patterns via user research. Just log the user-agent string on sign-on or via a test page emailed to users and then analyze the logs manually and you can quickly identify the top 3 browsers. You can re-assess the browser distribution every so often so you can keep up with new browsers.
Though given that you're only going to support the top 3 browsers, you can probably just look up the stats on the W3C site, since they're basically the same for most sites, just in different order for different demographics.
The unique way I know to do that on server side is to analyze the User Agent HTTP Header.
I know that using the get_browser function may be useful, or may be a pain in the a**. Because it depends on external files that can be outdated.
The safe solution? None actually, but you can shortcut the browscap.ini file lookup to faster, safer solution (but will require more maintenance).
Check the list of http user agents, and just match the string you need against the HTTP UAs you receive.
For example, IE 8 always send
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)
or
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)
Firefox always send:
Mozilla/5.0 (xxx; xxx; xxxxxxx; xx-xx; rv:x.x.x.x) Gecko/2xxxxxxx Firefox/3.6.x
Sarafi sends:
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/xxx.x (KHTML like Gecko) Safari/5xx.x
This is what you have. There is no solution further than this. Even javascript solutions use to work with these pre-defined values to provide platform and browser in the client side, hence these are the values javascript engine has to process.
Thinking further, the main risks you inccur is a client trying to use IE7, IE9 beta, Firefox 3.5, Google Chrome and Opera 10+. Few people, if any actually, would try to access you page using FF 2.0 with HTTP User Agent Switcher or some odd browser.
I know, this solution is far away from being perfect, or reliable enough, but you need to consider the scenario it is inserted, and the chances of someone use Dillo, IE 5.5 or Safari 2.0....
$_SERVER['HTTP_USER_AGENT'] contains the string you seek - how you parse it is up to you... user-agents.org provides examples of common contents.
Apparently this problem comes up often enough that there's a function - get_browser() - which specifically addresses it so you're looking for something like this:
$user_agent = get_browser( $_SERVER['HTTP_USER_AGENT'] );
... and from there you can apply appropriate checks against the returned object.
Update:
To clarify why this is ultimately a bad idea: you have no control over when Microsoft, Mozilla/Firefox, and Safari decide to change their user agent strings - there is no magic bullet regular expression which will withstand arbitrary changes, there is no database which will not eventually be obsolete, et cetera.
Terms of Use Create Support ticket Your support tickets Stock Market News! © vmapp.org2024 All Rights reserved.