-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
1,050 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,10 @@ | ||
UASparser | ||
========= | ||
|
||
User Agent String parser for PHP from user-agent-string.info | ||
A User Agent String parser for PHP | ||
|
||
This is a parser for the user agent strings presented by HTTP clients of various flavours. This code is based on the libraries available from http://user-agent-string.info | ||
|
||
Licensed under the LGPL, see license.txt for details. | ||
|
||
This version amended by by Marcus Bointon removes the view source option for security, cleans up phpdocs and code formatting (to PSR-2 style), fixes poor code in the example script. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,365 @@ | ||
<?php | ||
/** | ||
* PHP version 5 | ||
* | ||
* @package UASparser | ||
* @author Jaroslav Mallat (http://mallat.cz/) | ||
* @copyright Copyright (c) 2008 Jaroslav Mallat | ||
* @copyright Copyright (c) 2010 Alex Stanev (http://stanev.org) | ||
* @copyright Copyright (c) 2012 Martin van Wingerden (http://www.copernica.com) | ||
* @version 0.51 | ||
* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License | ||
* @link http://user-agent-string.info/download/UASparser | ||
*/ | ||
|
||
class UASparser | ||
{ | ||
/** | ||
* @var integer How often to update UAS database | ||
*/ | ||
public $updateInterval = 86400; // 1 day | ||
|
||
private static $_ini_url = 'http://user-agent-string.info/rpc/get_data.php?key=free&format=ini'; | ||
private static $_ver_url = 'http://user-agent-string.info/rpc/get_data.php?key=free&format=ini&ver=y'; | ||
private static $_md5_url = 'http://user-agent-string.info/rpc/get_data.php?format=ini&md5=y'; | ||
private static $_info_url = 'http://user-agent-string.info'; | ||
private $_cache_dir = null; | ||
private $_data = null; | ||
|
||
/** | ||
* Constructor with an optional cache directory | ||
* @param string $cacheDirectory | ||
* @param integer $updateInterval | ||
* @internal param \cache $string directory to be used by this instance | ||
*/ | ||
public function __construct($cacheDirectory = null, $updateInterval = null) | ||
{ | ||
if ($cacheDirectory) { | ||
$this->SetCacheDir($cacheDirectory); | ||
} | ||
if ($updateInterval) { | ||
$this->updateInterval = $updateInterval; | ||
} | ||
} | ||
|
||
/** | ||
* Parse the useragent string if given otherwise parse the current user agent | ||
* @param string $useragent user agent string | ||
* @return array | ||
*/ | ||
public function Parse($useragent = null) | ||
{ | ||
// intialize some variables | ||
$browser_id = $os_id = null; | ||
$result = array(); | ||
|
||
// initialize the return value | ||
$result['typ'] = 'unknown'; | ||
$result['ua_family'] = 'unknown'; | ||
$result['ua_name'] = 'unknown'; | ||
$result['ua_version'] = 'unknown'; | ||
$result['ua_url'] = 'unknown'; | ||
$result['ua_company'] = 'unknown'; | ||
$result['ua_company_url'] = 'unknown'; | ||
$result['ua_icon'] = 'unknown.png'; | ||
$result["ua_info_url"] = 'unknown'; | ||
$result["os_family"] = 'unknown'; | ||
$result["os_name"] = 'unknown'; | ||
$result["os_url"] = 'unknown'; | ||
$result["os_company"] = 'unknown'; | ||
$result["os_company_url"] = 'unknown'; | ||
$result["os_icon"] = 'unknown.png'; | ||
|
||
// if no user agent is supplied process the one from the server vars | ||
if (!isset($useragent) && isset($_SERVER['HTTP_USER_AGENT'])) { | ||
$useragent = $_SERVER['HTTP_USER_AGENT']; | ||
} | ||
|
||
// if we haven't loaded the data yet, do it now | ||
if (!$this->_data) { | ||
$this->_data = $this->_loadData(); | ||
} | ||
|
||
// we have no data or no valid user agent, just return the default data | ||
if (!$this->_data || !isset($useragent)) { | ||
return $result; | ||
} | ||
|
||
// crawler | ||
foreach ($this->_data['robots'] as $test) { | ||
if ($test[0] == $useragent) { | ||
$result['typ'] = 'Robot'; | ||
if ($test[1]) { | ||
$result['ua_family'] = $test[1]; | ||
} | ||
if ($test[2]) { | ||
$result['ua_name'] = $test[2]; | ||
} | ||
if ($test[3]) { | ||
$result['ua_url'] = $test[3]; | ||
} | ||
if ($test[4]) { | ||
$result['ua_company'] = $test[4]; | ||
} | ||
if ($test[5]) { | ||
$result['ua_company_url'] = $test[5]; | ||
} | ||
if ($test[6]) { | ||
$result['ua_icon'] = $test[6]; | ||
} | ||
if ($test[7]) { // OS set | ||
$os_data = $this->_data['os'][$test[7]]; | ||
if ($os_data[0]) { | ||
$result['os_family'] = $os_data[0]; | ||
} | ||
if ($os_data[1]) { | ||
$result['os_name'] = $os_data[1]; | ||
} | ||
if ($os_data[2]) { | ||
$result['os_url'] = $os_data[2]; | ||
} | ||
if ($os_data[3]) { | ||
$result['os_company'] = $os_data[3]; | ||
} | ||
if ($os_data[4]) { | ||
$result['os_company_url'] = $os_data[4]; | ||
} | ||
if ($os_data[5]) { | ||
$result['os_icon'] = $os_data[5]; | ||
} | ||
} | ||
if ($test[8]) { | ||
$result['ua_info_url'] = self::$_info_url . $test[8]; | ||
} | ||
return $result; | ||
} | ||
} | ||
|
||
// find a browser based on the regex | ||
foreach ($this->_data['browser_reg'] as $test) { | ||
if (@preg_match($test[0], $useragent, $info)) { // $info may contain version | ||
$browser_id = $test[1]; | ||
break; | ||
} | ||
} | ||
|
||
// a valid browser was found | ||
if ($browser_id) { // browser detail | ||
$browser_data = $this->_data['browser'][$browser_id]; | ||
if ($this->_data['browser_type'][$browser_data[0]][0]) { | ||
$result['typ'] = $this->_data['browser_type'][$browser_data[0]][0]; | ||
} | ||
if (isset($info[1])) { | ||
$result['ua_version'] = $info[1]; | ||
} | ||
if ($browser_data[1]) { | ||
$result['ua_family'] = $browser_data[1]; | ||
} | ||
if ($browser_data[1]) { | ||
$result['ua_name'] = $browser_data[1] . (isset($info[1]) ? ' ' . $info[1] : ''); | ||
} | ||
if ($browser_data[2]) { | ||
$result['ua_url'] = $browser_data[2]; | ||
} | ||
if ($browser_data[3]) { | ||
$result['ua_company'] = $browser_data[3]; | ||
} | ||
if ($browser_data[4]) { | ||
$result['ua_company_url'] = $browser_data[4]; | ||
} | ||
if ($browser_data[5]) { | ||
$result['ua_icon'] = $browser_data[5]; | ||
} | ||
if ($browser_data[6]) { | ||
$result['ua_info_url'] = self::$_info_url . $browser_data[6]; | ||
} | ||
} | ||
|
||
// browser OS, does this browser match contain a reference to an os? | ||
if (isset($this->_data['browser_os'][$browser_id])) { // os detail | ||
$os_id = $this->_data['browser_os'][$browser_id][0]; // Get the os id | ||
$os_data = $this->_data['os'][$os_id]; | ||
if ($os_data[0]) { | ||
$result['os_family'] = $os_data[0]; | ||
} | ||
if ($os_data[1]) { | ||
$result['os_name'] = $os_data[1]; | ||
} | ||
if ($os_data[2]) { | ||
$result['os_url'] = $os_data[2]; | ||
} | ||
if ($os_data[3]) { | ||
$result['os_company'] = $os_data[3]; | ||
} | ||
if ($os_data[4]) { | ||
$result['os_company_url'] = $os_data[4]; | ||
} | ||
if ($os_data[5]) { | ||
$result['os_icon'] = $os_data[5]; | ||
} | ||
return $result; | ||
} | ||
|
||
// search for the os | ||
foreach ($this->_data['os_reg'] as $test) { | ||
if (@preg_match($test[0], $useragent)) { | ||
$os_id = $test[1]; | ||
break; | ||
} | ||
} | ||
|
||
// a valid os was found | ||
if ($os_id) { // os detail | ||
$os_data = $this->_data['os'][$os_id]; | ||
if ($os_data[0]) { | ||
$result['os_family'] = $os_data[0]; | ||
} | ||
if ($os_data[1]) { | ||
$result['os_name'] = $os_data[1]; | ||
} | ||
if ($os_data[2]) { | ||
$result['os_url'] = $os_data[2]; | ||
} | ||
if ($os_data[3]) { | ||
$result['os_company'] = $os_data[3]; | ||
} | ||
if ($os_data[4]) { | ||
$result['os_company_url'] = $os_data[4]; | ||
} | ||
if ($os_data[5]) { | ||
$result['os_icon'] = $os_data[5]; | ||
} | ||
} | ||
return $result; | ||
} | ||
|
||
/** | ||
* Load the data from the files | ||
* @return boolean | ||
*/ | ||
private function _loadData() | ||
{ | ||
if (!file_exists($this->_cache_dir)) { | ||
return false; | ||
} | ||
|
||
if (file_exists($this->_cache_dir . '/cache.ini')) { | ||
$cacheIni = parse_ini_file($this->_cache_dir . '/cache.ini'); | ||
|
||
// should we reload the data because it is already old? | ||
if ($cacheIni['lastupdate'] < time() - $this->updateInterval || $cacheIni['lastupdatestatus'] != '0') { | ||
$this->_downloadData(); | ||
} | ||
} else { | ||
$this->_downloadData(); | ||
} | ||
|
||
// we have file with data, parse and return it | ||
if (file_exists($this->_cache_dir . '/uasdata.ini')) { | ||
return @parse_ini_file($this->_cache_dir . '/uasdata.ini', true); | ||
} else { | ||
trigger_error('ERROR: No datafile (uasdata.ini in Cache Dir), maybe update the file manually.'); | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Download the data | ||
*/ | ||
private function _downloadData() | ||
{ | ||
// support for at least on of the two is needed | ||
if (!ini_get('allow_url_fopen') && !function_exists('curl_init')) { | ||
trigger_error( | ||
'ERROR: function file_get_contents not allowed URL open. Update the datafile (uasdata.ini in Cache Dir) manually.' | ||
); | ||
return; | ||
} | ||
|
||
// by default status is failed | ||
$status = 1; | ||
$cacheIni = array(); | ||
if (file_exists($this->_cache_dir . '/cache.ini')) { | ||
$cacheIni = parse_ini_file($this->_cache_dir . '/cache.ini'); | ||
} | ||
|
||
// Get the version for the server | ||
$ver = $this->get_contents(self::$_ver_url); | ||
if (strlen($ver) != 11) { | ||
if ($cacheIni['localversion']) { | ||
$ver = $cacheIni['localversion']; | ||
} else { | ||
$ver = 'none'; | ||
} | ||
} | ||
|
||
// Download the ini file | ||
if ($ini = $this->get_contents(self::$_ini_url)) { | ||
// download the has file | ||
$md5hash = $this->get_contents(self::$_md5_url); | ||
// validate the hash, if okay store the new ini file | ||
if (md5($ini) == $md5hash) { | ||
@file_put_contents($this->_cache_dir . '/uasdata.ini', $ini); | ||
$status = 0; | ||
} | ||
} | ||
|
||
// build a new cache file and store it | ||
$cacheIni = "; cache info for class UASparser - http://user-agent-string.info/download/UASparser\n"; | ||
$cacheIni .= "[main]\n"; | ||
$cacheIni .= "localversion = \"$ver\"\n"; | ||
$cacheIni .= 'lastupdate = "' . time() . "\"\n"; | ||
$cacheIni .= "lastupdatestatus = \"$status\"\n"; | ||
@file_put_contents($this->_cache_dir . '/cache.ini', $cacheIni); | ||
} | ||
|
||
/** | ||
* Get the content of a certain url with a defined timeout | ||
* @param string $url | ||
* @param int|string $timeout | ||
* @return string | ||
*/ | ||
private function get_contents($url, $timeout = 5) | ||
{ | ||
// use file_get_contents | ||
if (ini_get('allow_url_fopen')) { | ||
$ctx = stream_context_create(array('http' => array('timeout' => $timeout))); | ||
return file_get_contents($url, false, $ctx); | ||
} // fall back to curl | ||
elseif (function_exists('curl_init')) { | ||
$ch = curl_init($url); | ||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); | ||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); | ||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | ||
$data = curl_exec($ch); | ||
curl_close($ch); | ||
return $data; | ||
} | ||
|
||
// no options left | ||
return ''; | ||
} | ||
|
||
/** | ||
* Set the cache directory | ||
* @param string | ||
*/ | ||
public function SetCacheDir($cache_dir) | ||
{ | ||
|
||
// The directory does not exist at this moment, try to make it | ||
if (!file_exists($cache_dir)) { | ||
@mkdir($cache_dir, 0777, true); | ||
} | ||
|
||
// perform some extra checks | ||
if (!is_writable($cache_dir) || !is_dir($cache_dir)) { | ||
trigger_error('ERROR: Cache dir(' . $cache_dir . ') is not a directory or not writable'); | ||
return; | ||
} | ||
|
||
// store the cache dir | ||
$cache_dir = realpath($cache_dir); | ||
$this->_cache_dir = $cache_dir; | ||
} | ||
} |
Oops, something went wrong.