shell bypass 403
<?php declare(strict_types=1);
/**
* Device Detector - The Universal Device Detection library for parsing User Agents
*
* @link https://matomo.org
*
* @license http://www.gnu.org/licenses/lgpl.html LGPL v3 or later
*/
namespace DeviceDetector\Parser\Client;
use DeviceDetector\Parser\Client\Browser\Engine;
/**
* Class Browser
*
* Client parser for browser detection
*/
class Browser extends AbstractClientParser
{
/**
* @var string
*/
protected $fixtureFile = 'regexes/client/browsers.yml';
/**
* @var string
*/
protected $parserName = 'browser';
/**
* Known browsers mapped to their internal short codes
*
* @var array
*/
protected static $availableBrowsers = [
'1B' => '115 Browser',
'2B' => '2345 Browser',
'36' => '360 Phone Browser',
'3B' => '360 Browser',
'AA' => 'Avant Browser',
'AB' => 'ABrowse',
'AF' => 'ANT Fresco',
'AG' => 'ANTGalio',
'AL' => 'Aloha Browser',
'AH' => 'Aloha Browser Lite',
'AM' => 'Amaya',
'AO' => 'Amigo',
'AN' => 'Android Browser',
'AE' => 'AOL Desktop',
'AD' => 'AOL Shield',
'AR' => 'Arora',
'AX' => 'Arctic Fox',
'AV' => 'Amiga Voyager',
'AW' => 'Amiga Aweb',
'A0' => 'Atom',
'AT' => 'Atomic Web Browser',
'AS' => 'Avast Secure Browser',
'VG' => 'AVG Secure Browser',
'AC' => 'Avira Scout',
'A1' => 'AwoX',
'BA' => 'Beaker Browser',
'BM' => 'Beamrise',
'BB' => 'BlackBerry Browser',
'BD' => 'Baidu Browser',
'BS' => 'Baidu Spark',
'BI' => 'Basilisk',
'BE' => 'Beonex',
'BH' => 'BlackHawk',
'BJ' => 'Bunjalloo',
'BL' => 'B-Line',
'BU' => 'Blue Browser',
'BN' => 'Borealis Navigator',
'BR' => 'Brave',
'BK' => 'BriskBard',
'BX' => 'BrowseX',
'BZ' => 'Browzar',
'BY' => 'Biyubi',
'BF' => 'Byffox',
'CA' => 'Camino',
'CL' => 'CCleaner',
'C6' => 'Chedot',
'C0' => 'Centaury',
'CC' => 'Coc Coc',
'C4' => 'CoolBrowser',
'C2' => 'Colibri',
'CD' => 'Comodo Dragon',
'C1' => 'Coast',
'CX' => 'Charon',
'CE' => 'CM Browser',
'CF' => 'Chrome Frame',
'HC' => 'Headless Chrome',
'CH' => 'Chrome',
'CI' => 'Chrome Mobile iOS',
'CK' => 'Conkeror',
'CM' => 'Chrome Mobile',
'CN' => 'CoolNovo',
'CO' => 'CometBird',
'CB' => 'COS Browser',
'CW' => 'Cornowser',
'C3' => 'Chim Lac',
'CP' => 'ChromePlus',
'CR' => 'Chromium',
'C5' => 'Chromium GOST',
'CY' => 'Cyberfox',
'CS' => 'Cheshire',
'CT' => 'Crusta',
'CG' => 'Craving Explorer',
'CZ' => 'Crazy Browser',
'CU' => 'Cunaguaro',
'CV' => 'Chrome Webview',
'DB' => 'dbrowser',
'DE' => 'Deepnet Explorer',
'DG' => 'deg-degan',
'DA' => 'Deledao',
'DT' => 'Delta Browser',
'DS' => 'DeskBrowse',
'DF' => 'Dolphin',
'DO' => 'Dorado',
'DR' => 'Dot Browser',
'DL' => 'Dooble',
'DI' => 'Dillo',
'DD' => 'DuckDuckGo Privacy Browser',
'EC' => 'Ecosia',
'EI' => 'Epic',
'EL' => 'Elinks',
'EB' => 'Element Browser',
'EE' => 'Elements Browser',
'EZ' => 'eZ Browser',
'EU' => 'EUI Browser',
'EP' => 'GNOME Web',
'ES' => 'Espial TV Browser',
'FA' => 'Falkon',
'FX' => 'Faux Browser',
'F1' => 'Firefox Mobile iOS',
'FB' => 'Firebird',
'FD' => 'Fluid',
'FE' => 'Fennec',
'FF' => 'Firefox',
'FK' => 'Firefox Focus',
'FY' => 'Firefox Reality',
'FR' => 'Firefox Rocket',
'FL' => 'Flock',
'FO' => 'Flow',
'FM' => 'Firefox Mobile',
'FW' => 'Fireweb',
'FN' => 'Fireweb Navigator',
'FS' => 'Flast',
'FU' => 'FreeU',
'GA' => 'Galeon',
'GH' => 'Ghostery Privacy Browser',
'GI' => 'GinxDroid Browser',
'GB' => 'Glass Browser',
'GE' => 'Google Earth',
'GO' => 'GOG Galaxy',
'HS' => 'HasBrowser',
'HA' => 'Hawk Turbo Browser',
'HO' => 'hola! Browser',
'HJ' => 'HotJava',
'HU' => 'Huawei Browser',
'IB' => 'IBrowse',
'IC' => 'iCab',
'I2' => 'iCab Mobile',
'I1' => 'Iridium',
'I3' => 'Iron Mobile',
'I4' => 'IceCat',
'ID' => 'IceDragon',
'IV' => 'Isivioo',
'IW' => 'Iceweasel',
'IE' => 'Internet Explorer',
'IM' => 'IE Mobile',
'IR' => 'Iron',
'JB' => 'Japan Browser',
'JS' => 'Jasmine',
'JA' => 'JavaFX',
'JI' => 'Jig Browser',
'JP' => 'Jig Browser Plus',
'JO' => 'Jio Browser',
'KB' => 'K.Browser',
'KI' => 'Kindle Browser',
'KM' => 'K-meleon',
'KO' => 'Konqueror',
'KP' => 'Kapiko',
'KN' => 'Kinza',
'KW' => 'Kiwi',
'KD' => 'Kode Browser',
'KY' => 'Kylo',
'KZ' => 'Kazehakase',
'LB' => 'Cheetah Browser',
'LF' => 'LieBaoFast',
'LG' => 'LG Browser',
'LH' => 'Light',
'LI' => 'Links',
'IF' => 'Lolifox',
'LO' => 'Lovense Browser',
'LU' => 'LuaKit',
'LL' => 'Lulumi',
'LS' => 'Lunascape',
'LN' => 'Lunascape Lite',
'LX' => 'Lynx',
'M1' => 'mCent',
'MB' => 'MicroB',
'MC' => 'NCSA Mosaic',
'MZ' => 'Meizu Browser',
'ME' => 'Mercury',
'MF' => 'Mobile Safari',
'MI' => 'Midori',
'MO' => 'Mobicip',
'MU' => 'MIUI Browser',
'MS' => 'Mobile Silk',
'MN' => 'Minimo',
'MT' => 'Mint Browser',
'MX' => 'Maxthon',
'NM' => 'MxNitro',
'MY' => 'Mypal',
'MR' => 'Monument Browser',
'MW' => 'MAUI WAP Browser',
'NW' => 'Navigateur Web',
'NR' => 'NFS Browser',
'NB' => 'Nokia Browser',
'NO' => 'Nokia OSS Browser',
'NV' => 'Nokia Ovi Browser',
'NX' => 'Nox Browser',
'NE' => 'NetSurf',
'NF' => 'NetFront',
'NL' => 'NetFront Life',
'NP' => 'NetPositive',
'NS' => 'Netscape',
'NT' => 'NTENT Browser',
'OC' => 'Oculus Browser',
'O1' => 'Opera Mini iOS',
'OB' => 'Obigo',
'O2' => 'Odin',
'OD' => 'Odyssey Web Browser',
'OF' => 'Off By One',
'HH' => 'OhHai Browser',
'OE' => 'ONE Browser',
'OX' => 'Opera GX',
'OG' => 'Opera Neon',
'OH' => 'Opera Devices',
'OI' => 'Opera Mini',
'OM' => 'Opera Mobile',
'OP' => 'Opera',
'ON' => 'Opera Next',
'OO' => 'Opera Touch',
'OA' => 'Orca',
'OS' => 'Ordissimo',
'OR' => 'Oregano',
'O0' => 'Origin In-Game Overlay',
'OY' => 'Origyn Web Browser',
'OV' => 'Openwave Mobile Browser',
'OW' => 'OmniWeb',
'OT' => 'Otter Browser',
'PL' => 'Palm Blazer',
'PM' => 'Pale Moon',
'PY' => 'Polypane',
'PP' => 'Oppo Browser',
'PR' => 'Palm Pre',
'PU' => 'Puffin',
'PW' => 'Palm WebPro',
'PA' => 'Palmscape',
'PE' => 'Perfect Browser',
'PH' => 'Phantom Browser',
'PX' => 'Phoenix',
'PB' => 'Phoenix Browser',
'PF' => 'PlayFree Browser',
'PO' => 'Polaris',
'PT' => 'Polarity',
'LY' => 'PolyBrowser',
'PI' => 'PrivacyWall',
'PS' => 'Microsoft Edge',
'Q2' => 'QQ Browser Lite',
'Q1' => 'QQ Browser Mini',
'QQ' => 'QQ Browser',
'QT' => 'Qutebrowser',
'QU' => 'Quark',
'QZ' => 'QupZilla',
'QM' => 'Qwant Mobile',
'QW' => 'QtWebEngine',
'RE' => 'Realme Browser',
'RK' => 'Rekonq',
'RM' => 'RockMelt',
'SB' => 'Samsung Browser',
'SA' => 'Sailfish Browser',
'S8' => 'Seewo Browser',
'SC' => 'SEMC-Browser',
'SE' => 'Sogou Explorer',
'SF' => 'Safari',
'S5' => 'Safe Exam Browser',
'SW' => 'SalamWeb',
'SV' => 'SFive',
'SH' => 'Shiira',
'S1' => 'SimpleBrowser',
'SY' => 'Sizzy',
'SK' => 'Skyfire',
'SS' => 'Seraphic Sraf',
'SL' => 'Sleipnir',
'S6' => 'Slimjet',
'S7' => 'SP Browser',
'7S' => '7Star',
'LE' => 'Smart Lenovo Browser',
'OZ' => 'Smooz',
'SN' => 'Snowshoe',
'SO' => 'Sogou Mobile Browser',
'S2' => 'Splash',
'SI' => 'Sputnik Browser',
'SR' => 'Sunrise',
'SP' => 'SuperBird',
'SU' => 'Super Fast Browser',
'S3' => 'surf',
'SG' => 'Stargon',
'S0' => 'START Internet Browser',
'S4' => 'Steam In-Game Overlay',
'ST' => 'Streamy',
'SX' => 'Swiftfox',
'SZ' => 'Seznam Browser',
'TR' => 'T-Browser',
'TO' => 't-online.de Browser',
'TA' => 'Tao Browser',
'TF' => 'TenFourFox',
'TB' => 'Tenta Browser',
'TZ' => 'Tizen Browser',
'TU' => 'Tungsten',
'TG' => 'ToGate',
'TS' => 'TweakStyle',
'TV' => 'TV Bro',
'UB' => 'UBrowser',
'UC' => 'UC Browser',
'UH' => 'UC Browser HD',
'UM' => 'UC Browser Mini',
'UT' => 'UC Browser Turbo',
'UR' => 'UR Browser',
'UZ' => 'Uzbl',
'VE' => 'Venus Browser',
'VI' => 'Vivaldi',
'VV' => 'vivo Browser',
'VB' => 'Vision Mobile Browser',
'VM' => 'VMware AirWatch',
'WI' => 'Wear Internet Browser',
'WP' => 'Web Explorer',
'WE' => 'WebPositive',
'WF' => 'Waterfox',
'WH' => 'Whale Browser',
'WO' => 'wOSBrowser',
'WT' => 'WeTab Browser',
'YJ' => 'Yahoo! Japan Browser',
'YA' => 'Yandex Browser',
'YL' => 'Yandex Browser Lite',
'YN' => 'Yaani Browser',
'YB' => 'Yolo Browser',
'XS' => 'xStand',
'XI' => 'Xiino',
'XV' => 'Xvast',
'ZE' => 'Zetakey',
'ZV' => 'Zvu',
// detected browsers in older versions
// 'IA' => 'Iceape', => pim
// 'SM' => 'SeaMonkey', => pim
];
/**
* Browser families mapped to the short codes of the associated browsers
*
* @var array
*/
protected static $browserFamilies = [
'Android Browser' => ['AN', 'MU'],
'BlackBerry Browser' => ['BB'],
'Baidu' => ['BD', 'BS'],
'Amiga' => ['AV', 'AW'],
'Chrome' => [
'CH', 'BA', 'BR', 'CC', 'CD', 'CM', 'CI', 'CF', 'CN',
'CR', 'CP', 'DD', 'IR', 'RM', 'AO', 'TS', 'VI', 'PT',
'AS', 'TB', 'AD', 'SB', 'WP', 'I3', 'CV', 'WH', 'SZ',
'QW', 'LF', 'KW', '2B', 'CE', 'EC', 'MT', 'MS', 'HA',
'OC', 'MZ', 'BM', 'KN', 'SW', 'M1', 'FA', 'TA', 'AH',
'CL', 'SU', 'EU', 'UB', 'LO', 'VG', 'TV', 'A0', '1B',
'S4', 'EE', 'AE', 'VM', 'O0', 'TG', 'GB', 'SY', 'HH',
'YJ', 'LL', 'TU', 'XV', 'C2', 'QU', 'YN', 'JB', 'MR',
'S6', '7S', 'NM', 'PB', 'UR', 'NR', 'SG', 'S8', 'C3',
'SS', 'O2', 'SV', 'TR', 'CW', 'GI', 'VE', 'AC', 'FS',
'CG', 'DR', 'C4', 'HS', 'DA', 'C5', 'C6', 'DG',
],
'Firefox' => [
'FF', 'FE', 'FM', 'SX', 'FB', 'PX', 'MB', 'EI', 'WF',
'CU', 'TF', 'QM', 'FR', 'I4', 'GZ', 'MO', 'F1', 'BI',
'MN', 'BH', 'TO', 'OS', 'MY', 'FY', 'AX', 'C0', 'LH',
'S5', 'ZV', 'IW', 'PI', 'BN', 'OA', 'LY', 'IF', 'BF',
],
'Internet Explorer' => ['IE', 'IM', 'PS', 'CZ', 'BZ'],
'Konqueror' => ['KO'],
'NetFront' => ['NF'],
'NetSurf' => ['NE'],
'Nokia Browser' => ['NB', 'NO', 'NV', 'DO'],
'Opera' => ['OP', 'OM', 'OI', 'ON', 'OO', 'OG', 'OH', 'O1', 'OX'],
'Safari' => ['SF', 'MF', 'SO', 'S7'],
'Sailfish Browser' => ['SA'],
];
/**
* Browsers that are available for mobile devices only
*
* @var array
*/
protected static $mobileOnlyBrowsers = [
'36', 'OC', 'PU', 'SK', 'MF', 'OI', 'OM', 'DD', 'DB',
'ST', 'BL', 'IV', 'FM', 'C1', 'AL', 'SA', 'SB', 'FR',
'WP', 'HA', 'NX', 'HU', 'VV', 'RE', 'CB', 'MZ', 'UM',
'FK', 'FX', 'WI', 'MN', 'M1', 'AH', 'SU', 'EU', 'EZ',
'UT', 'DT', 'S0', 'QU', 'YN', 'JB', 'GH', 'PI', 'SG',
'KD', 'PE', 'UH', 'S7', 'CW', 'OZ', 'GI', 'VE', 'C4',
];
/**
* Returns list of all available browsers
* @return array
*/
public static function getAvailableBrowsers(): array
{
return self::$availableBrowsers;
}
/**
* Returns list of all available browser families
* @return array
*/
public static function getAvailableBrowserFamilies(): array
{
return self::$browserFamilies;
}
/**
* @param string $browserLabel name or short name
*
* @return string|null If null, "Unknown"
*/
public static function getBrowserFamily(string $browserLabel): ?string
{
if (\in_array($browserLabel, self::$availableBrowsers)) {
$browserLabel = \array_search($browserLabel, self::$availableBrowsers);
}
foreach (self::$browserFamilies as $browserFamily => $browserLabels) {
if (\in_array($browserLabel, $browserLabels)) {
return $browserFamily;
}
}
return null;
}
/**
* Returns if the given browser is mobile only
*
* @param string $browser Label or name of browser
*
* @return bool
*/
public static function isMobileOnlyBrowser(string $browser): bool
{
return \in_array($browser, self::$mobileOnlyBrowsers) || (\in_array($browser, self::$availableBrowsers)
&& \in_array(\array_search($browser, self::$availableBrowsers), self::$mobileOnlyBrowsers));
}
/**
* @inheritdoc
*/
public function parse(): ?array
{
foreach ($this->getRegexes() as $regex) {
$matches = $this->matchUserAgent($regex['regex']);
if ($matches) {
break;
}
}
if (empty($matches) || empty($regex)) {
return null;
}
$name = $this->buildByMatch($regex['name'], $matches);
foreach (self::getAvailableBrowsers() as $browserShort => $browserName) {
if (\strtolower($name) === \strtolower($browserName)) {
$version = $this->buildVersion((string) $regex['version'], $matches);
$engine = $this->buildEngine($regex['engine'] ?? [], $version);
$engineVersion = $this->buildEngineVersion($engine);
return [
'type' => 'browser',
'name' => $browserName,
'short_name' => (string) $browserShort,
'version' => $version,
'engine' => $engine,
'engine_version' => $engineVersion,
];
}
}
// This Exception should never be thrown. If so a defined browser name is missing in $availableBrowsers
throw new \Exception(\sprintf(
'Detected browser name "%s" was not found in $availableBrowsers. Tried to parse user agent: %s',
$name,
$this->userAgent
)); // @codeCoverageIgnore
}
/**
* @param array $engineData
* @param string $browserVersion
*
* @return string
*/
protected function buildEngine(array $engineData, string $browserVersion): string
{
$engine = '';
// if an engine is set as default
if (isset($engineData['default'])) {
$engine = $engineData['default'];
}
// check if engine is set for browser version
if (\array_key_exists('versions', $engineData) && \is_array($engineData['versions'])) {
foreach ($engineData['versions'] as $version => $versionEngine) {
if (\version_compare($browserVersion, (string) $version) < 0) {
continue;
}
$engine = $versionEngine;
}
}
// try to detect the engine using the regexes
if (empty($engine)) {
$engineParser = new Engine();
$engineParser->setYamlParser($this->getYamlParser());
$engineParser->setCache($this->getCache());
$engineParser->setUserAgent($this->userAgent);
$result = $engineParser->parse();
$engine = $result['engine'] ?? '';
}
return $engine;
}
/**
* @param string $engine
*
* @return string
*/
protected function buildEngineVersion(string $engine): string
{
$engineVersionParser = new Engine\Version($this->userAgent, $engine);
$result = $engineVersionParser->parse();
return $result['version'] ?? '';
}
}