This commit is contained in:
coderkun 2015-04-27 16:42:05 +02:00
commit 046a724272
4209 changed files with 1186656 additions and 0 deletions

View file

@ -0,0 +1,3 @@
.idea/*
vendor/*
composer.phar

View file

@ -0,0 +1,13 @@
language: php
php:
- 5.3
- 5.4
- 5.5
before_script:
- composer self-update
- composer install
script:
- phpunit tests/DeviceDetectorTest.php

View file

@ -0,0 +1,967 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
class DeviceDetector
{
public static $deviceTypes = array(
'desktop', // 0
'smartphone', // 1
'tablet', // 2
'feature phone', // 3
'console', // 4
'tv', // 5
'car browser', // 6
'smart display', // 7
'camera' // 8
);
public static $deviceBrands = array(
'AC' => 'Acer',
'AI' => 'Airness',
'AL' => 'Alcatel',
'AN' => 'Arnova',
'AO' => 'Amoi',
'AP' => 'Apple',
'AR' => 'Archos',
'AU' => 'Asus',
'AV' => 'Avvio',
'AX' => 'Audiovox',
'BB' => 'BBK',
'BE' => 'Becker',
'BI' => 'Bird',
'BL' => 'Beetel',
'BO' => 'BangOlufsen',
'BQ' => 'BenQ',
'BS' => 'BenQ-Siemens',
'BX' => 'bq',
'CA' => 'Cat',
'CK' => 'Cricket',
'CL' => 'Compal',
'CN' => 'CnM',
'CR' => 'CreNova',
'CT' => 'Capitel',
'CO' => 'Coolpad',
'CU' => 'Cube',
'DE' => 'Denver',
'DB' => 'Dbtel',
'DC' => 'DoCoMo',
'DI' => 'Dicam',
'DL' => 'Dell',
'DM' => 'DMM',
'DP' => 'Dopod',
'EC' => 'Ericsson',
'EI' => 'Ezio',
'ER' => 'Ericy',
'ET' => 'eTouch',
'EZ' => 'Ezze',
'FL' => 'Fly',
'GD' => 'Gemini',
'GI' => 'Gionee',
'GG' => 'Gigabyte',
'GO' => 'Google',
'GR' => 'Gradiente',
'GU' => 'Grundig',
'HA' => 'Haier',
'HP' => 'HP',
'HT' => 'HTC',
'HU' => 'Huawei',
'HX' => 'Humax',
'IA' => 'Ikea',
'IK' => 'iKoMo',
'IM' => 'i-mate',
'IN' => 'Innostream',
'IX' => 'Intex',
'IO' => 'i-mobile',
'IQ' => 'INQ',
'IT' => 'Intek',
'IV' => 'Inverto',
'JI' => 'Jiayu',
'JO' => 'Jolla',
'KA' => 'Karbonn',
'KD' => 'KDDI',
'KN' => 'Kindle',
'KO' => 'Konka',
'KT' => 'K-Touch',
'KH' => 'KT-Tech',
'KY' => 'Kyocera',
'LA' => 'Lanix',
'LC' => 'LCT',
'LE' => 'Lenovo',
'LG' => 'LG',
'LO' => 'Loewe',
'LU' => 'LGUPlus',
'MA' => 'Manta Multimedia',
'MD' => 'Medion',
'ME' => 'Metz',
'MI' => 'MicroMax',
'MK' => 'MediaTek',
'MO' => 'Mio',
'MR' => 'Motorola',
'MS' => 'Microsoft',
'MT' => 'Mitsubishi',
'MY' => 'MyPhone',
'NE' => 'NEC',
'NG' => 'NGM',
'NI' => 'Nintendo',
'NK' => 'Nokia',
'NN' => 'Nikon',
'NW' => 'Newgen',
'NX' => 'Nexian',
'OD' => 'Onda',
'OP' => 'OPPO',
'OR' => 'Orange',
'OT' => 'O2',
'OU' => 'OUYA',
'PA' => 'Panasonic',
'PE' => 'PEAQ',
'PH' => 'Philips',
'PL' => 'Polaroid',
'PM' => 'Palm',
'PO' => 'phoneOne',
'PT' => 'Pantech',
'PP' => 'PolyPad',
'PR' => 'Prestigio',
'QT' => 'Qtek',
'RM' => 'RIM',
'RO' => 'Rover',
'SA' => 'Samsung',
'SD' => 'Sega',
'SE' => 'Sony Ericsson',
'SF' => 'Softbank',
'SG' => 'Sagem',
'SH' => 'Sharp',
'SI' => 'Siemens',
'SN' => 'Sendo',
'SO' => 'Sony',
'SP' => 'Spice',
'SU' => 'SuperSonic',
'SV' => 'Selevision',
'SY' => 'Sanyo',
'SM' => 'Symphony',
'SR' => 'Smart',
'TA' => 'Tesla',
'TC' => 'TCL',
'TE' => 'Telit',
'TH' => 'TiPhone',
'TI' => 'TIANYU',
'TL' => 'Telefunken',
'TM' => 'T-Mobile',
'TN' => 'Thomson',
'TO' => 'Toplux',
'TS' => 'Toshiba',
'TT' => 'TechnoTrend',
'TV' => 'TVC',
'TX' => 'TechniSat',
'TZ' => 'teXet',
'UT' => 'UTStarcom',
'VD' => 'Videocon',
'VE' => 'Vertu',
'VI' => 'Vitelcom',
'VK' => 'VK Mobile',
'VS' => 'ViewSonic',
'VT' => 'Vestel',
'VO' => 'Voxtel',
'VW' => 'Videoweb',
'WB' => 'Web TV',
'WE' => 'WellcoM',
'WO' => 'Wonu',
'WX' => 'Woxter',
'XI' => 'Xiaomi',
'XX' => 'Unknown',
'YU' => 'Yuandao',
'ZO' => 'Zonda',
'ZT' => 'ZTE',
);
public static $osShorts = array(
'AIX' => 'AIX',
'Android' => 'AND',
'AmigaOS' => 'AMG',
'Apple TV' => 'ATV',
'Arch Linux' => 'ARL',
'BackTrack' => 'BTR',
'Bada' => 'SBA',
'BeOS' => 'BEO',
'BlackBerry OS' => 'BLB',
'BlackBerry Tablet OS' => 'QNX',
'Bot' => 'BOT',
'Brew' => 'BMP',
'CentOS' => 'CES',
'Chrome OS' => 'COS',
'Debian' => 'DEB',
'DragonFly' => 'DFB',
'Fedora' => 'FED',
'Firefox OS' => 'FOS',
'FreeBSD' => 'BSD',
'Gentoo' => 'GNT',
'Google TV' => 'GTV',
'HP-UX' => 'HPX',
'Haiku OS' => 'HAI',
'IRIX' => 'IRI',
'Inferno' => 'INF',
'Knoppix' => 'KNO',
'Kubuntu' => 'KBT',
'Linux' => 'LIN',
'Lubuntu' => 'LBT',
'Mac' => 'MAC',
'Mandriva' => 'MDR',
'MeeGo' => 'SMG',
'Mint' => 'MIN',
'NetBSD' => 'NBS',
'Nintendo' => 'WII',
'Nintendo Mobile' => 'NDS',
'OS/2' => 'OS2',
'OSF1' => 'T64',
'OpenBSD' => 'OBS',
'PlayStation Portable' => 'PSP',
'PlayStation' => 'PS3',
'Presto' => 'PRS',
'Puppy' => 'PPY',
'Red Hat' => 'RHT',
'RISC OS' => 'ROS',
'Sabayon' => 'SAB',
'SUSE' => 'SSE',
'Sailfish OS' => 'SAF',
'Slackware' => 'SLW',
'Solaris' => 'SOS',
'Syllable' => 'SYL',
'Symbian' => 'SYM',
'Symbian OS' => 'SYS',
'Symbian OS Series 40' => 'S40',
'Symbian OS Series 60' => 'S60',
'Symbian^3' => 'SY3',
'Talkatone' => 'TKT',
'Tizen' => 'TIZ',
'Ubuntu' => 'UBT',
'WebTV' => 'WTV',
'WinWAP' => 'WWP',
'Windows' => 'WIN',
'Windows 2000' => 'W2K',
'Windows 3.1' => 'W31',
'Windows 7' => 'WI7',
'Windows 8' => 'WI8',
'Windows 95' => 'W95',
'Windows 98' => 'W98',
'Windows CE' => 'WCE',
'Windows ME' => 'WME',
'Windows Mobile' => 'WMO',
'Windows NT' => 'WNT',
'Windows Phone' => 'WPH',
'Windows RT' => 'WRT',
'Windows Server 2003' => 'WS3',
'Windows Vista' => 'WVI',
'Windows XP' => 'WXP',
'Xbox' => 'XBX',
'Xubuntu' => 'XBT',
'YunOs' => 'YNS',
'iOS' => 'IOS',
'palmOS' => 'POS',
'webOS' => 'WOS'
);
protected static $desktopOsArray = array('AmigaOS', 'IBM', 'Linux', 'Mac', 'Unix', 'Windows', 'BeOS');
public static $osFamilies = array(
'Android' => array('AND'),
'AmigaOS' => array('AMG'),
'Apple TV' => array('ATV'),
'BlackBerry' => array('BLB', 'QNX'),
'Bot' => array('BOT'),
'Brew' => array('BMP'),
'BeOS' => array('BEO', 'HAI'),
'Chrome OS' => array('COS'),
'Firefox OS' => array('FOS'),
'Gaming Console' => array('WII', 'PS3'),
'Google TV' => array('GTV'),
'IBM' => array('OS2'),
'iOS' => array('IOS'),
'RISC OS' => array('ROS'),
'Linux' => array('LIN', 'ARL', 'DEB', 'KNO', 'MIN', 'UBT', 'KBT', 'XBT', 'LBT', 'FED', 'RHT', 'MDR', 'GNT', 'SAB', 'SLW', 'SSE', 'PPY', 'CES', 'BTR', 'YNS', 'PRS', 'SAF'),
'Mac' => array('MAC'),
'Mobile Gaming Console' => array('PSP', 'NDS', 'XBX'),
'Other Mobile' => array('WOS', 'POS', 'SBA', 'TIZ', 'SMG'),
'Simulator' => array('TKT', 'WWP'),
'Symbian' => array('SYM', 'SYS', 'SY3', 'S60', 'S40'),
'Unix' => array('SOS', 'AIX', 'HPX', 'BSD', 'NBS', 'OBS', 'DFB', 'SYL', 'IRI', 'T64', 'INF'),
'WebTV' => array('WTV'),
'Windows' => array('WI7', 'WI8', 'WVI', 'WS3', 'WXP', 'W2K', 'WNT', 'WME', 'W98', 'W95', 'WRT', 'W31', 'WIN'),
'Windows Mobile' => array('WPH', 'WMO', 'WCE')
);
public static $browserFamilies = array(
'Android Browser' => array('AN'),
'BlackBerry Browser' => array('BB'),
'Chrome' => array('CH', 'CD', 'CM', 'CI', 'CF', 'CN', 'CR', 'CP', 'RM'),
'Firefox' => array('FF', 'FE', 'SX', 'FB', 'PX', 'MB'),
'Internet Explorer' => array('IE', 'IM'),
'Konqueror' => array('KO'),
'NetFront' => array('NF'),
'Nokia Browser' => array('NB', 'NO', 'NV'),
'Opera' => array('OP', 'OM', 'OI', 'ON'),
'Safari' => array('SF', 'MF'),
'Sailfish Browser' => array('SA')
);
public static $browsers = array(
'AA' => 'Avant Browser',
'AB' => 'ABrowse',
'AG' => 'ANTGalio',
'AM' => 'Amaya',
'AN' => 'Android Browser',
'AR' => 'Arora',
'AV' => 'Amiga Voyager',
'AW' => 'Amiga Aweb',
'BB' => 'BlackBerry Browser',
'BD' => 'Baidu Browser',
'BE' => 'Beonex',
'BJ' => 'Bunjalloo',
'BX' => 'BrowseX',
'CA' => 'Camino',
'CD' => 'Comodo Dragon',
'CX' => 'Charon',
'CF' => 'Chrome Frame',
'CH' => 'Chrome',
'CI' => 'Chrome Mobile iOS',
'CK' => 'Conkeror',
'CM' => 'Chrome Mobile',
'CN' => 'CoolNovo',
'CO' => 'CometBird',
'CP' => 'ChromePlus',
'CR' => 'Chromium',
'CS' => 'Cheshire',
'DF' => 'Dolphin',
'DI' => 'Dillo',
'EL' => 'Elinks',
'EP' => 'Epiphany',
'ES' => 'Espial TV Browser',
'FB' => 'Firebird',
'FD' => 'Fluid',
'FE' => 'Fennec',
'FF' => 'Firefox',
'FL' => 'Flock',
'FN' => 'Fireweb Navigator',
'GA' => 'Galeon',
'GE' => 'Google Earth',
'HJ' => 'HotJava',
'IA' => 'Iceape',
'IB' => 'IBrowse',
'IC' => 'iCab',
'ID' => 'IceDragon',
'IW' => 'Iceweasel',
'IE' => 'Internet Explorer',
'IM' => 'IE Mobile',
'IR' => 'Iron',
'JS' => 'Jasmine',
'KI' => 'Kindle Browser',
'KM' => 'K-meleon',
'KO' => 'Konqueror',
'KP' => 'Kapiko',
'KZ' => 'Kazehakase',
'LG' => 'Lightning',
'LI' => 'Links',
'LS' => 'Lunascape',
'LX' => 'Lynx',
'MB' => 'MicroB',
'MC' => 'NCSA Mosaic',
'ME' => 'Mercury',
'MF' => 'Mobile Safari',
'MI' => 'Midori',
'MS' => 'Mobile Silk',
'MX' => 'Maxthon',
'NB' => 'Nokia Browser',
'NO' => 'Nokia OSS Browser',
'NV' => 'Nokia Ovi Browser',
'NF' => 'NetFront',
'NL' => 'NetFront Life',
'NP' => 'NetPositive',
'NS' => 'Netscape',
'OB' => 'Obigo',
'OI' => 'Opera Mini',
'OM' => 'Opera Mobile',
'OP' => 'Opera',
'ON' => 'Opera Next',
'OR' => 'Oregano',
'OV' => 'Openwave Mobile Browser',
'OW' => 'OmniWeb',
'PL' => 'Palm Blazer',
'PM' => 'Pale Moon',
'PR' => 'Palm Pre',
'PU' => 'Puffin',
'PW' => 'Palm WebPro',
'PX' => 'Phoenix',
'PO' => 'Polaris',
'RK' => 'Rekonq',
'RM' => 'RockMelt',
'SA' => 'Sailfish Browser',
'SF' => 'Safari',
'SL' => 'Sleipnir',
'SM' => 'SeaMonkey',
'SN' => 'Snowshoe',
'SX' => 'Swiftfox',
'TB' => 'Thunderbird',
'TZ' => 'Tizen Browser',
'UC' => 'UC Browser',
'WE' => 'WebPositive',
'WO' => 'wOSBrowser',
'YA' => 'Yandex Browser',
'XI' => 'Xiino'
);
const UNKNOWN = "UNK";
protected static $regexesDir = '/regexes/';
protected static $osRegexesFile = 'oss.yml';
protected static $browserRegexesFile = 'browsers.yml';
protected static $mobileRegexesFile = 'mobiles.yml';
protected static $televisionRegexesFile = 'televisions.yml';
protected $userAgent;
protected $os = '';
protected $browser = '';
protected $device = '';
protected $brand = '';
protected $model = '';
protected $debug = false;
/**
* @var \Piwik\CacheFile
*/
protected $cache = null;
public function __construct($userAgent)
{
$this->userAgent = $userAgent;
}
protected function getOsRegexes()
{
static $regexOs;
if(empty($regexOs)) {
$regexOs = $this->getRegexList('os', self::$osRegexesFile);
}
return $regexOs;
}
protected function getBrowserRegexes()
{
static $regexBrowser;
if (empty($regexBrowser)) {
$regexBrowser = $this->getRegexList('browser', self::$browserRegexesFile);
}
return $regexBrowser;
}
protected function getMobileRegexes()
{
static $regexMobile;
if (empty($regexMobile)) {
$regexMobile = $this->getRegexList('mobile', self::$mobileRegexesFile);
}
return $regexMobile;
}
protected function getTelevisionRegexes()
{
static $regexTvs;
if (empty($regexTvs)) {
$regexTvs = $this->getRegexList('tv', self::$televisionRegexesFile);
}
return $regexTvs;
}
public function setCache($cache)
{
$this->cache = $cache;
}
protected function saveParsedYmlInCache($type, $data)
{
if (!empty($this->cache) && method_exists($this->cache, 'set')) {
$this->cache->set($type, serialize($data));
}
}
protected function getParsedYmlFromCache($type)
{
$data = null;
if (!empty($this->cache) && method_exists($this->cache, 'get')) {
$data = $this->cache->get($type);
if (!empty($data)) {
$data = unserialize($data);
}
}
return $data;
}
public function parse()
{
$this->parseOs();
if ($this->isBot() || $this->isSimulator())
return;
$this->parseBrowser();
if($this->isHbbTv()) {
$this->parseTelevision();
} else {
$this->parseMobile();
}
if (empty($this->device) && $this->isHbbTv()) {
$this->device = array_search('tv', self::$deviceTypes);
} else if (empty($this->device) && $this->isDesktop()) {
$this->device = array_search('desktop', self::$deviceTypes);
}
/**
* Android up to 3.0 was designed for smartphones only. But as 3.0, which was tablet only, was published
* too late, there were a bunch of tablets running with 2.x
* With 4.0 the two trees were merged and it is for smartphones and tablets
*
* So were are expecting that all devices running Android < 2 are smartphones
* Devices running Android 3.X are tablets. Device type of Android 2.X and 4.X+ are unknown
*/
if (empty($this->device) && $this->getOs('short_name') == 'AND' && $this->getOs('version') != '') {
if (version_compare($this->getOs('version'), '2.0') == -1) {
$this->device = array_search('smartphone', self::$deviceTypes);
} else if (version_compare($this->getOs('version'), '3.0') >= 0 AND version_compare($this->getOs('version'), '4.0') == -1) {
$this->device = array_search('tablet', self::$deviceTypes);
}
}
/**
* According to http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
* Internet Explorer 10 introduces the "Touch" UA string token. If this token is present at the end of the
* UA string, the computer has touch capability, and is running Windows 8 (or later).
* This UA string will be transmitted on a touch-enabled system running Windows 8 (RT)
*
* As most touch enabled devices are tablets and only a smaller part are desktops/notebooks we assume that
* all Windows 8 touch devices are tablets.
*/
if (empty($this->device) && in_array($this->getOs('short_name'), array('WI8', 'WRT')) && $this->isTouchEnabled()) {
$this->device = array_search('tablet', self::$deviceTypes);
}
if ($this->debug) {
var_export($this->brand, $this->model, $this->device);
}
}
protected function parseOs()
{
foreach ($this->getOsRegexes() as $osRegex) {
$matches = $this->matchUserAgent($osRegex['regex']);
if ($matches)
break;
}
if (!$matches)
return;
$name = $this->buildOsName($osRegex['name'], $matches);
$short = 'UNK';
foreach (self::$osShorts AS $osName => $osShort) {
if (strtolower($name) == strtolower($osName)) {
$name = $osName;
$short = $osShort;
}
}
$this->os = array(
'name' => $name,
'short_name' => $short,
'version' => $this->buildOsVersion($osRegex['version'], $matches)
);
if (array_key_exists($this->os['name'], self::$osShorts)) {
$this->os['short_name'] = self::$osShorts[$this->os['name']];
}
}
protected function parseBrowser()
{
foreach ($this->getBrowserRegexes() as $browserRegex) {
$matches = $this->matchUserAgent($browserRegex['regex']);
if ($matches)
break;
}
if (!$matches)
return;
$name = $this->buildBrowserName($browserRegex['name'], $matches);
$short = 'XX';
foreach (self::$browsers AS $browserShort => $browserName) {
if (strtolower($name) == strtolower($browserName)) {
$name = $browserName;
$short = $browserShort;
}
}
$this->browser = array(
'name' => $name,
'short_name' => $short,
'version' => $this->buildBrowserVersion($browserRegex['version'], $matches)
);
}
protected function parseMobile()
{
$mobileRegexes = $this->getMobileRegexes();
$this->parseBrand($mobileRegexes);
$this->parseModel($mobileRegexes);
}
protected function parseTelevision()
{
$televisionRegexes = $this->getTelevisionRegexes();
$this->parseBrand($televisionRegexes);
$this->parseModel($televisionRegexes);
}
protected function parseBrand($deviceRegexes)
{
foreach ($deviceRegexes as $brand => $mobileRegex) {
$matches = $this->matchUserAgent($mobileRegex['regex']);
if ($matches)
break;
}
if (!$matches)
return;
$brandId = array_search($brand, self::$deviceBrands);
if($brandId === false) {
throw new Exception("The brand with name '$brand' should be listed in the deviceBrands array.");
}
$this->brand = $brandId;
$this->fullName = $brand;
if (isset($mobileRegex['device'])) {
$this->device = array_search($mobileRegex['device'], self::$deviceTypes);
}
if (isset($mobileRegex['model'])) {
$this->model = $this->buildModel($mobileRegex['model'], $matches);
}
}
protected function parseModel($deviceRegexes)
{
if (empty($this->brand) || !empty($this->model) || empty($deviceRegexes[$this->fullName]['models']))
return;
foreach ($deviceRegexes[$this->fullName]['models'] as $modelRegex) {
$matches = $this->matchUserAgent($modelRegex['regex']);
if ($matches)
break;
}
if (!$matches) {
return;
}
$this->model = trim($this->buildModel($modelRegex['model'], $matches));
if (isset($modelRegex['device'])) {
$this->device = array_search($modelRegex['device'], self::$deviceTypes);
}
}
protected function matchUserAgent($regex)
{
$regex = '/(?:^|[^A-Z_-])(?:' . str_replace('/', '\/', $regex) . ')/i';
if (preg_match($regex, $this->userAgent, $matches)) {
return $matches;
}
return false;
}
protected function buildOsName($osName, $matches)
{
return $this->buildByMatch($osName, $matches);
}
protected function buildOsVersion($osVersion, $matches)
{
$osVersion = $this->buildByMatch($osVersion, $matches);
$osVersion = $this->buildByMatch($osVersion, $matches, '2');
$osVersion = str_replace('_', '.', $osVersion);
return $osVersion;
}
protected function buildBrowserName($browserName, $matches)
{
return $this->buildByMatch($browserName, $matches);
}
protected function buildBrowserVersion($browserVersion, $matches)
{
$browserVersion = $this->buildByMatch($browserVersion, $matches);
$browserVersion = $this->buildByMatch($browserVersion, $matches, '2');
$browserVersion = str_replace('_', '.', $browserVersion);
return $browserVersion;
}
protected function buildModel($model, $matches)
{
$model = $this->buildByMatch($model, $matches);
$model = $this->buildByMatch($model, $matches, '2');
$model = $this->buildModelExceptions($model);
$model = str_replace('_', ' ', $model);
return $model;
}
protected function buildModelExceptions($model)
{
if ($this->brand == 'O2') {
$model = preg_replace('/([a-z])([A-Z])/', '$1 $2', $model);
$model = ucwords(str_replace('_', ' ', $model));
}
return $model;
}
/**
* This method is used in this class for processing results of pregmatch
* results into string containing recognized information.
*
* General algorithm:
* Parsing UserAgent string consists of trying to match it against list of
* regular expressions for three different information:
* browser + version,
* OS + version,
* device manufacturer + model.
*
* After match has been found iteration stops, and results are processed
* by buildByMatch.
* As $item we get decoded name (name of browser, name of OS, name of manufacturer).
* In array $match we recieve preg_match results containing whole string matched at index 0
* and following matches in further indexes. Desired action now is to concatenate
* decoded name ($item) with matches found. First step is to append first found match,
* which is located in index=1 (that's why $nb is 1 by default).
* In other cases, where whe know that preg_match may return more than 1 result,
* we call buildByMatch with $nb = 2 or more, depending on what will be returned from
* regular expression.
*
* Example:
* We are parsing UserAgent of Firefox 20.0 browser.
* UserAgentParserEnhanced calls buildBrowserName() and buildBrowserVersion() in order
* to retrieve those information.
* In buildBrowserName() we only have one call of buildByMatch, where passed argument
* is regular expression testing given string for browser name. In this case, we are only
* interrested in first hit, so no $nb parameter will be set to 1. After finding match, and calling
* buildByMatch - we will receive just the name of browser.
*
* Also after decoding browser we will get list of regular expressions for this browser name
* testing UserAgent string for version number. Again we iterate over this list, and after finding first
* occurence - we break loop and proceed to build by match. Since browser regular expressions can
* contain two hits (major version and minor version) in function buildBrowserVersion() we have
* two calls to buildByMatch, one without 3rd parameter, and second with $nb set to 2.
* This way we can retrieve version number, and assign it to object property.
*
* In case of mobiles.yml this schema slightly varies, but general idea is the same.
*
* @param string $item
* @param array $matches
* @param int|string $nb
* @return string type
*/
protected function buildByMatch($item, $matches, $nb = '1')
{
if (strpos($item, '$' . $nb) === false)
return $item;
$replace = isset($matches[$nb]) ? $matches[$nb] : '';
return trim(str_replace('$' . $nb, $replace, $item));
}
public function isBot()
{
return $this->getOsFamily($this->getOs('short_name')) == 'Bot';
}
public function isSimulator()
{
return $this->getOsFamily($this->getOs('short_name')) == 'Simulator';
}
public function isHbbTv()
{
$regex = 'HbbTV/([1-9]{1}(\.[0-9]{1}){1,2})';
return $this->matchUserAgent($regex);
}
public function isTouchEnabled()
{
$regex = 'Touch';
return $this->matchUserAgent($regex);
}
public function isMobile()
{
return !$this->isDesktop();
}
public function isDesktop()
{
$osName = $this->getOs('name');
if (empty($osName) || empty(self::$osShorts[$osName])) {
return false;
}
$osShort = self::$osShorts[$osName];
foreach (self::$osFamilies as $family => $familyOs) {
if (in_array($osShort, $familyOs)) {
$decodedFamily = $family;
break;
}
}
return in_array($decodedFamily, self::$desktopOsArray);
}
public function getOs($attr = '')
{
if ($attr == '') {
return $this->os;
}
if (!isset($this->os[$attr])) {
return self::UNKNOWN;
}
return $this->os[$attr];
}
public function getBrowser($attr = '')
{
if ($attr == '') {
return $this->browser;
}
if (!isset($this->browser[$attr])) {
return self::UNKNOWN;
}
return $this->browser[$attr];
}
public function getDevice()
{
return $this->device;
}
public function getBrand()
{
return $this->brand;
}
public function getModel()
{
return $this->model;
}
public function getUserAgent()
{
return $this->userAgent;
}
/**
* @param $osLabel
* @return bool|string If false, "Unknown"
*/
public static function getOsFamily($osLabel)
{
foreach (self::$osFamilies as $family => $labels) {
if (in_array($osLabel, $labels)) {
return $family;
}
}
return false;
}
/**
* @param $browserLabel
* @return bool|string If false, "Unknown"
*/
public static function getBrowserFamily($browserLabel)
{
foreach (self::$browserFamilies as $browserFamily => $browserLabels) {
if (in_array($browserLabel, $browserLabels)) {
return $browserFamily;
}
}
return false;
}
public static function getOsNameFromId($os, $ver = false)
{
$osFullName = array_search($os, self::$osShorts);
if ($osFullName) {
if (in_array($os, self::$osFamilies['Windows'])) {
return $osFullName;
} else {
return trim($osFullName . " " . $ver);
}
}
return false;
}
static public function getInfoFromUserAgent($ua)
{
$userAgentParserEnhanced = new DeviceDetector($ua);
$userAgentParserEnhanced->parse();
$osFamily = $userAgentParserEnhanced->getOsFamily($userAgentParserEnhanced->getOs('short_name'));
$browserFamily = $userAgentParserEnhanced->getBrowserFamily($userAgentParserEnhanced->getBrowser('short_name'));
$device = $userAgentParserEnhanced->getDevice();
$deviceName = $device === '' ? '' : DeviceDetector::$deviceTypes[$device];
$processed = array(
'user_agent' => $userAgentParserEnhanced->getUserAgent(),
'os' => array(
'name' => $userAgentParserEnhanced->getOs('name'),
'short_name' => $userAgentParserEnhanced->getOs('short_name'),
'version' => $userAgentParserEnhanced->getOs('version'),
),
'browser' => array(
'name' => $userAgentParserEnhanced->getBrowser('name'),
'short_name' => $userAgentParserEnhanced->getBrowser('short_name'),
'version' => $userAgentParserEnhanced->getBrowser('version'),
),
'device' => array(
'type' => $deviceName,
'brand' => $userAgentParserEnhanced->getBrand(),
'model' => $userAgentParserEnhanced->getModel(),
),
'os_family' => $osFamily !== false ? $osFamily : 'Unknown',
'browser_family' => $browserFamily !== false ? $browserFamily : 'Unknown',
);
return $processed;
}
protected function getRegexList($type, $regexesFile)
{
$regexList = $this->getParsedYmlFromCache($type);
if (empty($regexList)) {
$regexList = Spyc::YAMLLoad(dirname(__FILE__) . self::$regexesDir . $regexesFile);
$this->saveParsedYmlInCache($type, $regexList);
}
return $regexList;
}
}

