* $myDevice = new tera_wurfl(); * $myDevice->getDeviceCapabilitiesFromAgent($_SERVER['HTTP_USER_AGENT'); * // see if this device is really a mobile browser * if($myDevice->browser_is_wap){ * // check capabilities * if($myDevice->capabilities['downloadfun']['downloadfun_support']){ * echo "downloadfun supported
"; * }else{ * echo "WAP is supported, downloadfun is not
"; * } * if($myDevice->device_image != ''){ * // display device image * echo '
'; * } * } * * * @package tera_wurfl */ class tera_wurfl { /** * Internal tracking of the WURFL ID * @var string * @access private */ var $id=""; /** * If true, Openwave's GUI (mostly wml 1.3) is supported * @var bool * @access public */ var $GUI=false; /** * Device brand (manufacturer) * @var string * @access public */ var $brand=''; /** * Device model name * @var string * @access public */ var $model=''; /** * If this is a WAP device, this is set to true * @var boolean * @access public */ var $browser_is_wap=false; /** * associative array with all the device's capabilities. * * Example: $this->capabilities['downloadfun']['downloadfun_support'] * true if downloadfun is supported, otherwise false * * @var associative array * @access public */ var $capabilities=array(); /** * HTTP_ACCEPT request headers * Use this to manually set the http-accept string: * * Example: $this->http_accept = "text/vnd.wap.wml"; * @var string * @access public */ var $http_accept=""; /** * Ignore desktop browser * Set this to false if you want to search the WURFL/patch * for desktop web browsers as well. * * @var string * @access public */ var $ignoreBrowser=false; /** * Track errors * Anytime a LOG_ERR level event occurs, a description is * added to the end of the array. * Example: echo count($this->$errors); // echos number of errors * @var array * @access public */ var $errors = array(); /** * Internal database link resource * @var resource * @access private */ var $dbcon = ''; /** * Internal device table tracking. Used to provide some members with the name * of the current device table. It will be either DB_DEVICE_TABLE or DB_HYBRID_TABLE * @var string * @access private */ var $devtable = ''; /** * WURFL ID of the ancestoral device root * This is the ID of the actual device, not a firmware revision * * @var string * @access public */ var $device_root = ''; /** * Device image path and filename, relative to the class file * * @var string * @access public */ var $device_image = ''; /** * Total number of queries performed * * @var number * @access public */ var $num_queries = 0; /** * True if the UA was found in the cache * * @var boolean * @access public */ var $found_in_cache = false; /** * Constructor, sets the http_accept property and connects to the WURFL database. * You don't need to call the constructor - it is called when you instantiate the class * * @access public * @return boolean success * */ function tera_wurfl() { // connect to database $this->dbcon = mysql_connect(DB_HOST,DB_USER,DB_PASS) or die("ERROR: Could not connect to MySQL Server (".DB_HOST."): ".mysql_error()); // Use the line below instead to keep the connection to the DB open between requests. // This will increase speed and decrease memory usage on high traffic sites. //$this->dbcon = mysql_pconnect(DB_HOST,DB_USER,DB_PASS) or die("ERROR: Could not connect to MySQL Server (".DB_HOST."): ".mysql_error()); // select schema mysql_select_db(DB_SCHEMA,$this->dbcon) or die("ERROR: Connected to MySQL Server but could not select database (".DB_SCHEMA."): ".mysql_error()); if(WURFL_PATCH_ENABLE){ $this->devtable = DB_HYBRID_TABLE; }else{ $this->devtable = DB_DEVICE_TABLE; } //TODO: remove this test - it's too slow // make sure the device table exists //$test = @mysql_query("SELECT COUNT(deviceID) AS num FROM ".$this->devtable) or die("ERROR: Device table not found (".$this->devtable."): ".mysql_error()."

If this is a new installation, please update the database."); //$this->num_queries++; // make sure the device table is not empty //if(mysql_result($test,0,"num") == 0)die("ERROR: The device table (".$this->devtable.") is empty. Please update the WURFL database."); // set the default http-accept $this->http_accept = isset($_SERVER['HTTP_ACCEPT'])? $_SERVER['HTTP_ACCEPT']:''; $this->_toLog('constructor', '-----Class Initiated-----', LOG_INFO); return(true); } /** * Given the device's id reads all its capabilities and each * parent (fall_back) devices' capabilities and merges them * * @param string the device's id from the WURFL database * @access private * @return boolean success */ function _GetFullCapabilities($_id) { if(count($this->errors) != 0) return(false); $this->_toLog('_GetFullCapabilities', "searching for $_id", LOG_INFO); $_curr_device = $this->_getDeviceCapabilitiesFromId($_id); // array of full records $_capabilities[] = $_curr_device; // keep the while loop from running away on an error $iteration_limit = 20; $i = 0; while ( $_curr_device['fall_back'] != 'generic' && $_curr_device['fall_back'] != 'root' && $i <= $iteration_limit) { $this->_toLog('_GetFullCapabilities', 'parent device:'.$_curr_device['fall_back'].' now going to read its capabilities', LOG_INFO); $_curr_device = $this->_getDeviceCapabilitiesFromId($_curr_device['fall_back']); array_unshift($_capabilities,$_curr_device); $i++; } if($i >= $iteration_limit){ // the while loop ran away $this->_toLog('_GetFullCapabilities', 'Killing runaway while loop - $_id='.$_id, LOG_ERR); return(false); } $this->_toLog('_GetFullCapabilities', 'getting baseline capabilities from generic device', LOG_INFO); $generic = $this->_getDeviceCapabilitiesFromId('generic'); $_final = $generic; // the generic devices are already at the top of the array because I used array_unshift() foreach($_capabilities as $curr_device){ //TODO: Why don't I just array_merge the whole record???? Good question! foreach($curr_device as $key => $val) { if ( is_array($val) ) { $_final[$key] = array_merge($_final[$key], $val); } else { $_final[$key] = $val; } } } $this->capabilities = $_final; //$this->brand = $this->capabilities['product_info']['brand_name']; //$this->model = $this->capabilities['product_info']['model_name']; //$this->id = $this->capabilities['id']; return(true); } /** * Given a device id reads its capabilities * * @param string device's wurfl_id * @access private * @return mixed boolean false if not identified or array capabilities * */ function _getDeviceCapabilitiesFromId($_id) { if(count($this->errors) != 0) return(false); $this->_toLog('_getDeviceCapabilitiesFromId', "reading id:$_id", LOG_INFO); if ( $_id == 'upgui_generic' ) { $this->GUI = true; } $res = mysql_query("SELECT * FROM ".$this->devtable." WHERE deviceID=".$this->_sqlPrep($_id),$this->dbcon) or die(mysql_error($this->dbcon)); $this->num_queries++; if(mysql_num_rows($res) > 0){ $device = mysql_fetch_assoc($res); //print_r($device); if($this->device_root == '' && $device['actual_device_root'] == 1){ $this->_toLog("_getDeviceCapabilitiesFromId","device root detected: ".$device['deviceID'], LOG_INFO); $this->device_root = $device['deviceID']; $image = IMAGE_DIR.$device['deviceID'].".gif"; // PHP evaluates from left to right, so "file_exists" will not get // called if IMAGE_CHECKING is false if(IMAGE_CHECKING && file_exists($image)){ $this->device_image = $image; $this->_toLog("_getDeviceCapabilitiesFromId","device image found: $image",LOG_INFO); } } $cap = unserialize($device['capabilities']); //echo "
".print_r($cap,true)."
"; return($cap); }else{ // device is not in the WURFL // deal with it appropriately $this->_toLog('_getDeviceCapabilitiesFromId', "the id $_id is not present in wurfl >>HOW DID THIS HAPPEN???<<", LOG_ERR); //die("the id $_id is not present in wurfl_agents"); // I should never get here!! return(false); } } /** * Given the user_agent reads the device's capabilities. * This method will return true or false based on its success. * After calling this function, the following properties will be accessible (on success): * * * Example: * * $myDevice = new tera_wurfl(); * // get the capabilities of your device * $myDevice->getDeviceCapabilitiesFromAgent($_SERVER['HTTP_USER_AGENT'); * echo "Device: ".$myDevice->brand." ".$myDevice->model."
"; *
* * @param string device's user_agent * @param boolean check the HTTP-ACCEPT headers if needed * @access public * @return boolean success * **/ function getDeviceCapabilitiesFromAgent($_user_agent, $_check_accept=false) { if(count($this->errors) != 0){ $this->_toLog('getDeviceCapabilitiesFromAgent','Returning early because of previous errors. Use $this->clearErrors() to ignore this problem.',LOG_ERR); return(false); } //TODO: Would be cool to log user agent and headers for future use to feed WURFL // clear any existing device root and image $this->device_root = ''; $this->device_image = ''; // Resetting properties $this->user_agent = $_user_agent; // the class prop will remain unchanged $this->num_queries = 0; $this->found_in_cache = false; // if caching is enabled, let's check the cache if(WURFL_CACHE_ENABLE){ $cache_data = $this->_UserAgentInCache($this->user_agent); if($cache_data !== false){ $this->_toLog('_UserAgentInCache', 'UA was found in the cache', LOG_INFO); $this->found_in_cache = true; $cache_data = unserialize($cache_data); //die(print_r($cache_data)); $this->capabilities = $cache_data['capabilities']; $this->_setGlobalProps(); if($cache_data['device_root'] != ''){ $this->_toLog("_UserAgentInCache","device root detected: ".$cache_data['device_root'], LOG_INFO); $this->device_root = $cache_data['device_root']; $image = IMAGE_DIR.$cache_data['device_root'].".gif"; // PHP evaluates from left to right, so "file_exists" will not get // called if IMAGE_CHECKING is false if(IMAGE_CHECKING && file_exists($image)){ $this->device_image = $image; $this->_toLog("_UserAgentInCache","device image found: $image",LOG_INFO); } } return(true); }else{ $this->_toLog('_UserAgentInCache', 'UA was not found in the cache', LOG_INFO); } } // removing the possible Openwave MAG tag // at this point a user agent like this: "UP.Link/6.3.0.0.0" will // result in a null $_user_agent // $_user_agent = trim(ereg_replace("UP.Link.*", "", $_user_agent)); $_user_agent = trim(preg_replace(REMOVE_REGEX, "", $_user_agent)); $this->user_agent = $_user_agent; // if(trim($_user_agent) == '' || !$_user_agent) //FIXME: PocketPCs (Windows Mobile) contain "MSIE 5" // like the Cingular 8125 /** * The following logic has been removed because it has been deemed unmaintainable * with the introduction of so many mobile versions of common desktop browsers. */ /* if ( ( stristr($_user_agent, 'Opera') && stristr($_user_agent, 'Windows') ) || ( stristr($_user_agent, 'Opera') && stristr($_user_agent, 'Linux') ) || stristr($_user_agent, 'Gecko') || ( (stristr($_user_agent, 'MSIE 6') || stristr($_user_agent, 'MSIE 5') ) && !stristr($_user_agent, 'MIDP') && !stristr($_user_agent, 'Windows CE') && !stristr($_user_agent, 'Symbian') ) ) { // This is a web browser. Setting the defaults $this->_toLog('constructor', 'Web browser', LOG_INFO); $this->browser_is_wap=false; $this->capabilities['product_info']['brand_name'] = 'Generic Web browser'; $this->capabilities['product_info']['model_name'] = '1.0'; $this->capabilities['product_info']['is_wireless_device'] = false; $this->capabilities['product_info']['device_claims_web_support'] = true; if($this->ignoreBrowser){ // choosing not to waste time looking up desktop browsers return(true); } } */ // TODO: Spend some time on this code and make it MUCH more robust. // FIXME: I'm not sure that this even actually does anything :( - I think 'browser_is_wap' // get's overwritten anyway. Hmmmm.... Also, I changed it from LOG_WARNING to LOG_NOTICE if ($_check_accept == true) { if (!eregi('wml', $this->http_accept) && !eregi('wap', $this->http_accept) && !eregi('xhtml', $this->http_accept)) { $this->_toLog('getDeviceCapabilitiesFromAgent', 'This browser does not support wml, wap, or xhtml', LOG_NOTICE); $this->browser_is_wap=false; }else{ // We can assume this is a mobile device since it accepts wml || wap || xhtml $this->browser_is_wap=true; } } $this->_toLog('getDeviceCapabilitiesFromAgent', 'searching for '.$_user_agent, LOG_INFO); if(strpos($_user_agent,'/') === false){ // NO '/' IN USER AGENT??? This is not a WAP device (probably not a real device at all) // Version 1.5.2 - changed this to LOG_NOTICE since it is a normal occurence $this->_toLog('getDeviceCapabilitiesFromAgent', 'Invalid user agent', LOG_NOTICE); $this->_setGlobalProps(); return($this->_getGenericID($_user_agent)); } $curr_device = $this->_UserAgentInDB($this->user_agent); if(is_array($curr_device)){ // the exact user agent was in the WURFL - Great! $this->_GetFullCapabilities($curr_device['deviceID']); $this->capabilities['matched_at']=$this->user_agent; $this->_AddUAToCache($this->user_agent,$this->capabilities,$this->device_root); $this->_setGlobalProps(); return(true); } $_ua_len = strlen($_user_agent); $this->_toLog('getDeviceCapabilitiesFromAgent', 'Searching the DB ('.$this->devtable.')', LOG_INFO); // The user_agent should not become shorter than 4 characters $_min_len = 4; if(MATCH_TO_UA_PREFIX){ $_min_len = strpos($_user_agent,'/'); } $matched_dev = NULL; $niceua = rtrim($this->_sqlPrep(substr($_user_agent, 0, $_min_len)),"'")."%'"; $minquery = "SELECT deviceID FROM ".$this->devtable." WHERE user_agent LIKE $niceua ORDER BY actual_device_root LIMIT 2"; $res = mysql_query($minquery,$this->dbcon); $this->num_queries++; $num = mysql_num_rows($res); if($num == 0){ //DEBUG: echo "no devices match the UA down to the min chars in the DB
$minquery"; // no devices match the UA down to the min chars in the DB // basically you're not going to get a match. // look for acceptable generic ID $this->_setGlobalProps(); return($this->_getGenericID($_user_agent)); }else if($num == 1){ // Only one match... No use searching // Christian Aune Thomassen $matched_dev = mysql_result($res,0,'deviceID'); $this->capabilities['matched_at']=substr($_user_agent, 0, $_min_len); $_short_ua = $_user_agent; }else{ // $_ua_len should not be longer than the longest agent which // matches $niceua to reduce the amount of queries // by Christian Aune Thomassen unset($res); $res = mysql_query("SELECT MAX(CHAR_LENGTH(user_agent)) AS max_user_agent FROM ".$this->devtable." WHERE user_agent LIKE $niceua",$this->dbcon); $this->num_queries++; $max_user_agent_len = mysql_result($res,0,'max_user_agent'); if ($max_user_agent_len < $_ua_len) { // the longest user agent that we will come across is smaller than // this user agent - let's not waste our time here! $_ua_len = $max_user_agent_len; } while ( $_ua_len > $_min_len) { //DEBUG: echo "--trying user agent length $_ua_len
"; // version 1.5.2, realized that it should be ($_ua_len - 1) $_short_ua = substr($_user_agent, 0, $_ua_len-1); // take the user agent and prep it: escapes chars and adds single quotes // then remove the right most quote and put %' in it's place which will // make it this MOT- look like this: 'MOT-%' - that will work for MySQL LIKE queries $niceua = rtrim($this->_sqlPrep($_short_ua),"'")."%'"; // May 25 2007 - added order by and limit for accuracy and speed $res = mysql_query("SELECT deviceID FROM ".$this->devtable." WHERE user_agent LIKE $niceua ORDER BY actual_device_root DESC LIMIT 1",$this->dbcon)or die("Error: ".mysql_error()); $this->num_queries++; if(mysql_num_rows($res)>0){ // TODO: add $this->matched_at = $_short_ua $matched_dev = mysql_result($res,0,'deviceID'); break; } // shortening the agent by one each time $_ua_len--; } } if(!is_null($matched_dev)){ //$device = $this->_UserAgentInDB($matched_ua); $this->_GetFullCapabilities($matched_dev); $this->capabilities['matched_at']=$_short_ua; $this->_AddUAToCache($this->user_agent,$this->capabilities,$this->device_root); $this->_toLog('getDeviceCapabilitiesFromAgent', 'Match found in DB after '.$this->num_queries.' queries', LOG_INFO); $this->_setGlobalProps(); return(true); }else{ // no match was found $this->capabilities['matched_at']=$_short_ua; $this->_AddUAToCache($this->user_agent,$this->capabilities,$this->device_root); $this->_toLog('getDeviceCapabilitiesFromAgent', 'No match was found in DB >>THIS SHOULDN\'T EVER HAPPEN!<<', LOG_WARNING); $this->_setGlobalProps(); return(false); } } /** * Checks to see if a given user agent is in the WURFL database * * @param string user agent * @return mixed false if not in DB, else full device record array * @access private */ function _UserAgentInDB($ua){ //TODO: using LIKE will do the search case-insensitive, but = is much faster $res = mysql_query("SELECT * FROM ".$this->devtable." WHERE user_agent LIKE ".$this->_sqlPrep($ua),$this->dbcon); $this->num_queries++; $curr_device = mysql_fetch_assoc($res); $ret = (mysql_num_rows($res) > 0)? $curr_device: false; return($ret); } /** * Checks to see if a given user agent is in the cache * * @param string user agent * @return mixed false if not in cache, else full device cache data array * @access private */ function _UserAgentInCache($ua){ $ua = trim(preg_replace(REMOVE_REGEX, "", $ua)); //TODO: using LIKE will do the search case-insensitive, but = is much faster $query = "SELECT * FROM ".DB_CACHE_TABLE." WHERE user_agent = ".$this->_sqlPrep($ua); $res = mysql_query($query,$this->dbcon); $this->num_queries++; $cache_data = mysql_fetch_assoc($res); $ret = (mysql_num_rows($res) > 0)? $cache_data['cache_data']: false; //if(!$ret)die($query); return($ret); } /** * Adds a user agent and its associated data to the cache * * @param string user agent * @param array capabilities * @param string device root * @return mixed false if not in cache, else full device cache data array * @access private */ function _AddUAToCache($ua,$cap,$devroot){ if(!WURFL_CACHE_ENABLE)return(true); $ua = trim(preg_replace(REMOVE_REGEX, "", $ua)); // don't cache UAs that are too short to be real if(strlen($ua) < 3)return(true); $cache_data = serialize(array("capabilities"=>$cap,"device_root"=>$devroot)); // FIXME: DELAYED INSERTS only work on MyIASM mysql_query("INSERT DELAYED INTO ".DB_CACHE_TABLE." (user_agent,cache_data) VALUES (".$this->_sqlPrep($ua).",".$this->_sqlPrep($cache_data).")",$this->dbcon); $this->_toLog('_AddUAToCache', 'Added UA to cache: '.$ua, LOG_INFO); $this->num_queries++; return(true); } /** * Given a capability name returns the value (true|false|). This is * helpful if you don't know the group that the capability is in. * * Example: * * $myDevice = new tera_wurfl(); * // get the capabilities of your device * $callstring $myDevice->getDeviceCapability('wml_make_phone_call_string'); * echo "Call me"; * * * @param string capability name as a string * @access public * @return string NULL if not found, else value specified in the WURFL * */ function getDeviceCapability($capability) { $this->_toLog('getDeviceCapability', 'Searching for '.$capability.' as a capability', LOG_INFO); $deviceCapabilities = $this->capabilities; foreach ( $deviceCapabilities as $group ) { if ( !is_array($group) ) { continue; } while ( list($key, $value)=each($group) ) { if ($key==$capability) { $this->_toLog('getDeviceCapability', 'I found it, value is '.$value, LOG_INFO); return $value; } } } $this->_toLog('getDeviceCapability', 'I could not find the requested capability ('.$capability.'), returning NULL', LOG_WARNING); // since 1.5.2, I can't return "false" because that is a valid value. Now I return NULL, use is_null() to check return NULL; } /** * Clears any LOG_ERR level errors that were detected. This will * allow you to continue testing other user agents after an error * is detected. * * Example: * * $myDevice = new tera_wurfl(); * // this will throw an error and prevent the methods from working * $myDevice->getDeviceCapabilitiesFromAgent(""); * // clear any errors * $myDevice->clearErrors(); * // now we can check another user agent * $myDevice->getDeviceCapabilitiesFromAgent("MOT-V3"); * * * @access public * @return boolean true */ function clearErrors(){ $this->errors = array(); return(true); } /** * Calculates the confidence of the match. Returns the confidence * percentage as an precision 2 decimal beween 0-100. * * @access public * @return decimal(10,2) match confidence percentage from 0 to 100 */ function matchConfidence(){ return(round(strlen($this->capabilities['matched_at'])/strlen(preg_replace(REMOVE_REGEX,'',$this->user_agent))*100,2)); } /** * This function checks and prepares the text to be logged * * @access private * @param string Function name * @param string Reason text/description * @param int Log level (LOG_ERR|LOG_WARNING|LOG_NOTICE|LOG_INFO) * Any of the PHP LOG contstants will work, but if you * throw a LOG_ERR, the script will stop and return false */ function _toLog($func, $text, $requestedLogLevel=LOG_NOTICE){ if($requestedLogLevel == LOG_ERR) $this->errors[] = $text; if ( !defined('LOG_LEVEL') || LOG_LEVEL == 0 || ($requestedLogLevel-1) >= LOG_LEVEL ) { return; } if ( $requestedLogLevel == LOG_ERR ) { $warn_banner = 'ERROR: '; } else if ( $requestedLogLevel == LOG_WARNING ) { $warn_banner = 'WARNING: '; } else { $warn_banner = ''; } // Thanks laacz $_textToLog = date('r')." [".php_uname('n')." ".getmypid()."]"."[$func] ".$warn_banner . $text; $_logFP = fopen(WURFL_LOG_FILE, "a+"); fputs($_logFP, $_textToLog."\n"); fclose($_logFP); return(true); } /** * Kills the script on fatal database errors * * @access private */ function _dberror(){ die("Error in query: ".mysql_error($this->dbcon)); } /** * This function checks the user agent for signs that it's a WAP device * Returns true if a generic ID is found, otherwise false. * This is a last resort function that is only called if the device in question * does not exist in the WURFL and the class is forced to find another way to * identify the device. * * @param string User agent * @access private * @return boolean success */ function _getGenericID($_user_agent){ if(RETURN_GENERIC === false){ $this->capabilities['matched_at']=''; return false; } $this->_toLog('getGenericID', "I couldn't find the device in my list, the headers are my last chance", LOG_NOTICE); $matched_dev = ''; $my_is_wireless = false; if ( strstr($_user_agent, 'UP.Browser/') && strstr($_user_agent, '(GUI)') ) { $matched_dev = 'upgui_generic'; $my_is_wireless = true; } else if ( strstr($_user_agent, 'UP.Browser/') ) { $matched_dev = 'uptext_generic'; $my_is_wireless = true; } else if ( eregi('wml', $this->http_accept) || eregi('wap', $this->http_accept) ) { $matched_dev = 'generic'; $my_is_wireless = true; } else { $this->_toLog('getGenericID', 'This should not be a WAP device, quitting', LOG_NOTICE); $matched_dev = 'generic'; $my_is_wireless = false; } $this->_GetFullCapabilities($matched_dev); $this->capabilities['matched_at']=''; $this->capabilities['product_info']['is_wireless_device']=$my_is_wireless; $this->_setGlobalProps(); // we should return false if this device is generic and not wireless // this "unmatched device" is not cached because there is no logical way to tell // that it is unmatched when we read it from the cache. if($my_is_wireless === false) return false; $this->_AddUAToCache($this->user_agent,$this->capabilities,$this->device_root); return true; } /** * Given a string, will escape any unfriendly characters and return * a single quoted string to be used directly in an SQL statement to a * MySQL server. * Given a real number it will return the number without quotes so MySQL * sees it as a number instead of a string. * Given a null string ('') it will return the MySQL keyword NULL. * * Example: it's a fine day -> 'it\'s a fine day' * @param mixed Input variable to be prepared * @access private */ function _sqlPrep($value){ if (get_magic_quotes_gpc()) $value = stripslashes($value); if($value == '') $value = 'NULL'; else if (!is_numeric($value) || $value[0] == '0') $value = "'" . $this->_compatibleEscape($value) . "'"; //Quote if not integer return($value); } /** * This allows PHP < 4.3.0 to use Tera-WURFL * * @param mixed Input variable to be prepared * @access private */ function _compatibleEscape($value){ if (version_compare(phpversion(), "4.3.0", ">=")) { // you're on 4.3.0 or later return(mysql_real_escape_string($value)); } else { // you're not return(mysql_escape_string($value)); } } function _setGlobalProps(){ $this->GUI = false; if(!isset($this->capabilities['product_info']['is_wireless_device'])){ $this->capabilities['product_info'] = array(); // set this to false by default $this->capabilities['product_info']['is_wireless_device'] = false; $this->capabilities['product_info']['brand_name'] = ''; $this->capabilities['product_info']['model_name'] = ''; } unset($this->wurfl_agent); unset($this->browser_is_wap); unset($this->brand); unset($this->model); unset($this->id); $this->wurfl_agent = $this->capabilities['user_agent']; $this->browser_is_wap = $this->capabilities['product_info']['is_wireless_device']; $this->brand = $this->capabilities['product_info']['brand_name']; $this->model = $this->capabilities['product_info']['model_name']; $this->id = $this->capabilities['id']; } } ?>