UserAgentParser.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <?php
  2. /**
  3. * Parses a user agent string into its important parts
  4. *
  5. * @author Jesse G. Donat <donatj@gmail.com>
  6. * @link https://github.com/donatj/PhpUserAgent
  7. * @link http://donatstudios.com/PHP-Parser-HTTP_USER_AGENT
  8. * @param string|null $u_agent User agent string to parse or null. Uses $_SERVER['HTTP_USER_AGENT'] on NULL
  9. * @throws InvalidArgumentException on not having a proper user agent to parse.
  10. * @return string[] an array with browser, version and platform keys
  11. */
  12. function parse_user_agent( $u_agent = null ) {
  13. if( is_null($u_agent) ) {
  14. if( isset($_SERVER['HTTP_USER_AGENT']) ) {
  15. $u_agent = $_SERVER['HTTP_USER_AGENT'];
  16. } else {
  17. throw new \InvalidArgumentException('parse_user_agent requires a user agent');
  18. }
  19. }
  20. $platform = null;
  21. $browser = null;
  22. $version = null;
  23. $empty = array( 'platform' => $platform, 'browser' => $browser, 'version' => $version );
  24. if( !$u_agent ) return $empty;
  25. if( preg_match('/\((.*?)\)/im', $u_agent, $parent_matches) ) {
  26. preg_match_all('/(?P<platform>BB\d+;|Android|CrOS|Tizen|iPhone|iPad|iPod|Linux|Macintosh|Windows(\ Phone)?|Silk|linux-gnu|BlackBerry|PlayBook|(New\ )?Nintendo\ (WiiU?|3?DS)|Xbox(\ One)?)
  27. (?:\ [^;]*)?
  28. (?:;|$)/imx', $parent_matches[1], $result, PREG_PATTERN_ORDER);
  29. $priority = array( 'Xbox One', 'Xbox', 'Windows Phone', 'Tizen', 'Android' );
  30. $result['platform'] = array_unique($result['platform']);
  31. if( count($result['platform']) > 1 ) {
  32. if( $keys = array_intersect($priority, $result['platform']) ) {
  33. $platform = reset($keys);
  34. } else {
  35. $platform = $result['platform'][0];
  36. }
  37. } elseif( isset($result['platform'][0]) ) {
  38. $platform = $result['platform'][0];
  39. }
  40. }
  41. if( $platform == 'linux-gnu' ) {
  42. $platform = 'Linux';
  43. } elseif( $platform == 'CrOS' ) {
  44. $platform = 'Chrome OS';
  45. }
  46. preg_match_all('%(?P<browser>Camino|Kindle(\ Fire)?|Firefox|Iceweasel|Safari|MSIE|Trident|AppleWebKit|TizenBrowser|Chrome|
  47. Vivaldi|IEMobile|Opera|OPR|Silk|Midori|Edge|CriOS|
  48. Baiduspider|Googlebot|YandexBot|bingbot|Lynx|Version|Wget|curl|
  49. NintendoBrowser|PLAYSTATION\ (\d|Vita)+)
  50. (?:\)?;?)
  51. (?:(?:[:/ ])(?P<version>[0-9A-Z.]+)|/(?:[A-Z]*))%ix',
  52. $u_agent, $result, PREG_PATTERN_ORDER);
  53. // If nothing matched, return null (to avoid undefined index errors)
  54. if( !isset($result['browser'][0]) || !isset($result['version'][0]) ) {
  55. if( preg_match('%^(?!Mozilla)(?P<browser>[A-Z0-9\-]+)(/(?P<version>[0-9A-Z.]+))?%ix', $u_agent, $result) ) {
  56. return array( 'platform' => $platform ?: null, 'browser' => $result['browser'], 'version' => isset($result['version']) ? $result['version'] ?: null : null );
  57. }
  58. return $empty;
  59. }
  60. if( preg_match('/rv:(?P<version>[0-9A-Z.]+)/si', $u_agent, $rv_result) ) {
  61. $rv_result = $rv_result['version'];
  62. }
  63. $browser = $result['browser'][0];
  64. $version = $result['version'][0];
  65. $lowerBrowser = array_map('strtolower', $result['browser']);
  66. $find = function ( $search, &$key ) use ( $lowerBrowser ) {
  67. $xkey = array_search(strtolower($search), $lowerBrowser);
  68. if( $xkey !== false ) {
  69. $key = $xkey;
  70. return true;
  71. }
  72. return false;
  73. };
  74. $key = 0;
  75. $ekey = 0;
  76. if( $browser == 'Iceweasel' ) {
  77. $browser = 'Firefox';
  78. } elseif( $find('Playstation Vita', $key) ) {
  79. $platform = 'PlayStation Vita';
  80. $browser = 'Browser';
  81. } elseif( $find('Kindle Fire', $key) || $find('Silk', $key) ) {
  82. $browser = $result['browser'][$key] == 'Silk' ? 'Silk' : 'Kindle';
  83. $platform = 'Kindle Fire';
  84. if( !($version = $result['version'][$key]) || !is_numeric($version[0]) ) {
  85. $version = $result['version'][array_search('Version', $result['browser'])];
  86. }
  87. } elseif( $find('NintendoBrowser', $key) || $platform == 'Nintendo 3DS' ) {
  88. $browser = 'NintendoBrowser';
  89. $version = $result['version'][$key];
  90. } elseif( $find('Kindle', $key) ) {
  91. $browser = $result['browser'][$key];
  92. $platform = 'Kindle';
  93. $version = $result['version'][$key];
  94. } elseif( $find('OPR', $key) ) {
  95. $browser = 'Opera Next';
  96. $version = $result['version'][$key];
  97. } elseif( $find('Opera', $key) ) {
  98. $browser = 'Opera';
  99. $find('Version', $key);
  100. $version = $result['version'][$key];
  101. } elseif( $find('Midori', $key) ) {
  102. $browser = 'Midori';
  103. $version = $result['version'][$key];
  104. } elseif( $browser == 'MSIE' || ($rv_result && $find('Trident', $key)) || $find('Edge', $ekey) ) {
  105. $browser = 'MSIE';
  106. if( $find('IEMobile', $key) ) {
  107. $browser = 'IEMobile';
  108. $version = $result['version'][$key];
  109. } elseif( $ekey ) {
  110. $version = $result['version'][$ekey];
  111. } else {
  112. $version = $rv_result ?: $result['version'][$key];
  113. }
  114. if( version_compare($version, '12', '>=') ) {
  115. $browser = 'Edge';
  116. }
  117. } elseif( $find('Vivaldi', $key) ) {
  118. $browser = 'Vivaldi';
  119. $version = $result['version'][$key];
  120. } elseif( $find('Chrome', $key) || $find('CriOS', $key) ) {
  121. $browser = 'Chrome';
  122. $version = $result['version'][$key];
  123. } elseif( $browser == 'AppleWebKit' ) {
  124. if( ($platform == 'Android' && !($key = 0)) ) {
  125. $browser = 'Android Browser';
  126. } elseif( strpos($platform, 'BB') === 0 ) {
  127. $browser = 'BlackBerry Browser';
  128. $platform = 'BlackBerry';
  129. } elseif( $platform == 'BlackBerry' || $platform == 'PlayBook' ) {
  130. $browser = 'BlackBerry Browser';
  131. } elseif( $find('Safari', $key) ) {
  132. $browser = 'Safari';
  133. } elseif( $find('TizenBrowser', $key) ) {
  134. $browser = 'TizenBrowser';
  135. }
  136. $find('Version', $key);
  137. $version = $result['version'][$key];
  138. } elseif( $key = preg_grep('/playstation \d/i', array_map('strtolower', $result['browser'])) ) {
  139. $key = reset($key);
  140. $platform = 'PlayStation ' . preg_replace('/[^\d]/i', '', $key);
  141. $browser = 'NetFront';
  142. }
  143. return array( 'platform' => $platform ?: null, 'browser' => $browser ?: null, 'version' => $version ?: null );
  144. }