public static function extractFromUserAgent($userAgent)
{
$userAgent = trim($userAgent);
/**
* @see http://www.texsoft.it/index.php?c=software&m=sw.php.useragent&l=it
*/
$pattern = "(([^/\\s]*)(/(\\S*))?)(\\s*\\[[a-zA-Z][a-zA-Z]\\])?\\s*(\\((([^()]|(\\([^()]*\\)))*)\\))?\\s*";
preg_match("#^{$pattern}#", $userAgent, $match);
$comment = array();
if (isset($match[7])) {
$comment = explode(';', $match[7]);
}
// second part if exists
$end = substr($userAgent, strlen($match[0]));
if (!empty($end)) {
$result['others']['full'] = $end;
}
$match2 = array();
if (isset($result['others'])) {
preg_match_all('/(([^\\/\\s]*)(\\/)?([^\\/\\(\\)\\s]*)?)(\\s\\((([^\\)]*)*)\\))?/i', $result['others']['full'], $match2);
}
$result['user_agent'] = trim($match[1]);
$result['product_name'] = isset($match[2]) ? trim($match[2]) : '';
$result['browser_name'] = $result['product_name'];
if (isset($match[4]) && trim($match[4])) {
$result['product_version'] = trim($match[4]);
$result['browser_version'] = trim($match[4]);
}
if (count($comment) && !empty($comment[0])) {
$result['comment']['full'] = trim($match[7]);
$result['comment']['detail'] = $comment;
$result['compatibility_flag'] = trim($comment[0]);
if (isset($comment[1])) {
$result['browser_token'] = trim($comment[1]);
}
if (isset($comment[2])) {
$result['device_os_token'] = trim($comment[2]);
}
}
if (empty($result['device_os_token']) && !empty($result['compatibility_flag'])) {
// some browsers do not have a platform token
$result['device_os_token'] = $result['compatibility_flag'];
}
if ($match2) {
$i = 0;
$max = count($match2[0]);
for ($i = 0; $i < $max; $i++) {
if (!empty($match2[0][$i])) {
$result['others']['detail'][] = array($match2[0][$i], $match2[2][$i], $match2[4][$i]);
}
}
}
/** Security level */
$security = array('N' => 'no security', 'U' => 'strong security', 'I' => 'weak security');
if (!empty($result['browser_token'])) {
if (isset($security[$result['browser_token']])) {
$result['security_level'] = $security[$result['browser_token']];
unset($result['browser_token']);
}
}
$product = strtolower($result['browser_name']);
// Mozilla : true && false
$compatibleOrIe = false;
if (isset($result['compatibility_flag']) && isset($result['comment'])) {
$compatibleOrIe = $result['compatibility_flag'] == 'compatible' || strpos($result['comment']['full'], "MSIE") !== false;
}
if ($product == 'mozilla' && $compatibleOrIe) {
if (!empty($result['browser_token'])) {
// Classic Mozilla chain
preg_match_all('/([^\\/\\s].*)(\\/|\\s)(.*)/i', $result['browser_token'], $real);
} else {
// MSIE specific chain with 'Windows' compatibility flag
foreach ($result['comment']['detail'] as $v) {
if (strpos($v, 'MSIE') !== false) {
$real[0][1] = trim($v);
$result['browser_engine'] = "MSIE";
$real[1][0] = "Internet Explorer";
$temp = explode(' ', trim($v));
$real[3][0] = $temp[1];
}
if (strpos($v, 'Win') !== false) {
$result['device_os_token'] = trim($v);
}
}
}
if (!empty($real[0])) {
$result['browser_name'] = $real[1][0];
$result['browser_version'] = $real[3][0];
} else {
if (isset($result['browser_token'])) {
$result['browser_name'] = $result['browser_token'];
}
$result['browser_version'] = '??';
}
} elseif ($product == 'mozilla' && $result['browser_version'] < 5.0) {
// handles the real Mozilla (or old Netscape if version < 5.0)
$result['browser_name'] = 'Netscape';
}
/** windows */
if ($result['browser_name'] == 'MSIE') {
$result['browser_engine'] = 'MSIE';
$result['browser_name'] = 'Internet Explorer';
}
if (isset($result['device_os_token'])) {
if (strpos($result['device_os_token'], 'Win') !== false) {
$windows = array('Windows NT 6.1' => 'Windows 7', 'Windows NT 6.0' => 'Windows Vista', 'Windows NT 5.2' => 'Windows Server 2003', 'Windows NT 5.1' => 'Windows XP', 'Windows NT 5.01' => 'Windows 2000 SP1', 'Windows NT 5.0' => 'Windows 2000', 'Windows NT 4.0' => 'Microsoft Windows NT 4.0', 'WinNT' => 'Microsoft Windows NT 4.0', 'Windows 98; Win 9x 4.90' => 'Windows Me', 'Windows 98' => 'Windows 98', 'Win98' => 'Windows 98', 'Windows 95' => 'Windows 95', 'Win95' => 'Windows 95', 'Windows CE' => 'Windows CE');
if (isset($windows[$result['device_os_token']])) {
$result['device_os_name'] = $windows[$result['device_os_token']];
} else {
$result['device_os_name'] = $result['device_os_token'];
}
}
}
// iphone
$apple_device = array('iPhone', 'iPod', 'iPad');
if (isset($result['compatibility_flag'])) {
if (in_array($result['compatibility_flag'], $apple_device)) {
$result['device'] = strtolower($result['compatibility_flag']);
$result['device_os_token'] = 'iPhone OS';
if (isset($comment[3])) {
$result['browser_language'] = trim($comment[3]);
}
if (isset($result['others']['detail'][1])) {
$result['browser_version'] = $result['others']['detail'][1][2];
} elseif (isset($result['others']['detail']) && count($result['others']['detail'])) {
$result['browser_version'] = $result['others']['detail'][0][2];
}
if (!empty($result['others']['detail'][2])) {
$result['firmware'] = $result['others']['detail'][2][2];
}
if (!empty($result['others']['detail'][3])) {
$result['browser_name'] = $result['others']['detail'][3][1];
$result['browser_build'] = $result['others']['detail'][3][2];
}
}
}
// Safari
if (isset($result['others'])) {
if ($result['others']['detail'][0][1] == 'AppleWebKit') {
$result['browser_engine'] = 'AppleWebKit';
if (isset($result['others']['detail'][1]) && $result['others']['detail'][1][1] == 'Version') {
$result['browser_version'] = $result['others']['detail'][1][2];
} else {
$result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][2];
}
if (isset($comment[3])) {
$result['browser_language'] = trim($comment[3]);
}
$last = $result['others']['detail'][count($result['others']['detail']) - 1][1];
if (empty($result['others']['detail'][2][1]) || $result['others']['detail'][2][1] == 'Safari') {
if (isset($result['others']['detail'][1])) {
$result['browser_name'] = $result['others']['detail'][1][1] && $result['others']['detail'][1][1] != 'Version' ? $result['others']['detail'][1][1] : 'Safari';
$result['browser_version'] = $result['others']['detail'][1][2] ? $result['others']['detail'][1][2] : $result['others']['detail'][0][2];
} else {
$result['browser_name'] = $result['others']['detail'][0][1] && $result['others']['detail'][0][1] != 'Version' ? $result['others']['detail'][0][1] : 'Safari';
$result['browser_version'] = $result['others']['detail'][0][2];
}
} else {
$result['browser_name'] = $result['others']['detail'][2][1];
$result['browser_version'] = $result['others']['detail'][2][2];
// mobile version
if ($result['browser_name'] == 'Mobile') {
$result['browser_name'] = 'Safari ' . $result['browser_name'];
if ($result['others']['detail'][1][1] == 'Version') {
$result['browser_version'] = $result['others']['detail'][1][2];
}
}
}
// For Safari < 2.2, AppleWebKit version gives the Safari version
if (strpos($result['browser_version'], '.') > 2 || (int) $result['browser_version'] > 20) {
$temp = explode('.', $result['browser_version']);
$build = (int) $temp[0];
$awkVersion = array(48 => '0.8', 73 => '0.9', 85 => '1.0', 103 => '1.1', 124 => '1.2', 300 => '1.3', 400 => '2.0');
foreach ($awkVersion as $k => $v) {
if ($build >= $k) {
$result['browser_version'] = $v;
}
}
}
}
// Gecko (Firefox or compatible)
if ($result['others']['detail'][0][1] == 'Gecko') {
$searchRV = true;
if (!empty($result['others']['detail'][1][1]) && !empty($result['others']['detail'][count($result['others']['detail']) - 1][2]) || strpos(strtolower($result['others']['full']), 'opera') !== false) {
$searchRV = false;
$result['browser_engine'] = $result['others']['detail'][0][1];
// the name of the application is at the end indepenently
// of quantity of information in $result['others']['detail']
$last = count($result['others']['detail']) - 1;
// exception : if the version of the last information is
// empty we take the previous one
if (empty($result['others']['detail'][$last][2])) {
$last--;
}
// exception : if the last one is 'Red Hat' or 'Debian' =>
// use rv: to find browser_version */
if (in_array($result['others']['detail'][$last][1], array('Debian', 'Hat'))) {
$searchRV = true;
}
$result['browser_name'] = $result['others']['detail'][$last][1];
$result['browser_version'] = $result['others']['detail'][$last][2];
if (isset($comment[4])) {
$result['browser_build'] = trim($comment[4]);
}
if (isset($comment[3])) {
$result['browser_language'] = trim($comment[3]);
}
// Netscape
if ($result['browser_name'] == 'Navigator' || $result['browser_name'] == 'Netscape6') {
$result['browser_name'] = 'Netscape';
}
}
if ($searchRV) {
// Mozilla alone : the version is identified by rv:
$result['browser_name'] = 'Mozilla';
if (isset($result['comment']['detail'])) {
foreach ($result['comment']['detail'] as $rv) {
if (strpos($rv, 'rv:') !== false) {
$result['browser_version'] = trim(str_replace('rv:', '', $rv));
}
}
}
}
}
// Netscape
if ($result['others']['detail'][0][1] == 'Netscape') {
$result['browser_name'] = 'Netscape';
$result['browser_version'] = $result['others']['detail'][0][2];
}
// Opera
// Opera: engine Presto
if ($result['others']['detail'][0][1] == 'Presto') {
$result['browser_engine'] = 'Presto';
if (!empty($result['others']['detail'][1][2])) {
$result['browser_version'] = $result['others']['detail'][1][2];
}
}
// UA ends with 'Opera X.XX' or 'Opera/X.XX'
if ($result['others']['detail'][0][1] == 'Opera') {
$result['browser_name'] = $result['others']['detail'][0][1];
// Opera X.XX
if (isset($result['others']['detail'][1][1])) {
$result['browser_version'] = $result['others']['detail'][1][1];
// Opera/X.XX
} elseif (isset($result['others']['detail'][0][2])) {
$result['browser_version'] = $result['others']['detail'][0][2];
}
}
// Opera Mini
if (isset($result["browser_token"])) {
if (strpos($result["browser_token"], 'Opera Mini') !== false) {
$result['browser_name'] = 'Opera Mini';
}
}
// Symbian
if ($result['others']['detail'][0][1] == 'SymbianOS') {
$result['device_os_token'] = 'SymbianOS';
}
}
// UA ends with 'Opera X.XX'
if (isset($result['browser_name']) && isset($result['browser_engine'])) {
if ($result['browser_name'] == 'Opera' && $result['browser_engine'] == 'Gecko' && empty($result['browser_version'])) {
$result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][1];
}
}
// cleanup
if (isset($result['browser_version']) && isset($result['browser_build'])) {
if ($result['browser_version'] == $result['browser_build']) {
unset($result['browser_build']);
}
}
// compatibility
$compatibility['AppleWebKit'] = 'Safari';
$compatibility['Gecko'] = 'Firefox';
$compatibility['MSIE'] = 'Internet Explorer';
$compatibility['Presto'] = 'Opera';
if (!empty($result['browser_engine'])) {
if (isset($compatibility[$result['browser_engine']])) {
$result['browser_compatibility'] = $compatibility[$result['browser_engine']];
}
}
ksort($result);
return $result;
}