<?php
/**
 * Class Browscap
 *
 * Library File for get the browser and operating system name from the http user agent variable.
 *
 * @todo need to sync with newly found browser and os
 * @author Lij@zzz
 * @package Oorjit Products
 * @copyright Copyright (c) 2005 ISPG Technologies (I) Pvt Ltd. All rights reserved.
 * @version Browscap.class.PHP, v 1.0 2012/05/14 20:52:11 
 */
class Browscap {
	
	public $updateInterval =   3600; // 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;
	
public function __construct($api='') 
{
if($api=='')
{	
$properties=array('browser_name','browser_name_regex','browser_name_pattern','Parent','Browser','Version','MajorVer','MinorVer','Platform','Alpha','Beta','Win16','Win32','Win64','Frames','IFrames','Tables','Cookies','BackgroundSounds','JavaScript','VBScript','JavaApplets','ActiveXControls','isBanned','isMobileDevice','isSyndicationReader','Crawler','CssVersion','AolVersion');

	$xmlfile = file_get_contents(__CORE_PUBLIC_UPLOADS_PATH.'/browscap/_browsers.xml');
	$ob= simplexml_load_string($xmlfile);
	$json  = json_encode($ob);
	$configData = json_decode($json, true);
	foreach($configData  as $key=>$value)
	{
		foreach($value  as $key1=>$value1)
		{
			if(!is_array($value1))
			{
				$finalArray[substr($key, 3)][substr($key1, 3)]=$value1;	
			}
			else
			{
				$finalArray[substr($key, 3)][substr($key1, 3)]='';
			}
		}
			
	}
	$this->_browsers = $finalArray;
	unset($finalArray);
	unset($xmlfile);
	unset($ob);
	unset($json);
	unset($configData);
	unset($key);
	unset($value);
	unset($key1);
	unset($value1);
	
	$xmlfile 	= file_get_contents(__CORE_PUBLIC_UPLOADS_PATH.'/browscap/_userAgent.xml');
	$ob			= simplexml_load_string($xmlfile);
	$json  		= json_encode($ob);
	$configData = json_decode($json, true);
	foreach($configData  as $key=>$value)
	{
		if(!is_array($value1))
		{
			$finalArray[substr($key, 3)]=$value;	
		}
		else
		{
			$finalArray[substr($key, 3)]='';
		}
			
	}
	$this->_userAgents=$finalArray;
	unset($finalArray);
	unset($xmlfile);
	unset($ob);
	unset($json);
	unset($configData);
	unset($key);
	unset($value);
	unset($key1);
	unset($value1);
	
	$xmlfile = file_get_contents(__CORE_PUBLIC_UPLOADS_PATH.'/browscap/_pattern.xml');
	$ob= simplexml_load_string($xmlfile);
	$json  = json_encode($ob);
	$configData = json_decode($json, true);
	foreach($configData  as $key=>$value)
	{
		if(!is_array($value1))
		{
			$finalArray[substr($key, 3)]=$value;
		}
		else
		{
			$finalArray[substr($key, 3)]='';
		}
			
	}
	$this->_patterns=$finalArray;
	unset($finalArray);
	unset($xmlfile);
	unset($ob);
	unset($json);
	unset($configData);
	unset($key);
	unset($value);
	unset($key1);
	unset($value1);
}
else
{
	if ($updateInterval) $this->updateInterval = $updateInterval;
}
}
    /**
     *  Parse the useragent string if given otherwise parse the current user agent
     *  @param  string  user agent string
     */
    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
     */
    private function _loadData() {
        if (!file_exists($this->_cache_dir)) return;
    
        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.');
        }
    }

    /**
     *  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;
        if (file_exists($this->_cache_dir.'/cache.ini')) {
            $cacheIni = parse_ini_file($this->_cache_dir.'/cache.ini');
        } 
        else {
            
        }
        
        // 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  string  $timeout
     */
    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;
    }
}