View file

@ -0,0 +1,7 @@
DeviceDetector
==============
The Universal Device Detection library, that parses User Agents and detects devices (desktop, tablet, mobile, tv, cars, console, etc.), and detects browsers, operating systems, devices, brands and models.
Build status (master branch) [![Build Status](https://travis-ci.org/piwik/DeviceDetector.png?branch=master)](https://travis-ci.org/piwik/DeviceDetector)

View file

@ -0,0 +1,28 @@
{
"name": "piwik/device-detector",
"type": "library",
"description": "The Universal Device Detection library, that parses User Agents and detects devices (desktop, tablet, mobile, tv, cars, console, etc.), and detects browsers, operating systems, devices, brands and models.",
"keywords": ["useragent","parser","devicedetection"],
"homepage": "http://piwik.org",
"license": "GPL-3.0+",
"authors": [
{
"name": "The Piwik Team",
"email": "hello@piwik.org",
"homepage": "http://piwik.org/the-piwik-team/"
}
],
"support": {
"forum": "http://forum.piwik.org/",
"issues": "http://dev.piwik.org/trac/roadmap",
"wiki": "http://dev.piwik.org/",
"source": "https://github.com/piwik/piwik"
},
"autoload": {
"files": [ "DeviceDetector.php" ]
},
"require": {
"php": ">=5.3.1",
"mustangostang/spyc": "*"
}
}

View file

@ -0,0 +1,540 @@
###############
# Piwik - Open source web analytics
#
# @link http://piwik.org
# @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
#
# @category UserAgentParserEnhanced
###############
#SailfishBrowser
- regex: 'SailfishBrowser(?:/(\d+\.\d+))?'
name: 'Sailfish Browser'
version: '$1'
# SeaMonkey
- regex: '(Iceape|SeaMonkey|gnuzilla)(?:/(\d+\.\d+))?'
name: '$1'
version: '$2'
# Camino
- regex: 'Camino(?:/(\d+\.\d+))?'
name: 'Camino'
version: '$1'
#Fennec (Firefox for mobile)
- regex: 'Fennec(?:/(\d+\.\d+))?'
name: 'Fennec'
version: '$1'
#MicroB
- regex: 'Firefox.*Tablet browser (\d+\.\d+)'
name: 'MicroB'
version: '$1'
#Avant Browser
- regex: 'Avant Browser'
name: 'Avant Browser'
version: ''
#Bunjalloo
- regex: 'Bunjalloo(?:/(\d+\.\d+))?'
name: 'Bunjalloo'
version: '$1'
#Iceweasel
- regex: 'Iceweasel(?:/(\d+\.\d+))?'
name: 'Iceweasel'
version: '$1'
#WebPositive
- regex: 'WebPositive'
name: 'WebPositive'
version: ''
#Pale Moon
- regex: 'PaleMoon(?:/(\d+\.\d+))?'
name: 'Pale Moon'
version: '$1'
#CometBird
- regex: 'CometBird(?:/(\d+\.\d+))?'
name: 'CometBird'
version: '$1'
#IceDragon
- regex: 'IceDragon(?:/(\d+\.\d+))?'
name: 'IceDragon'
version: '$1'
#Flock
- regex: 'Flock(?:/(\d+\.\d+))?'
name: 'Flock'
version: '$1'
#Swiftfox
- regex: 'Firefox/(\d+\.\d+).*\(Swiftfox\)'
name: 'Swiftfox'
version: '$1'
#Firefox
- regex: 'Firefox(?:/(\d+\.\d+))?'
name: 'Firefox'
version: '$1'
- regex: '(BonEcho|GranParadiso|Lorentz|Minefield|Namoroka|Shiretoko)/(\d+\.\d+)'
name: 'Firefox'
version: '$1 ($2)'
#ANTGalio
- regex: 'ANTGalio(?:/(\d+\.\d+))?'
name: 'ANTGalio'
version: '$1'
#Espial TV Browser
- regex: '(?:Espial|Escape)(?:[/ ](\d+\.\d+))?'
name: 'Espial TV Browser'
version: '$1'
#RockMelt
- regex: 'RockMelt(?:/(\d+\.\d+))?'
name: 'RockMelt'
version: '$1'
#Netscape
- regex: '(?:Navigator|Netscape6)(?:/(\d+\.\d+))?'
name: 'Netscape'
version: '$1'
#Opera
- regex: '(?:Opera Tablet.*Version|Opera/.+Opera Mobi.+Version|Mobile.+OPR)/(\d+\.\d+)'
name: 'Opera Mobile'
version: '$1'
- regex: 'Opera Mini/(?:att/)?(\d+\.\d+)'
name: 'Opera Mini'
version: '$1'
- regex: 'Opera.+Edition Next.+Version/(\d+\.\d+)'
name: 'Opera Next'
version: '$1'
- regex: '(?:Opera|OPR)[/ ](?:9.80.*Version/)?(\d+\.\d+).+Edition Next'
name: 'Opera Next'
version: '$1'
- regex: '(?:Opera|OPR)[/ ](?:9.80.*Version/)?(\d+\.\d+)'
name: 'Opera'
version: '$1'
#wOSBrowser
- regex: '(?:hpw|web)OS/(\d+\.\d+)'
name: 'wOSBrowser'
version: '$1'
#Rekonq
- regex: 'rekonq(?:/(\d+\.\d+))?'
name: 'Rekonq'
version: '$1'
#CoolNovo
- regex: 'CoolNovo(?:/(\d+\.\d+))?'
name: 'CoolNovo'
version: '$1'
#Comodo Dragon
- regex: 'Comodo[ _]Dragon(?:/(\d+\.\d+))?'
name: 'Comodo Dragon'
version: '$1'
#ChromePlus
- regex: 'ChromePlus(?:/(\d+\.\d+))?'
name: 'ChromePlus'
version: '$1'
#Conkeror
- regex: 'Conkeror(?:/(\d+\.\d+))?'
name: 'Conkeror'
version: '$1'
#Konqueror
- regex: 'Konqueror(?:/(\d+\.\d+))?'
name: 'Konqueror'
version: '$1'
#Baidu Browser
- regex: 'baidubrowser(?:[/ ](\d+(?:\.?\d+)?))?'
name: 'Baidu Browser'
version: '$1'
#Yandex Browser
- regex: 'YaBrowser(?:/(\d+(?:\.?\d+)?))?'
name: 'Yandex Browser'
version: '$1'
#Midori
- regex: 'Midori(?:/(\d+\.\d+))?'
name: 'Midori'
version: '$1'
#Mercury
- regex: 'Mercury(?:/(\d+\.\d+))?'
name: 'Mercury'
version: '$1'
#Maxthon
- regex: 'Maxthon[ /](\d+\.\d+)'
name: 'Maxthon'
version: '$1'
- regex: '(?:Maxthon|MyIE2|Uzbl|Shiira)'
name: 'Maxthon'
version: ''
#Puffin
- regex: 'Puffin(?:/(\d+\.\d+))?'
name: 'Puffin'
version: '$1'
#Iron
- regex: 'Iron(?:/(\d+\.\d+))?'
name: 'Iron'
version: '$1'
#Epiphany
- regex: 'Epiphany(?:/(\d+\.\d+))?'
name: 'Epiphany'
version: '$1'
#Chrome
- regex: 'CrMo(?:/(\d+\.\d+))?'
name: 'Chrome Mobile'
version: '$1'
- regex: 'CriOS(?:/(\d+\.\d+))?'
name: 'Chrome Mobile iOS'
version: '$1'
- regex: 'Chrome(?:/(\d+\.\d+))?.*Mobile'
name: 'Chrome Mobile'
version: '$1'
- regex: 'chromeframe(?:/(\d+\.\d+))?'
name: 'Chrome Frame'
version: '$1'
- regex: 'Chrome(?:/(\d+\.\d+))?'
name: 'Chrome'
version: '$1'
- regex: 'Chromium(?:/(\d+\.\d+))?'
name: 'Chromium'
version: '$1'
#UC Browser
- regex: 'UC[ ]?Browser(?:[ /]?(\d+\.\d+))?'
name: 'UC Browser'
version: '$1'
- regex: 'UCWEB(?:[ /]?(\d+\.\d+))?'
name: 'UC Browser'
version: '$1'
#Tizen Browser
- regex: '(?:Tizen|SLP) Browser(?:/(\d+\.\d+))?'
name: 'Tizen Browser'
version: '$1'
#Palm Blazer
- regex: 'Blazer(?:/(\d+\.\d+))?'
name: 'Palm Blazer'
version: '$1'
- regex: 'Pre/(\d+\.\d+)'
name: 'Palm Pre'
version: '$1'
#Palm WebPro
- regex: 'WebPro(?:[ /](\d+\.\d+))?'
name: 'Palm WebPro'
version: '$1'
#Fireweb Navigator
- regex: 'Fireweb Navigator(?:/(\d+\.\d+))?'
name: 'Fireweb Navigator'
version: '$1'
#Jasmine
- regex: 'Jasmine(?:[ /](\d+\.\d+))?'
name: 'Jasmine'
version: '$1'
#Lynx
- regex: 'Lynx(?:/(\d+\.\d+))?'
name: 'Lynx'
version: '$1'
#NCSA Mosaic
- regex: 'NCSA_Mosaic(?:/(\d+\.\d+))?'
name: 'NCSA Mosaic'
version: '$1'
#ABrowse
- regex: 'ABrowse(?: (\d+\.\d+))?'
name: 'ABrowse'
version: '$1'
#Amaya
- regex: 'amaya(?:/(\d+\.\d+))?'
name: 'Amaya'
version: '$1'
#Amiga Voyager
- regex: 'AmigaVoyager(?:/(\d+\.\d+))?'
name: 'Amiga Voyager'
version: '$1'
#Amiga Aweb
- regex: 'Amiga-Aweb(?:/(\d+\.\d+))?'
name: 'Amiga Aweb'
version: '$1'
#Arora
- regex: 'Arora(?:/(\d+\.\d+))?'
name: 'Arora'
version: '$1'
#Beonex
- regex: 'Beonex(?:/(\d+\.\d+))?'
name: 'Beonex'
version: '$1'
#BlackBerry Browser
- regex: 'BlackBerry|PlayBook|BB10'
name: 'BlackBerry Browser'
version: ''
#BrowseX
- regex: 'BrowseX \((\d+\.\d+)'
name: 'BrowseX'
version: '$1'
#Charon
- regex: 'Charon(?:[/ ](\d+\.\d+))?'
name: 'Charon'
version: '$1'
#Cheshire
- regex: 'Cheshire(?:/(\d+\.\d+))?'
name: 'Cheshire'
version: '$1'
#Dillo
- regex: 'Dillo(?:/(\d+\.\d+))?'
name: 'Dillo'
version: '$1'
#Dolphin
- regex: 'Dolfin(?:/(\d+\.\d+))?|dolphin'
name: 'Dolphin'
version: '$1'
#Elinks
- regex: 'Elinks(?:/(\d+\.\d+))?'
name: 'Elinks'
version: '$1'
#Firebird
- regex: 'Firebird(?:/(\d+\.\d+))?'
name: 'Firebird'
version: '$1'
#Fluid
- regex: 'Fluid(?:/(\d+\.\d+))?'
name: 'Fluid'
version: '$1'
#Galeon
- regex: 'Galeon(?:/(\d+\.\d+))?'
name: 'Galeon'
version: '$1'
#Google Earth
- regex: 'Google Earth(?:/(\d+\.\d+))?'
name: 'Google Earth'
version: '$1'
#HotJava
- regex: 'HotJava(?:/(\d+\.\d+))?'
name: 'HotJava'
version: '$1'
#IBrowse
- regex: 'IBrowse(?:[ /](\d+\.\d+))?'
name: 'IBrowse'
version: '$1'
#iCab
- regex: 'iCab(?:[ /](\d+\.\d+))?'
name: 'iCab'
version: '$1'
#Sleipnir
- regex: 'Sleipnir(?:[ /](\d+\.\d+))?'
name: 'Sleipnir'
version: '$1'
#Lunascape
- regex: 'Lunascape(?:[/ ](\d+\.\d+))?'
name: 'Lunascape'
version: '$1'
#Internet Explorer
- regex: 'IEMobile[ /](\d+\.\d+)'
name: 'IE Mobile'
version: '$1'
- regex: 'MSIE (\d+\.\d+).*XBLWP7'
name: 'IE Mobile'
version: '$1'
- regex: 'MSIE.*Trident/4.0'
name: 'Internet Explorer'
version: 8.0
- regex: 'MSIE.*Trident/5.0'
name: 'Internet Explorer'
version: 9.0
- regex: 'MSIE.*Trident/6.0'
name: 'Internet Explorer'
version: 10.0
- regex: 'Trident/7.0'
name: 'Internet Explorer'
version: 11.0
- regex: 'MSIE (\d+\.\d+)'
name: 'Internet Explorer'
version: '$1'
- regex: 'IE[ /](\d+\.\d+)'
name: 'Internet Explorer'
version: '$1'
#Kapiko
- regex: 'Kapiko(?:/(\d+\.\d+))?'
name: 'Kapiko'
version: '$1'
#Kazehakase
- regex: 'Kazehakase(?:/(\d+\.\d+))?'
name: 'Kazehakase'
version: '$1'
#Kindle Browser
- regex: 'Kindle/(\d+\.\d+)'
name: 'Kindle Browser'
version: '$1'
#K-meleon
- regex: 'K-meleon(?:/(\d+\.\d+))?'
name: 'K-meleon'
version: '$1'
#Lightning
- regex: 'Lightning(?:/(\d+\.\d+))?'
name: 'Lightning'
version: '$1'
#Links
- regex: 'Links(?: \((\d+\.\d+))?'
name: 'Links'
version: '$1'
#Openwave Mobile Browser
- regex: 'UP.Browser(?:/(\d+\.\d+))?'
name: 'Openwave Mobile Browser'
version: '$1'
#OmniWeb
- regex: 'OmniWeb(?:/[v]?(\d+\.\d+))?'
name: 'OmniWeb'
version: '$1'
#Phoenix
- regex: 'Phoenix(?:/(\d+\.\d+))?'
name: 'Phoenix'
version: '$1'
#Mobile Silk
- regex: 'Silk(?:/(\d+\.\d+))?'
name: 'Mobile Silk'
version: '$1'
#Nokia Browser
- regex: '(?:NokiaBrowser|BrowserNG)(?:/(\d+\.\d+))?'
name: 'Nokia Browser'
version: '$1'
- regex: 'Series60/5\.0'
name: 'Nokia Browser'
version: '7.0'
- regex: 'Series60/(\d+\.\d+)'
name: 'Nokia OSS Browser'
version: '$1'
- regex: 'S40OviBrowser/(\d+\.\d+)'
name: 'Nokia Ovi Browser'
version: '$1'
- regex: '^Nokia|Nokia[EN]?\d+'
name: 'Nokia Browser'
version: ''
#NetFront
- regex: 'NetFrontLifeBrowser(?:/(\d+\.\d+))?'
name: 'NetFront Life'
version: '$1'
- regex: 'NetFront(?:/(\d+\.\d+))?'
name: 'NetFront'
version: '$1'
- regex: 'PLAYSTATION|NINTENDO 3|AppleWebKit.+ NX/\d+\.\d+\.\d+'
name: 'NetFront'
version: ''
#NetPositive
- regex: 'NetPositive(?:/(\d+\.\d+))?'
name: 'NetPositive'
version: '$1'
#Obigo
- regex: 'Obigo[ ]?(?:InternetBrowser|Browser)?(?:[ /]([a-z0-9]*))?'
name: 'Obigo'
version: '$1'
- regex: 'Obigo|Teleca'
name: 'Obigo'
version: ''
#Oregano
- regex: 'Oregano(?:[ /](\d+\.\d+))?'
name: 'Oregano'
version: '$1'
#Polaris
- regex: '(?:Polaris|Embider)(?:/(\d+\.\d+))?'
name: 'Polaris'
version: '$1'
#Snowshoe
- regex: 'Snowshoe(?:/(\d+\.\d+))?'
name: 'Snowshoe'
version: '$1'
#Thunderbird
- regex: 'Thunderbird(?:/(\d+\.\d+))?'
name: 'Thunderbird'
version: '$1'
#Xiino
- regex: 'Xiino(?:/(\d+\.\d+))?'
name: 'Xiino'
version: '$1'
#Android Browser
- regex: 'Android'
name: 'Android Browser'
version: ''
#Safari
- regex: '(?:iPod|iPad|iPhone).+Version/(\d+\.\d+)'
name: 'Mobile Safari'
version: '$1'
- regex: 'Version/(\d+\.\d+).*Mobile.*Safari/'
name: 'Mobile Safari'
version: '$1'
- regex: '(?:iPod|iPhone|iPad)'
name: 'Mobile Safari'
version: ''
- regex: 'Version/(\d+\.\d+).*Safari/|Safari/\d+'
name: 'Safari'
version: '$1'

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,494 @@
###############
# Piwik - Open source web analytics
#
# @link http://piwik.org
# @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
#
# @category UserAgentParserEnhanced
###############
##########
# Bot
##########
- regex: '(nuhk|Sosospider|CareerBot|bingbot|SputnikBot|TsolCrawler|SensikaBot|UptimeRobot|SeznamBot|AhrefsBot|Ezooms|Googlebot|Exabot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves/Teoma|ia_archiver|ScoutJet|Gulper Web Bot|EmailWolf|grub-client|Download Demon|SearchExpress|Microsoft URL Control|bot|borg|yahoo|slurp|msnbot|msrbot|openbot|archiver|netresearch|transcoder|crawler|lycos|scooter|altavista|teoma|gigabot|baiduspider|blitzbot|oegp|charlotte|furlbot|http%20client|polybot|htdig|ichiro|mogimogi|larbin|pompos|scrubby|searchsight|seekbot|semanticdiscovery|snappy|speedy|spider|voila|vortex|zao|zeal|fast-webcrawler|converacrawler|dataparksearch|findlinksYottaaMonitor|BrowserMob|HttpMonitor|YandexBot|Slurp|BingPreview|PagePeeker|ThumbShotsBot|WebThumb|URL2PNG|ZooShot|GomezA|Catchpoint bot|Willow Internet Crawler|Google SketchUp|Read%20Later|Minimo|Pingdom.com|facebookexternalhit|Twitterbot|RackspaceBot)'
name: 'Bot'
version: ''
##########
# Simulators
##########
- regex: '(Talkatone|WinWAP)'
name: '$1'
version: ''
##########
# Tizen
##########
- regex: 'Tizen'
name: 'Tizen'
version: ''
##########
## Sailfish OS
###########
- regex: 'Sailfish|Jolla'
name: 'Sailfish OS'
version: ''
##########
# Android
##########
- regex: '(?:Android|Adr)[ /](?:[a-z]+ )?(\d+\.\d+)'
name: 'Android'
version: '$1'
- regex: 'Android|Silk-Accelerated=[a-z]{4,5}'
name: 'Android'
version: ''
##########
# AmigaOS
##########
- regex: 'AmigaOS[ ]?(\d+\.\d+)'
name: 'AmigaOS'
version: '$1'
- regex: 'AmigaOS|AmigaVoyager|Amiga-AWeb'
name: 'AmigaOS'
version: ''
##########
# Linux
##########
- regex: 'Arch ?Linux(?:[ /\-](\d+\.\d+))?'
name: 'Arch Linux'
version: '$1'
- regex: 'Linux; .*((?:Debian|Knoppix|Mint|Ubuntu|Kubuntu|Xubuntu|Lubuntu|Fedora|Red Hat|Mandriva|Gentoo|Sabayon|Slackware|SUSE|Puppy|CentOS|BackTrack|YunOs|Presto))[ /](\d+\.\d+)'
name: '$1'
version: '$2'
- regex: '(Debian|Knoppix|Mint|Ubuntu|Kubuntu|Xubuntu|Lubuntu|Fedora|Red Hat|Mandriva|Gentoo|Sabayon|Slackware|SUSE|Puppy|CentOS|BackTrack|YunOs)(?: Linux)?(?:[ /\-](\d+\.\d+))?'
name: '$1'
version: '$2'
# generic linux match -> end of file
##########
# Windows Mobile
##########
- regex: 'Windows Phone (?:OS)?[ ]?(\d+\.\d+)'
name: 'Windows Phone'
version: '$1'
- regex: 'XBLWP7|Windows Phone'
name: 'Windows Phone'
version: ''
- regex: 'Windows CE'
name: 'Windows CE'
version: ''
- regex: '(?:IEMobile|Windows Mobile)(?: (\d+\.\d+))?'
name: 'Windows Mobile'
version: '$1'
- regex: 'Windows NT 6.2; ARM;'
name: 'Windows RT'
version: ''
##########
# webOS
##########
- regex: '(?:webOS|Palm webOS)(?:/(\d+\.\d+))?'
name: 'webOS'
version: '$1'
- regex: '(?:PalmOS|Palm OS)(?:[/ ](\d+\.\d+))?|Palm'
name: 'palmOS'
version: '$1'
- regex: 'Xiino(?:.*v\. (\d+\.\d+))?' # palmOS only browser
name: 'palmOS'
version: '$1'
##########
# Windows
##########
- regex: 'CYGWIN_NT-6.2|Windows NT 6.2|Windows NT 6.3|Windows 8'
name: 'Windows 8'
version: '8'
- regex: 'CYGWIN_NT-6.1|Windows NT 6.1|Windows 7'
name: 'Windows 7'
version: '7'
- regex: 'CYGWIN_NT-6.0|Windows NT 6.0|Windows Vista'
name: 'Windows Vista'
version: 'Vista'
- regex: 'CYGWIN_NT-5.2|Windows NT 5.2|Windows Server 2003 / XP x64'
name: 'Windows Server 2003'
version: 'Server 2003'
- regex: 'CYGWIN_NT-5.1|Windows NT 5.1|Windows XP'
name: 'Windows XP'
version: 'XP'
- regex: 'CYGWIN_NT-5.0|Windows NT 5.0|Windows 2000'
name: 'Windows 2000'
version: '2000'
- regex: 'CYGWIN_NT-4.0|Windows NT 4.0|WinNT|Windows NT'
name: 'Windows NT'
version: 'NT'
- regex: 'CYGWIN_ME-4.90|Win 9x 4.90|Windows ME'
name: 'Windows ME'
version: 'ME'
- regex: 'CYGWIN_98-4.10|Win98|Windows 98'
name: 'Windows 98'
version: '98'
- regex: 'CYGWIN_95-4.0|Win32|Win95|Windows 95|Windows_95'
name: 'Windows 95'
version: '95'
- regex: 'Windows 3.1'
name: 'Windows 3.1'
version: '3.1'
- regex: 'Windows'
name: 'Windows'
version: ''
##########
# Mac
##########
- regex: 'Mac OS X (\d+[_.]\d+)'
name: 'Mac'
version: '$1'
- regex: 'Darwin|Macintosh|Mac_PowerPC|PPC|Mac PowerPC'
name: 'Mac'
version: ''
##########
# iOS
##########
- regex: '(?:CPU OS|iPhone OS)[ _](\d+(?:_\d+)?)'
name: 'iOS'
version: '$1'
- regex: '(?:iPhone|iPad|iPod)(?:.*Mac OS X.*Version/(\d+\.\d+)|; Opera)'
name: 'iOS'
version: '$1'
##########
# ChromeOS
##########
- regex: 'CrOS [a-z0-9_]+ (\d+\.\d+)'
name: 'Chrome OS'
version: '$1'
##########
# BlackBerry
##########
- regex: '(?:BB10;.+Version|Black[Bb]erry[0-9a-z]+|Black[Bb]erry.+Version)/(\d+\.\d+)'
name: 'BlackBerry OS'
version: '$1'
- regex: 'RIM Tablet OS (\d+\.\d+)'
name: 'BlackBerry Tablet OS'
version: '$1'
- regex: 'RIM Tablet OS|QNX|Play[Bb]ook'
name: 'BlackBerry Tablet OS'
version: ''
- regex: 'BlackBerry'
name: 'BlackBerry OS'
version: ''
##########
# Haiku OS
##########
- regex: 'Haiku'
name: 'Haiku OS'
version: ''
##########
# BeOS
##########
- regex: 'BeOS'
name: 'BeOS'
version: ''
##########
# Symbian
##########
- regex: '(?:Series ?60|SymbOS|S60)(?:[ /]?(\d+\.\d+|V\d+))?'
name: 'Symbian OS Series 60'
version: '$1'
- regex: 'Series40'
name: 'Symbian OS Series 40'
version: ''
- regex: 'SymbianOS/(\d+\.\d+)'
name: 'Symbian OS'
version: '$1'
- regex: 'Symbian/3.+NokiaBrowser/7\.3'
name: 'Symbian'
version: '^3 Anna'
- regex: 'Symbian/3.+NokiaBrowser/7\.4'
name: 'Symbian'
version: '^3 Belle'
- regex: 'Symbian[/]?3'
name: 'Symbian^3'
version: '^3'
- regex: 'MeeGo|WeTab'
name: 'MeeGo'
version: ''
- regex: 'Symbian OS|SymbOS'
name: 'Symbian OS'
version: ''
- regex: 'Nokia'
name: 'Symbian'
version: ''
##########
# Firefox OS
##########
- regex: '(?:Mobile|Tablet);.+Firefox/\d+\.\d+'
name: 'Firefox OS'
version: ''
##########
# RISC OS
##########
- regex: 'RISC OS(?:-NC)?(?:[ /](\d+\.\d+))?'
name: 'RISC OS'
version: '$1'
##########
# Inferno
##########
- regex: 'Inferno(?:[ /](\d+\.\d+))?'
name: 'Inferno'
version: '$1'
##########
# Bada
##########
- regex: 'bada(?:[ /](\d+\.\d+))'
name: 'Bada'
version: '$1'
- regex: 'bada'
name: 'Bada'
version: ''
##########
# Brew
##########
- regex: '(?:Brew MP|BREW|BMP)(?:[ /](\d+\.\d+))'
name: 'Brew'
version: '$1'
- regex: 'Brew MP|BREW|BMP'
name: 'Brew'
version: ''
##########
# Web TV
##########
- regex: 'GoogleTV[ /](\d+\.\d+)|GoogleTV'
name: 'Google TV'
version: '$1'
- regex: 'AppleTV(?:/?(\d+\.\d+))?'
name: 'Apple TV'
version: '$1'
- regex: 'WebTV/(\d+\.\d+)'
name: 'WebTV'
version: '$1'
##########
# Unix
##########
- regex: '(?:SunOS|Solaris)(?:[/ ](\d+\.\d+))?'
name: 'Solaris'
version: '$1'
- regex: 'AIX(?:[/ ]?(\d+\.\d+))?'
name: 'AIX'
version: '$1'
- regex: 'HP-UX(?:[/ ]?(\d+\.\d+))?'
name: 'HP-UX'
version: '$1'
- regex: 'FreeBSD(?:[/ ]?(\d+\.\d+))?'
name: 'FreeBSD'
version: '$1'
- regex: 'NetBSD(?:[/ ]?(\d+\.\d+))?'
name: 'NetBSD'
version: '$1'
- regex: 'OpenBSD(?:[/ ]?(\d+\.\d+))?'
name: 'OpenBSD'
version: '$1'
- regex: 'DragonFly(?:[/ ]?(\d+\.\d+))?'
name: 'DragonFly'
version: '$1'
- regex: 'Syllable(?:[/ ]?(\d+\.\d+))?'
name: 'Syllable'
version: '$1'
- regex: 'IRIX(?:[/ ]?(\d+\.\d+))'
name: 'IRIX'
version: '$1'
- regex: 'OSF1(?:[/ ]?v?(\d+\.\d+))?'
name: 'OSF1'
version: '$1'
##########
# Gaming Console
##########
- regex: 'Nintendo Wii'
name: 'Nintendo'
version: 'Wii'
- regex: 'PlayStation ?([3|4])'
name: 'PlayStation'
version: '$1'
- regex: 'Xbox|KIN\.(?:One|Two)'
name: 'Xbox'
version: '360'
##########
# Mobile Gaming Console
##########
- regex: 'Nitro|Nintendo ([3]?DS[i]?)'
name: 'Nintendo Mobile'
version: '$1'
- regex: 'PlayStation ((?:Portable|Vita))'
name: 'PlayStation Portable'
version: '$1'
##########
# IBM
##########
- regex: 'OS/2'
name: 'OS/2'
version: ''
###########
# Linux (Generic)
###########
- regex: 'Linux[^a-z]'
name: 'Linux'
version: ''

View file

@ -0,0 +1,242 @@
###############
# Piwik - Open source web analytics
#
# @link http://piwik.org
# @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
#
# @category UserAgentParserEnhanced
#
# ATTENTION: This file may only include tv user agents that contain 'HbbTV/([1-9]{1}(\.[0-9]{1}){1,2})'
#
###############
# BangOlufsen
BangOlufsen:
regex: 'Bangolufsen'
device: 'tv'
model: 'BeoVision'
# CreNova
CreNova:
regex: 'CreNova'
device: 'tv'
model: 'CNV001'
# DMM
DMM:
regex: 'DMM'
device: 'tv'
models: 'Dreambox'
# Grundig
Grundig:
regex: '(OWB|Grundig|Arcelik)'
device: 'tv'
model: ''
# Humax
Humax:
regex: 'Humax'
device: 'tv'
models:
- regex: '(HD-FOX C|HD (FOX\+|NANO)|iCord (HD\+|MINI|Cable)|(CX|IR)HD-5100(C|S)|HM9503HD)'
model: '$1'
- regex: 'HMS1000S'
model: 'HMS-1000S'
# IKEA
Ikea:
regex: 'Ikea'
device: 'tv'
models:
- regex: '(LF1V[0-9]{3})'
model: '$1'
# Intek
Intek:
regex: 'Intek'
device: 'tv'
models:
- regex: '(Vantage|VT-100|VT-1)'
model: '$1'
# Inverto
Inverto:
regex: 'Inverto'
device: 'tv'
models:
- regex: '(Volksbox Web Edition|Volksbox Essential|Volksbox II|Volksbox)'
model: '$1'
# LG
LG:
regex: 'LGE'
device: 'tv'
models:
- regex: '(NetCast [0-9]{1}.[0-9]{1}|GLOBAL_PLAT3)'
model: '$1'
# Loewe
Loewe:
regex: 'Loewe'
device: 'tv'
models:
- regex: '([A-Z]{2}[0-9]{3})'
model: '$1'
# MediaTek
MediaTek:
regex: 'MTK'
device: 'tv'
models:
- regex: '(MT[0-9]{4})'
model: '$1'
# Medion
Medion:
regex: 'Medion'
device: 'tv'
models:
- regex: '(MB[0-9]{2})'
model: '$1'
# Metz
Metz:
regex: 'Metz'
device: 'tv'
model: ''
# Panasonic
Panasonic:
regex: 'Panasonic'
device: 'tv'
models:
- regex: '(VIERA [0-9]{1,4})|(DIGA [A-Z]{1}[0-9]{4})'
model: '$1'
- regex: 'DIGA Webkit ([A-Z]{1}[0-9]{4})'
model: 'DIGA $1'
# PEAQ
PEAQ:
regex: 'PEAQ'
device: 'tv'
models:
- regex: '(LF1V[0-9]{3})'
model: '$1'
# Philips
Philips:
regex: 'Philips'
device: 'tv'
models:
- regex: '(NETTV/[0-9\.]{5})'
model: '$1'
# Samsung
Samsung:
regex: 'Samsung|Maple_2011'
device: 'tv'
models:
- regex: '(SmartTV2013|SmartTV2012)'
model: '$1'
- regex: 'Maple_2011'
model: 'SmartTV2011'
# Selevision
Selevision:
regex: 'Selevision'
device: 'tv'
models:
- regex: '(EMC1000i)'
model: '$1'
# Sharp
Sharp:
regex: 'Sharp'
device: 'tv'
models:
- regex: '(LE[0-9]{3}[A-Z]{0,3})'
model: '$1'
# Smart
Smart:
regex: 'Smart'
device: 'tv'
models:
- regex: '([A-Z]{2}[0-9]{2}|ZAPPIX)'
model: '$1'
# Sony
Sony:
regex: 'Sony'
device: 'tv'
models:
- regex: '(KDL[0-9]{2}[A-Z]{1,2}[0-9]{3})'
model: '$1'
# TechniSat
TechniSat:
regex: 'TechniSat'
device: 'tv'
models:
- regex: '((DigiCorder|MultyVision|Digit) (ISIO S|ISIO C|ISIO))'
model: '$1'
# TechnoTrend
TechnoTrend:
regex: 'TechnoTrend'
device: 'tv'
models:
- regex: '([A-Z]{1}-[0-9]{3})'
model: '$1'
# Telefunken
Telefunken:
regex: 'Telefunken'
device: 'tv'
models:
- regex: '(MB[0-9]{2})'
model: '$1'
# TCL
TCL:
regex: 'TCL'
device: 'tv'
models:
- regex: '(LF1V[0-9]{3})'
model: '$1'
# Thomson
Thomson:
regex: 'THOMSON|THOM'
device: 'tv'
models:
- regex: '(LF1V[0-9]{3})'
model: '$1'
# Toshiba
Toshiba:
regex: 'Toshiba'
device: 'tv'
models:
- regex: '(([0-9]{2}|DTV_)[A-Z]{2}[0-9]{1,3})'
model: '$1'
# Vestel
Vestel:
regex: 'Vestel'
device: 'tv'
models:
- regex: '(MB[0-9]{2})'
model: '$1'
# Videoweb
Videoweb:
regex: 'videoweb|compatible;'
device: 'tv'
models:
- regex: '(videowebtv)'
model: 'VideoWeb TV'
- regex: '(tv2n)'
model: '$1'
- regex: 'ANTGalio/3.0'
model: '600S'