1<?php 2namespace TYPO3\CMS\Core\Utility; 3 4/* 5 * This file is part of the TYPO3 CMS project. 6 * 7 * It is free software; you can redistribute it and/or modify it under 8 * the terms of the GNU General Public License, either version 2 9 * of the License, or any later version. 10 * 11 * For the full copyright and license information, please read the 12 * LICENSE.txt file that was distributed with this source code. 13 * 14 * The TYPO3 project - inspiring people to share! 15 */ 16 17/** 18 * Class to handle and determine browser specific information. 19 */ 20class ClientUtility 21{ 22 /** 23 * Generates an array with abstracted browser information 24 * 25 * @param string $userAgent The useragent string, \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('HTTP_USER_AGENT') 26 * @return array Contains keys "browser", "version", "system 27 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 28 */ 29 public static function getBrowserInfo($userAgent) 30 { 31 trigger_error('ClientUtility::getBrowserInfo() will be removed with TYPO3 v10.0.', E_USER_DEPRECATED); 32 // Hook: $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/div/class.t3lib_utility_client.php']['getBrowserInfo']: 33 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/div/class.t3lib_utility_client.php']['getBrowserInfo'] ?? [] as $hookFunction) { 34 $returnResult = true; 35 $hookParameters = [ 36 'userAgent' => &$userAgent, 37 'returnResult' => &$returnResult 38 ]; 39 // need reference for third parameter in \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction, 40 // so create a reference to NULL 41 $null = null; 42 $hookResult = GeneralUtility::callUserFunction($hookFunction, $hookParameters, $null); 43 if ($returnResult && is_array($hookResult) && !empty($hookResult)) { 44 return $hookResult; 45 } 46 } 47 $userAgent = trim($userAgent); 48 $browserInfo = [ 49 'useragent' => $userAgent 50 ]; 51 // Analyze the userAgent string 52 // Declare known browsers to look for 53 $known = [ 54 'msie', 55 'firefox', 56 'webkit', 57 'opera', 58 'netscape', 59 'konqueror', 60 'gecko', 61 'chrome', 62 'safari', 63 'seamonkey', 64 'navigator', 65 'mosaic', 66 'lynx', 67 'amaya', 68 'omniweb', 69 'avant', 70 'camino', 71 'flock', 72 'aol' 73 ]; 74 $matches = []; 75 $pattern = '#(?P<browser>' . implode('|', $known) . ')[/ ]+(?P<version>[0-9]+(?:\\.[0-9]+)?)#'; 76 // Find all phrases (or return empty array if none found) 77 if (!preg_match_all($pattern, strtolower($userAgent), $matches)) { 78 // Microsoft Internet-Explorer 11 does not have a sign of "MSIE" or so in the useragent. 79 // All checks from the pattern above fail here. Look for a special combination of 80 // "Mozilla/5.0" in front, "Trident/7.0" in the middle and "like Gecko" at the end. 81 // The version (revision) is given as "; rv:11.0" in the useragent then. 82 unset($matches); 83 $pattern = '#mozilla/5\\.0 \\(.*trident/7\\.0.*; rv:(?P<version>[0-9]+(?:\\.[0-9]+)?)\\) like gecko#i'; 84 if (preg_match_all($pattern, $userAgent, $matches)) { 85 $browserInfo['browser'] = 'msie'; 86 $browserInfo['version'] = $matches['version'][0]; 87 $browserInfo['all'] = ['msie' => $matches['version'][0]]; 88 } else { 89 $browserInfo['browser'] = 'unknown'; 90 $browserInfo['version'] = ''; 91 $browserInfo['all'] = []; 92 } 93 } else { 94 // Since some UAs have more than one phrase (e.g Firefox has a Gecko phrase, 95 // Opera 7,8 have a MSIE phrase), use the last one found (the right-most one 96 // in the UA). That's usually the most correct. 97 // For IE use the first match as IE sends multiple MSIE with version, from higher to lower. 98 $lastIndex = count($matches['browser']) - 1; 99 $browserInfo['browser'] = $matches['browser'][$lastIndex]; 100 $browserInfo['version'] = $browserInfo['browser'] === 'msie' ? $matches['version'][0] : $matches['version'][$lastIndex]; 101 // But return all parsed browsers / version in an extra array 102 $browserInfo['all'] = []; 103 for ($i = 0; $i <= $lastIndex; $i++) { 104 if (!isset($browserInfo['all'][$matches['browser'][$i]])) { 105 $browserInfo['all'][$matches['browser'][$i]] = $matches['version'][$i]; 106 } 107 } 108 // Replace gecko build date with version given by rv 109 if (isset($browserInfo['all']['gecko'])) { 110 preg_match_all('/rv:([0-9\\.]*)/', strtolower($userAgent), $version); 111 if ($version[1][0]) { 112 $browserInfo['all']['gecko'] = $version[1][0]; 113 } 114 } 115 } 116 $browserInfo['all_systems'] = []; 117 if (strstr($userAgent, 'Win')) { 118 // Windows 119 if (strstr($userAgent, 'Windows NT 6.2') || strstr($userAgent, 'Windows NT 6.3')) { 120 $browserInfo['all_systems'][] = 'win8'; 121 $browserInfo['all_systems'][] = 'winNT'; 122 } elseif (strstr($userAgent, 'Windows NT 6.1')) { 123 $browserInfo['all_systems'][] = 'win7'; 124 $browserInfo['all_systems'][] = 'winNT'; 125 } elseif (strstr($userAgent, 'Windows NT 6.0')) { 126 $browserInfo['all_systems'][] = 'winVista'; 127 $browserInfo['all_systems'][] = 'winNT'; 128 } elseif (strstr($userAgent, 'Windows NT 5.1')) { 129 $browserInfo['all_systems'][] = 'winXP'; 130 $browserInfo['all_systems'][] = 'winNT'; 131 } elseif (strstr($userAgent, 'Windows NT 5.0')) { 132 $browserInfo['all_systems'][] = 'win2k'; 133 $browserInfo['all_systems'][] = 'winNT'; 134 } elseif (strstr($userAgent, 'Win98') || strstr($userAgent, 'Windows 98')) { 135 $browserInfo['all_systems'][] = 'win98'; 136 } elseif (strstr($userAgent, 'Win95') || strstr($userAgent, 'Windows 95')) { 137 $browserInfo['all_systems'][] = 'win95'; 138 } elseif (strstr($userAgent, 'WinNT') || strstr($userAgent, 'Windows NT')) { 139 $browserInfo['all_systems'][] = 'winNT'; 140 } elseif (strstr($userAgent, 'Win16') || strstr($userAgent, 'Windows 311')) { 141 $browserInfo['all_systems'][] = 'win311'; 142 } 143 } elseif (strstr($userAgent, 'Mac')) { 144 if (strstr($userAgent, 'iPad') || strstr($userAgent, 'iPhone') || strstr($userAgent, 'iPod')) { 145 $browserInfo['all_systems'][] = 'iOS'; 146 $browserInfo['all_systems'][] = 'mac'; 147 } else { 148 $browserInfo['all_systems'][] = 'mac'; 149 } 150 } elseif (strstr($userAgent, 'Android')) { 151 $browserInfo['all_systems'][] = 'android'; 152 $browserInfo['all_systems'][] = 'linux'; 153 } elseif (strstr($userAgent, 'Linux')) { 154 $browserInfo['all_systems'][] = 'linux'; 155 } elseif (strstr($userAgent, 'BSD')) { 156 $browserInfo['all_systems'][] = 'unix_bsd'; 157 } elseif (strstr($userAgent, 'SGI') && strstr($userAgent, ' IRIX ')) { 158 $browserInfo['all_systems'][] = 'unix_sgi'; 159 } elseif (strstr($userAgent, ' SunOS ')) { 160 $browserInfo['all_systems'][] = 'unix_sun'; 161 } elseif (strstr($userAgent, ' HP-UX ')) { 162 $browserInfo['all_systems'][] = 'unix_hp'; 163 } elseif (strstr($userAgent, 'CrOS')) { 164 $browserInfo['all_systems'][] = 'chrome'; 165 $browserInfo['all_systems'][] = 'linux'; 166 } 167 return $browserInfo; 168 } 169 170 /** 171 * Returns the version of a browser; Basically getting float value of the input string, 172 * stripping of any non-numeric values in the beginning of the string first. 173 * 174 * @param string $version A string with version number, eg. '/7.32 some text' 175 * @return float Returns double value, eg. 7.32 176 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 177 */ 178 public static function getVersion($version) 179 { 180 trigger_error('ClientUtility::getVersion() will be removed with TYPO3 v10.0.', E_USER_DEPRECATED); 181 return (float)preg_replace('/^[^0-9]*/', '', $version); 182 } 183} 184