PHP: browser agent version user agent with version / xxx (Safari & Opera)

I wrote a simple class to verify that user agents display a warning for incompatible browsers. I am doing this server side, I know that this is possible on the client side.

Okey first, I'm not very good at writing regular expressions.

I wrote a regular expression that looks for browser names in lower case and then version number. I am doing foreach() with an array like :

 <?php $browsers = Array('msie','chrome','safari','firefox','opera'); foreach($browsers as $i => $browser) { $regex = "#({$browser})[/ ]([0-9.]*)#i"; if(preg_match($regex, $useragent, $matches)) { echo "Browser: \"{$matches[0]}\", version: \"{$matches[1]}\""; } } ?> 

This will give: Browser: "Firefox", version "23.0.6" .

I found this for Firefox, MS IE and older versions of Opera. However, some browsers, such as Safari and later versions of Opera, have a different user agent line that contains the / xxx version, which

Just to give you an idea, here are 3 lines of the user agent, and what I need is highlighted.

  • Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/ 6.0.5 Safari /536.30.1
  • Mozilla/5.0 (compatible; MSIE 10.0 ; Windows NT 6.1; WOW64; Trident/6.0)
  • Opera /9.80 (Windows NT 6.0) Presto/2.12.388 Version/ 12.14

So, in each of them the correct logic:

  • If the line has a Version/ xxx number, which is the version number.
  • If not, then Browsername/ xxx is the version number.

Also, if you look at the first and last line of the user agent above, you can see that Version may appear before or after the browser name.

Can someone help me make a regex for use with preg_match() ? Do I need to use a conditional operator or can I find additional groups? I'm a little confused.

Thanks!

Edit 09-17-2013: I forgot to mention that I do not want to use get_browser() , it uses a huge library to detect the capabilities of browsers, etc. I only need a short “white list” of browsers, which should take several milliseconds, and not several hundred ms, to read cap.ini files for viewing. Otherwise, George’s answer would be the answer.

+7
php regex pcre version user-agent
source share
4 answers

It ended a little differently, as I had problems with some browsers with Remus answer.

 <?php function get_useragent_info($ua) { $ua = is_null($ua) ? $_SERVER['HTTP_USER_AGENT'] : $ua; // Enumerate all common platforms, this is usually placed in braces (order is important! First come first serve..) $platforms = "Windows|iPad|iPhone|Macintosh|Android|BlackBerry"; // All browsers except MSIE/Trident and.. // NOT for browsers that use this syntax: Version/0.xx Browsername $browsers = "Firefox|Chrome"; // Specifically for browsers that use this syntax: Version/0.xx Browername $browsers_v = "Safari|Mobile"; // Mobile is mentioned in Android and BlackBerry UA's // Fill in your most common engines.. $engines = "Gecko|Trident|Webkit|Presto"; // Regex the crap out of the user agent, making multiple selections and.. $regex_pat = "/((Mozilla)\/[\d\.]+|(Opera)\/[\d\.]+)\s\(.*?((MSIE)\s([\d\.]+).*?(Windows)|({$platforms})).*?\s.*?({$engines})[\/\s]+[\d\.]+(\;\srv\:([\d\.]+)|.*?).*?(Version[\/\s]([\d\.]+)(.*?({$browsers_v})|$)|(({$browsers})[\/\s]+([\d\.]+))|$).*/i"; // .. placing them in this order, delimited by | $replace_pat = '$7$8|$2$3|$9|${17}${15}$5$3|${18}${13}$6${11}'; // Run the preg_replace .. and explode on | $ua_array = explode("|",preg_replace($regex_pat, $replace_pat, $ua, PREG_PATTERN_ORDER)); if (count($ua_array)>1) { $return['platform'] = $ua_array[0]; // Windows / iPad / MacOS / BlackBerry $return['type'] = $ua_array[1]; // Mozilla / Opera etc. $return['renderer'] = $ua_array[2]; // WebKit / Presto / Trident / Gecko etc. $return['browser'] = $ua_array[3]; // Chrome / Safari / MSIE / Firefox /* Not necessary but this will filter out Chromes ridiculously long version numbers 31.0.1234.122 becomes 31.0, while a "normal" 3 digit version number like 10.2.1 would stay 10.2.1, 11.0 stays 11.0. Non-match stays what it is. */ if (preg_match("/^[\d]+\.[\d]+(?:\.[\d]{0,2}$)?/",$ua_array[4],$matches)) { $return['version'] = $matches[0]; } else { $return['version'] = $ua_array[4]; } } else { /* Unknown browser.. This could be a deal breaker for you but I use this to actually keep old browsers out of my application, users are told to download a compatible browser (99% of modern browsers are compatible. You can also ignore my error but then there is no guarantee that the application will work and thus no need to report debugging data. */ return false; } // Replace some browsernames eg MSIE -> Internet Explorer switch(strtolower($return['browser'])) { case "msie": case "trident": $return['browser'] = "Internet Explorer"; break; case "": // IE 11 is a steamy turd (thanks Microsoft...) if (strtolower($return['renderer']) == "trident") { $return['browser'] = "Internet Explorer"; } break; } switch(strtolower($return['platform'])) { case "android": // These browsers claim to be Safari but are BB Mobile case "blackberry": // and Android Mobile if ($return['browser'] =="Safari" || $return['browser'] == "Mobile" || $return['browser'] == "") { $return['browser'] = "{$return['platform']} mobile"; } break; } return $return; } // End of Function ?> 
+6
source share

Given your handful of results, this works. This may not be in all cases, but it will significantly reduce processing time.

I would use one regex to extract the version:

 (?:version\/|(?:msie|chrome|safari|firefox|opera) )([\d.]+) 

And then, since you are only looking for a few exact lines, you can use php stripos() to check the browser line.

 <?php $useragent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/6.0.5 Safari/536.30.1"; $browsers = Array('msie','chrome','safari','firefox','opera'); preg_match("/(?:version\/|(?:msie|chrome|safari|firefox|opera) )([\d.]+)/i", $useragent, $matches); $version = $matches[1]; $browser = ""; foreach($browsers as $b) { if (stripos($useragent, $b) !== false) { $browser = ucfirst($b); break; } } echo "$browser: $version"; ?> 

The benefits of this approach are immediate:

  • You do not need to check useragent multiple times with regex.
  • stripos() significantly faster during processing than regular expressions.

You can also play with regex here: http://regex101.com/r/lE6lI2

+6
source share

Have you heard of eyebrows and get_browser() ? In my installation:

 $info = get_browser(); echo $info->browser; // Chrome echo $info->version; // 29.0 

To use it, grab a copy of the php version of the php_browscap.ini browser from here (e.g. php_browscap.ini ), php_browscap.ini to it in php.ini according to the browscap directive, and you're good to go.

+4
source share

This class / function does a nice job:

 old dead link: https://github.com/diversen/coscms/blob/master/coslib/useragent.php 

I tested this with iphone and opera. At the same time, you will get the OS that the browser is running on.)

Edit:

I see that this function has a git repository. Use this as it is updated and maintained:

https://github.com/donatj/PhpUserAgent

+4
source share

All Articles