tera_wurfl
[ class tree: tera_wurfl ] [ index: tera_wurfl ] [ all elements ]

Source for file tera_wurfl.php

Documentation is available at tera_wurfl.php

  1. <?php
  2. /*
  3.  * Tera_WURFL - PHP MySQL driven WURFL
  4.  * 
  5.  * Tera-WURFL was written by Steve Kamerman, Tera Technologies and is based on the
  6.  * WURFL PHP Tools from http://wurfl.sourceforge.net/.  This version uses a MySQL database
  7.  * to store the entire WURFL file to provide extreme performance increases.
  8.  * 
  9.  * @package tera_wurfl
  10.  * @author Steve Kamerman, Tera Technologies (kamermans AT teratechnologies DOT net)
  11.  * @version Stable 1.5.0 $Date: 2007/04/27 17:26:50 $
  12.  * @license http://www.mozilla.org/MPL/ MPL Vesion 1.1
  13.  * $Id: tera_wurfl.php,v 1.1.4.6.2.19 2007/04/27 17:26:50 kamermans Exp $
  14.  * $RCSfile: tera_wurfl.php,v $
  15.  * 
  16.  * Based On: WURFL PHP Tools by Andrea Trasatti ( atrasatti AT users DOT sourceforge DOT net )
  17.  *
  18.  */
  19.  
  20. if !defined('WURFL_CONFIG') )
  21.     require_once(dirname(__FILE__).'/tera_wurfl_config.php');
  22.  
  23. if !defined('WURFL_CONFIG') )
  24.     die("NO CONFIGURATION");
  25.  
  26. if defined('WURFL_PARSER_FILE') )
  27.     require_once(WURFL_PARSER_FILE);
  28. else
  29.     require_once(dirname(__FILE__)."/tera_wurfl_parser.php");
  30.  
  31. /**
  32.  * Tera-WURFL was written by Steve Kamerman, Tera Technologies and is based on the
  33.  * WURFL PHP Tools from http://wurfl.sourceforge.net/.  This version uses a MySQL database
  34.  * to store the entire WURFL file to provide extreme performance increases.
  35.  * 
  36.  * See the documentation for specific usage information.
  37.  * Quick Example:
  38.  * <code>
  39.  * $myDevice = new tera_wurfl();
  40.  * $myDevice->getDeviceCapabilitiesFromAgent($_SERVER['HTTP_USER_AGENT');
  41.  * // see if this device is really a mobile browser
  42.  * if($myDevice->browser_is_wap){
  43.  *     // check capabilities
  44.  *    if($myDevice->capabilities['downloadfun']['downloadfun_support']){
  45.  *        echo "downloadfun supported<br />";
  46.  *    }else{
  47.  *        echo "WAP is supported, downloadfun is not<br />";
  48.  *     }
  49.  *    if($myDevice->device_image != ''){
  50.  *         // display device image
  51.  *         echo '<img src="'.$myDevice->device_image.'" /><br />';
  52.  *     }
  53.  * }
  54.  * </code>
  55.  * 
  56.  * @package tera_wurfl
  57.  */
  58. class tera_wurfl {
  59.     /**
  60.      * Internal tracking of the WURFL ID
  61.      * @var string 
  62.      * @access private
  63.      */
  64.     var $id="";
  65.  
  66.     /**
  67.      * If true, Openwave's GUI (mostly wml 1.3) is supported
  68.      * @var bool 
  69.      * @access public
  70.      */
  71.     var $GUI=false;
  72.  
  73.     /**
  74.      * Device brand (manufacturer)
  75.      * @var string 
  76.      * @access public
  77.      */
  78.     var $brand='';
  79.  
  80.     /**
  81.      * Device model name
  82.      * @var string 
  83.      * @access public
  84.      */
  85.     var $model='';
  86.  
  87.     /**
  88.      * If this is a WAP device, this is set to true
  89.      * @var boolean 
  90.      * @access public
  91.      */
  92.     var $browser_is_wap=false;
  93.  
  94.     /**
  95.      * associative array with all the device's capabilities.
  96.      * 
  97.      * Example:  $this->capabilities['downloadfun']['downloadfun_support']
  98.      *    true if downloadfun is supported, otherwise false
  99.      *
  100.      * @var associative array
  101.      * @access public
  102.      */
  103.     var $capabilities=array();
  104.  
  105.     /**
  106.      * HTTP_ACCEPT request headers
  107.      * Use this to manually set the http-accept string:
  108.      * 
  109.      * Example:  $this->http_accept = "text/vnd.wap.wml";
  110.      * @var string 
  111.      * @access public
  112.      */
  113.     var $http_accept="";
  114.  
  115.     /**
  116.      * Ignore desktop browser
  117.      * Set this to false if you want to search the WURFL/patch
  118.      * for desktop web browsers as well.
  119.      * 
  120.      * @var string 
  121.      * @access public
  122.      */
  123.     var $ignoreBrowser=false;
  124.  
  125.     /**
  126.      * Track errors
  127.      * Anytime a LOG_ERR level event occurs, a description is
  128.      * added to the end of the array.
  129.      * Example:  echo count($this->$errors); // echos number of errors
  130.      * @var array 
  131.      * @access public
  132.      */
  133.     var $errors = array();
  134.  
  135.     /**
  136.      * Internal database link resource
  137.      * @var resource 
  138.      * @access private
  139.      */
  140.     var $dbcon '';
  141.     
  142.     /**
  143.      * Internal device table tracking.  Used to provide some members with the name
  144.      * of the current device table.  It will be either DB_DEVICE_TABLE or DB_HYBRID_TABLE
  145.      * @var string 
  146.      * @access private
  147.      */
  148.     var $devtable '';
  149.     
  150.     /**
  151.      * WURFL ID of the ancestoral device root
  152.      * This is the ID of the actual device, not a firmware revision
  153.      *
  154.      * @var string 
  155.      * @access public
  156.      */
  157.     var $device_root = '';
  158.     
  159.     /**
  160.      * Device image path and filename, relative to the class file
  161.      *
  162.      * @var string 
  163.      * @access public
  164.      */
  165.     var $device_image = '';
  166.     
  167.     /**
  168.      * Total number of queries performed
  169.      * 
  170.      * @var number 
  171.      * @access public
  172.      */
  173.     var $num_queries = 0;
  174.     
  175.     /**
  176.      * True if the UA was found in the cache
  177.      * 
  178.      * @var boolean 
  179.      * @access public
  180.      */
  181.     var $found_in_cache = false;
  182.     
  183.     /**
  184.      * Constructor, sets the http_accept property and connects to the WURFL database.
  185.      * You don't need to call the constructor - it is called when you instantiate the class
  186.      *
  187.      * @access public
  188.      * @return boolean    success
  189.      *
  190.      */
  191.     function tera_wurfl({
  192.         // connect to database
  193.         $this->dbcon mysql_connect(DB_HOST,DB_USER,DB_PASSor die("ERROR: Could not connect to MySQL Server (".DB_HOST."): ".mysql_error());
  194.         // select schema
  195.         mysql_select_db(DB_SCHEMA,$this->dbconor die("ERROR: Connected to MySQL Server but could not select database (".DB_SCHEMA."): ".mysql_error());
  196.         if(WURFL_PATCH_ENABLE){
  197.             $this->devtable DB_HYBRID_TABLE;
  198.         }else{
  199.             $this->devtable DB_DEVICE_TABLE;
  200.         }
  201. //TODO: remove this test - it's too slow
  202. // make sure the device table exists
  203. //$test = @mysql_query("SELECT COUNT(deviceID) AS num FROM ".$this->devtable) or die("ERROR: Device table not found (".$this->devtable."): ".mysql_error()."<br/><br/><strong>If this is a new installation, please <a href=\"admin/\">update the database</a>.");
  204. //$this->num_queries++;
  205.         // make sure the device table is not empty
  206. //if(mysql_result($test,0,"num") == 0)die("ERROR: The device table (".$this->devtable.") is empty. Please update the WURFL database.");
  207.         // set the default http-accept
  208.         $this->http_accept = $_SERVER['HTTP_ACCEPT'];
  209.         $this->_toLog('constructor''-----Class Initiated-----'LOG_NOTICE);
  210.         return(true);
  211.     }
  212.  
  213.     /**
  214.      * Given the device's id reads all its capabilities and each
  215.      * parent (fall_back) devices' capabilities and merges them
  216.      *
  217.      * @param string the device's id from the WURFL database
  218.      * @access private
  219.      * @return boolean success
  220.      */
  221.     function _GetFullCapabilities($_id{
  222.         if(count($this->errors!= 0return(false);
  223.         $this->_toLog('_GetFullCapabilities'"searching for $_id"LOG_INFO);
  224.         $_curr_device $this->_getDeviceCapabilitiesFromId($_id);
  225.         // array of full records
  226.         $_capabilities[$_curr_device;
  227.         // keep the while loop from running away on an error
  228.         $iteration_limit 20;
  229.         $i 0;
  230.         while $_curr_device['fall_back'!= 'generic' && $_curr_device['fall_back'!= 'root' && $i <= $iteration_limit{
  231.             $this->_toLog('_GetFullCapabilities''parent device:'.$_curr_device['fall_back'].' now going to read its capabilities'LOG_INFO);
  232.             $_curr_device $this->_getDeviceCapabilitiesFromId($_curr_device['fall_back']);
  233.             array_unshift($_capabilities,$_curr_device);
  234.             $i++;
  235.         }
  236.         if($i >= $iteration_limit){
  237.             // the while loop ran away
  238.             $this->_toLog('_GetFullCapabilities''Killing runaway while loop - $_id='.$_idLOG_ERR);
  239.             return(false);
  240.         }
  241.         $this->_toLog('_GetFullCapabilities''reading capabilities of \'generic\' device'LOG_INFO);
  242.         $generic $this->_getDeviceCapabilitiesFromId('generic');
  243.         $_final $generic;
  244.         // the generic devices are already at the top of the array because I used array_unshift()
  245.         foreach($_capabilities as $curr_device){
  246.             //TODO: Why don't I just array_merge the whole record???? Good question!
  247.             foreach($curr_device as $key => $val{
  248.                 if is_array($val) ) {
  249.                     $_final[$keyarray_merge($_final[$key]$val);
  250.                 else {
  251.                     $_final[$key$val;
  252.                 }
  253.             }
  254.         }
  255.         $this->capabilities = $_final;
  256.         //$this->brand = $this->capabilities['product_info']['brand_name'];
  257.         //$this->model = $this->capabilities['product_info']['model_name'];
  258.         //$this->id = $this->capabilities['id'];
  259.         return(true);
  260.     }
  261.  
  262.     /**
  263.      * Given a device id reads its capabilities
  264.      *
  265.      * @param string device's wurfl_id
  266.      * @access private
  267.      * @return mixed boolean false if not identified or array capabilities
  268.      *
  269.      */
  270.     function _getDeviceCapabilitiesFromId($_id{
  271.         if(count($this->errors!= 0return(false);
  272.         $this->_toLog('_getDeviceCapabilitiesFromId'"reading id:$_id"LOG_INFO);
  273.         if $_id == 'upgui_generic' {
  274.             $this->GUI = true;
  275.         }
  276.         $res mysql_query("SELECT * FROM ".$this->devtable." WHERE deviceID=".$this->_sqlPrep($_id),$this->dbconor die(mysql_error($this->dbcon));
  277.         $this->num_queries++;
  278.         if(mysql_num_rows($res0){
  279.             $device mysql_fetch_assoc($res);
  280.             //print_r($device);
  281.             if($this->device_root == '' && $device['actual_device_root'== 1){
  282.                 $this->_toLog("_getDeviceCapabilitiesFromId","device root detected: ".$device['deviceID']LOG_INFO);
  283.                 $this->device_root = $device['deviceID'];
  284.                 $image IMAGE_DIR.$device['deviceID'].".gif";
  285.                 // PHP evaluates from left to right, so "file_exists" will not get
  286.                 // called if IMAGE_CHECKING is false
  287.                 if(IMAGE_CHECKING && file_exists($image)){
  288.                     $this->device_image = $image;
  289.                     $this->_toLog("_getDeviceCapabilitiesFromId","device image found$image",LOG_INFO);
  290.                 }
  291.             }
  292.             $cap unserialize($device['capabilities']);
  293.             //echo "<pre>".print_r($cap,true)."</pre>";
  294.             return($cap);
  295.         }else{
  296.             // device is not in the WURFL
  297.             // deal with it appropriately
  298.             $this->_toLog('_getDeviceCapabilitiesFromId'"the id $_id is not present in wurfl"LOG_WARNING);
  299.             //die("the id $_id is not present in wurfl_agents");
  300.             echo("the id ($_idis not present in wurfl DB<br />");
  301.             // I should never get here!!
  302.             return(false);
  303.         }
  304.     }
  305.  
  306.     /**
  307.      * Given the user_agent reads the device's capabilities.
  308.      * This method will return true or false based on its success.
  309.      * After calling this function, the following properties will be accessible (on success):
  310.      * <ul>
  311.      * <li>$this->brand</li>
  312.      * <li>$this->model</li>
  313.      * <li>$this->browser_is_wap</li>
  314.      * <li>$this->capabilities</li>
  315.      * <li>$this->device_root</li>
  316.      * <li>$this->device_image (if enabled)</li>
  317.      * <li>$this->errors</li>
  318.      * <li>$this->GUI</li>
  319.      * </ul>
  320.      * 
  321.      * Example:
  322.      * <code>
  323.      * $myDevice = new tera_wurfl();
  324.      * // get the capabilities of your device
  325.      * $myDevice->getDeviceCapabilitiesFromAgent($_SERVER['HTTP_USER_AGENT');
  326.      * echo "Device: ".$myDevice->brand." ".$myDevice->model."<br />";
  327.      * </code>
  328.      * 
  329.      * @param string    device's user_agent
  330.      * @param boolean    check the HTTP-ACCEPT headers if needed
  331.      * @access public
  332.      * @return boolean success
  333.      *
  334.      ***/
  335.     function getDeviceCapabilitiesFromAgent($_user_agent$_check_accept=false{
  336.         if(count($this->errors!= 0return(false);
  337.         //TODO: Would be cool to log user agent and headers for future use to feed WURFL
  338.         // clear any existing device root and image
  339.         $this->device_root = '';
  340.         $this->device_image = '';
  341.         // Resetting properties
  342.         $this->user_agent $_user_agent// the class prop will remain unchanged
  343.         // FIXME: I'm not sure if people use these, but they're not getting set all the time
  344.         $this->wurfl_agent '';
  345.         $this->GUI = false;
  346.         $this->capabilities = array();
  347.         $this->capabilities['product_info'array();
  348.         // set this to false by default
  349.         $this->capabilities['product_info']['is_wireless_device'false;
  350.         $this->capabilities['product_info']['brand_name''';
  351.         $this->capabilities['product_info']['model_name''';
  352.         // As of version 1.4.5 the short names are references to the actual capabilities
  353.         $this->browser_is_wap = &$this->capabilities['product_info']['is_wireless_device'];
  354.         $this->brand = &$this->capabilities['product_info']['brand_name'];
  355.         $this->model = &$this->capabilities['product_info']['model_name'];
  356.         $this->id &$this->capabilities['id'];
  357.         $this->num_queries = 0;
  358.         $this->found_in_cache = false;
  359.  
  360.         // if caching is enabled, let's check the cache
  361.         if(WURFL_CACHE_ENABLE){
  362.             $cache_data $this->_UserAgentInCache($this->user_agent);
  363.             if($cache_data !== false){
  364.                 $this->_toLog('_UserAgentInCache''UA was found in the cache'LOG_INFO);
  365.                 $this->found_in_cache = true;
  366.                 $cache_data unserialize($cache_data);
  367. //die(print_r($cache_data));
  368.                 $this->capabilities = $cache_data['capabilities'];
  369.                 if($cache_data['device_root'!= ''){
  370.                     $this->_toLog("_UserAgentInCache","device root detected: ".$cache_data['device_root']LOG_INFO);
  371.                     $this->device_root = $cache_data['device_root'];
  372.                     $image IMAGE_DIR.$cache_data['device_root'].".gif";
  373.                     // PHP evaluates from left to right, so "file_exists" will not get
  374.                     // called if IMAGE_CHECKING is false
  375.                     if(IMAGE_CHECKING && file_exists($image)){
  376.                         $this->device_image = $image;
  377.                         $this->_toLog("_UserAgentInCache","device image found$image",LOG_INFO);
  378.                     }
  379.                 }
  380.                 return(true);
  381.             }else{
  382.                 $this->_toLog('_UserAgentInCache''UA was not found in the cache'LOG_INFO);
  383.             }
  384.         }
  385.         // removing the possible Openwave MAG tag
  386.         // at this point a user agent like this: "UP.Link/6.3.0.0.0" will
  387.         // result in an null $_user_agent
  388.         //FIXME: why do we really need to get rid of this anyway???
  389.         $_user_agent trim(ereg_replace("UP.Link.*"""$_user_agent));
  390. //        if(trim($_user_agent) == '' || !$_user_agent)
  391.         //FIXME: PocketPCs (Windows Mobile) contain "MSIE 5"
  392.         // like the Cingular 8125
  393.         /**
  394.          * The following logic has been removed because it has been deemed unmaintainable
  395.          * with the introduction of so many mobile versions of common desktop browsers.
  396.          */
  397. /*        if (    ( stristr($_user_agent, 'Opera') && stristr($_user_agent, 'Windows') )
  398.             || ( stristr($_user_agent, 'Opera') && stristr($_user_agent, 'Linux') )
  399.             || stristr($_user_agent, 'Gecko')
  400.             || ( (stristr($_user_agent, 'MSIE 6') || stristr($_user_agent, 'MSIE 5') ) && !stristr($_user_agent, 'MIDP') && !stristr($_user_agent, 'Windows CE') && !stristr($_user_agent, 'Symbian') )
  401.             ) {
  402.             // This is a web browser. Setting the defaults
  403.             $this->_toLog('constructor', 'Web browser', LOG_INFO);
  404.             $this->browser_is_wap=false;
  405.             $this->capabilities['product_info']['brand_name'] = 'Generic Web browser';
  406.             $this->capabilities['product_info']['model_name'] = '1.0';
  407.             $this->capabilities['product_info']['is_wireless_device'] = false;
  408.             $this->capabilities['product_info']['device_claims_web_support'] = true;
  409.             if($this->ignoreBrowser){
  410.                 // choosing not to waste time looking up desktop browsers
  411.                 return(true);
  412.             }
  413.         }
  414. */
  415.         // TODO: Spend some time on this code and make it MUCH more robust.
  416.         // FIXME: I'm not sure that this even actually does anything :( - I think 'browser_is_wap'
  417.         // get's overwritten anyway. Hmmmm....  Also, I changed it from LOG_WARNING to LOG_NOTICE
  418.         if ($_check_accept == true{
  419.             if (!eregi('wml'$this->http_accept&& !eregi('wap'$this->http_accept&& !eregi('xhtml'$this->http_accept)) {
  420.                 $this->_toLog('getDeviceCapabilitiesFromAgent''This browser does not support wml, wap, or xhtml'LOG_NOTICE);
  421.                 $this->browser_is_wap=false;
  422.             }else{
  423.                 // We can assume this is a mobile device since it accepts wml || wap || xhtml
  424.                 $this->browser_is_wap=true;
  425.             }
  426.         }
  427.         $this->_toLog('getDeviceCapabilitiesFromAgent''searching for '.$_user_agentLOG_INFO);
  428.         if trim($_user_agent== '' || !$_user_agent {
  429.             // NO USER AGENT??? This is not a WAP device
  430.             $this->_toLog('getDeviceCapabilitiesFromAgent''No user agent'LOG_ERR);
  431.             $this->browser_is_wap=false;
  432.             return(false);
  433.         }
  434.         $curr_device $this->_UserAgentInDB($this->user_agent);
  435.         if(is_array($curr_device)){
  436.             // the exact user agent was in the WURFL - Great!
  437.             //DEBUG: echo "Found exact UA in DB!<br />".print_r($curr_device,true)."<br />";
  438.             $this->_GetFullCapabilities($curr_device['deviceID']);
  439.             // in case you have desktop web browsers in your patch file
  440.             // It was suggested by MOLABIB on 22Dec2006 that the following line
  441.             // is incorrect and should be replaced:
  442.             // $this->browser_is_wap = $this->capabilities['browser_is_wap'];
  443.             // the following is it's replacement:
  444.             //$this->browser_is_wap = $this->capabilities['product_info']['is_wireless_device'];
  445.             //$this->brand = $this->capabilities['product_info']['brand_name'];
  446.             //$this->model = $this->capabilities['product_info']['model_name'];
  447.             $this->_AddUAToCache($this->user_agent,$this->capabilities,$this->device_root);
  448.             return(true);
  449.         }
  450.         // the user agent was NOT in the WURFL - try to dissect it
  451.         $_ua $_user_agent;
  452.         // Used to be $_ua_len = strlen($_ua) - 1 but that resulted in erroneous results since
  453.         // the full string could still match UAs longer than itself in the DB
  454.         // Thanks to Christian Aune Thomassen [christian.thomassen(at)waptheweb.no] for finding this bug!
  455.         $_ua_len strlen($_ua);
  456.         // Searching in wurfl_agents
  457.         // The user_agent should not become shorter than 4 characters
  458.         $this->_toLog('getDeviceCapabilitiesFromAgent''Searching the DB ('.$this->devtable.')'LOG_INFO);
  459.         // I request to set a short list of UA's among which I should search an unknown user agent
  460.         $_short_ua_len 4;
  461.         $_last_good_short_ua array();
  462.         $_min_len 4;
  463.         // track number of queries
  464.         $niceua rtrim($this->_sqlPrep(substr($_ua0$_min_len)),"'")."%'";
  465.         $minquery "SELECT COUNT(deviceID) AS num FROM ".$this->devtable." WHERE user_agent LIKE $niceua";
  466.         $res mysql_query($minquery,$this->dbcon);
  467.         $this->num_queries++;
  468.         $_short_wurfl_ua array();
  469.         if(mysql_result($res,0,'num'== 0){
  470.             //DEBUG: echo "no devices match the UA down to the min chars in the DB<br />$minquery";
  471.             // no devices match the UA down to the min chars in the DB
  472.             // basically you're not going to get a match.
  473.             // look for acceptable generic ID
  474.             if(!$this->_getGenericID($_user_agent)){
  475.                 // no generic ID found - assuming this is not a WAP device
  476.                 return(true);
  477.             }
  478.         }else{
  479.             while $_ua_len $_min_len{
  480.                 //DEBUG: echo "--trying user agent length $_ua_len<br />";
  481.                 $_short_wurfl_ua array();
  482.                 $_short_ua substr($_ua0$_ua_len);
  483.                 // take the user agent and prep it (escapes chars and adds single quotes
  484.                 // then remove the right most quote and put %' in it's place which will
  485.                 // make it this MOT- look like this: 'MOT-%' - that will work for MySQL LIKE queries
  486.                 $niceua rtrim($this->_sqlPrep($_short_ua),"'")."%'";
  487.                 $res mysql_query("SELECT user_agent FROM ".$this->devtable." WHERE user_agent LIKE $niceua",$this->dbcon);
  488.                 $this->num_queries++;
  489.                 while($row mysql_fetch_assoc($res)){
  490.                     // load the $_short_wurfl_ua array with matching user agents
  491.                     $_short_wurfl_ua[$row['user_agent'];
  492.                 }
  493.                 if $_ua_len <= $_min_len && count($_short_wurfl_ua== {
  494.                     // Probably impossible to get here, but if it does there is no match
  495.                     // DEBUG fast search echo "no match even for the first 4 chars<br>\n";
  496.                     break;
  497.                 }
  498.                 if count($_short_wurfl_ua{
  499.                     // This is the FIRST time that ANY matching user agents were found
  500.                     //DEBUG: echo "list has ".count($_short_wurfl_ua)." elements<br />";
  501.                     break;
  502.                 }
  503.                 // shortening the agent by one each time
  504.                 $_ua_len--;
  505.             }
  506.         }
  507.         //DEBUG: die("Done.<br />Original UA: $_user_agent<br />Best match UA: ".$_short_wurfl_ua[0]."<br />");
  508.         //FIXME: probably shouldn't blindly grab the first UA, so improve...
  509.         if(count($_short_wurfl_ua0){
  510.             $bestmatch array_shift($_short_wurfl_ua);
  511.             $device $this->_UserAgentInDB($bestmatch);
  512.             $this->_GetFullCapabilities($device['deviceID']);
  513.             $this->_AddUAToCache($this->user_agent,$this->capabilities,$this->device_root);
  514.             $this->_toLog('getDeviceCapabilitiesFromAgent''Match found in DB after '.$this->num_queries.' queries'LOG_INFO);
  515.             return(true);
  516.         }else{
  517.             // no match was found
  518.             $this->_AddUAToCache($this->user_agent,$this->capabilities,$this->device_root);
  519.             $this->_toLog('getDeviceCapabilitiesFromAgent''No match was found in DB'LOG_INFO);
  520.             return(false);
  521.         }
  522.     }
  523.     /**
  524.      * Checks to see if a given user agent is in the WURFL database
  525.      * 
  526.      * @param string user agent
  527.      * @return mixed false if not in DB, else full device record array
  528.      * @access private
  529.      */
  530.     function _UserAgentInDB($ua){
  531.         //TODO: using LIKE will do the search case-insensitive, but = is much faster
  532.         $res mysql_query("SELECT * FROM ".$this->devtable." WHERE user_agent LIKE ".$this->_sqlPrep($ua),$this->dbcon);
  533.         $this->num_queries++;
  534.         $curr_device mysql_fetch_assoc($res);
  535.         $ret (mysql_num_rows($res0)$curr_devicefalse;
  536.         return($ret);
  537.     }
  538.     /**
  539.      * Checks to see if a given user agent is in the cache
  540.      * 
  541.      * @param string user agent
  542.      * @return mixed false if not in cache, else full device cache data array
  543.      * @access private
  544.      */
  545.     function _UserAgentInCache($ua){
  546.         //TODO: using LIKE will do the search case-insensitive, but = is much faster
  547.         $query "SELECT * FROM ".DB_CACHE_TABLE." WHERE user_agent = ".$this->_sqlPrep($ua);
  548.         $res mysql_query($query,$this->dbcon);
  549.         $this->num_queries++;
  550.         $cache_data mysql_fetch_assoc($res);
  551.         $ret (mysql_num_rows($res0)$cache_data['cache_data']false;
  552. //if(!$ret)die($query);
  553.         return($ret);
  554.     }
  555.     /**
  556.      * Adds a user agent and its associated data to the cache
  557.      * 
  558.      * @param string user agent
  559.      * @param array capabilities
  560.      * @param string device root
  561.      * @return mixed false if not in cache, else full device cache data array
  562.      * @access private
  563.      */
  564.     function _AddUAToCache($ua,$cap,$devroot){
  565.         if(!WURFL_CACHE_ENABLE)return(true);
  566.         // don't cache UAs that are too short to be real
  567.         if(strlen($ua3)return(true);
  568.         $cache_data serialize(array("capabilities"=>$cap,"device_root"=>$devroot));
  569.         // FIXME: DELAYED INSERTS only work on MyIASM
  570.         mysql_query("INSERT DELAYED INTO ".DB_CACHE_TABLE." (user_agent,cache_data) VALUES (".$this->_sqlPrep($ua).",".$this->_sqlPrep($cache_data).")",$this->dbcon);
  571.         $this->_toLog('_AddUAToCache''Added UA to cache: '.$uaLOG_INFO);
  572.         $this->num_queries++;
  573.         return(true);
  574.     }
  575.     /**
  576.      * Given a capability name returns the value (true|false|<anythingelse>).  This is
  577.      * helpful if you don't know the group that the capability is in.
  578.      * 
  579.      * Example:
  580.      * <code>
  581.      * $myDevice = new tera_wurfl();
  582.      * // get the capabilities of your device
  583.      * $callstring $myDevice->getDeviceCapability('wml_make_phone_call_string');
  584.      * echo "<a href=\"$callstring6161234567\">Call me</a>";
  585.      * </code>
  586.      * 
  587.      * @param string capability name as a string
  588.      * @access public
  589.      * @return mixed boolean success or other string if specified in the WURFL
  590.      *
  591.      */
  592.     function getDeviceCapability($capability{
  593.         $this->_toLog('_getDeviceCapability''Searching for '.$capability.' as a capability'LOG_INFO);
  594.         $deviceCapabilities $this->capabilities;
  595.         foreach $deviceCapabilities as $group {
  596.             if !is_array($group) ) {
  597.                 continue;
  598.             }
  599.             while list($key$value)=each($group) ) {
  600.                 if ($key==$capability{
  601.                     $this->_toLog('_getDeviceCapability''I found it, value is '.$valueLOG_INFO);
  602.                     return $value;
  603.                 }
  604.             }
  605.         }
  606.         $this->_toLog('_getDeviceCapability''I could not find the requested capability, returning false'LOG_WARNING);
  607.         return false;
  608.     }
  609.     /**
  610.      * Clears any LOG_ERR level errors that were detected.  This will
  611.      * allow you to continue testing other user agents after an error
  612.      * is detected.
  613.      *
  614.      * Example:
  615.      * <code>
  616.      * $myDevice = new tera_wurfl();
  617.      * // this will throw an error and prevent the methods from working
  618.      * $myDevice->getDeviceCapabilitiesFromAgent("");
  619.      * // clear any errors
  620.      * $myDevice->clearErrors();
  621.      * // now we can check another user agent
  622.      * $myDevice->getDeviceCapabilitiesFromAgent("MOT-V3");
  623.      * </code>
  624.      * 
  625.      * @access public
  626.      * @return boolean true
  627.      */
  628.     function clearErrors(){
  629.         $this->errors = array();
  630.         return(true);
  631.     }
  632.  
  633.     /**
  634.      * This function checks and prepares the text to be logged
  635.      *
  636.      * @access private
  637.      * @param string        Function name
  638.      * @param string        Reason text/description
  639.      * @param int            Log level (LOG_ERR|LOG_WARN|LOG_NOTICE|LOG_INFO)
  640.      *                          Any of the PHP LOG contstants will work, but if you
  641.      *                          throw a LOG_ERR, the script will stop and return false
  642.      */
  643.     function _toLog($func$text$requestedLogLevel=LOG_NOTICE){
  644.         if($requestedLogLevel == LOG_ERR$this->errors[$text;
  645.         if !defined('LOG_LEVEL'|| LOG_LEVEL == || ($requestedLogLevel-1>= LOG_LEVEL {
  646.             return;
  647.         }
  648.         if $requestedLogLevel == LOG_ERR {
  649.             $warn_banner 'ERROR: ';
  650.         else if $requestedLogLevel == LOG_WARNING {
  651.             $warn_banner 'WARNING: ';
  652.         else {
  653.             $warn_banner '';
  654.         }
  655.         // Thanks laacz
  656.         $_textToLog date('r')." [".php_uname('n')." ".getmypid()."]"."[$func] ".$warn_banner $text;
  657.         $_logFP fopen(WURFL_LOG_FILE"a+");
  658.         fputs($_logFP$_textToLog."\n");
  659.         fclose($_logFP);
  660.         return(true);
  661.     }
  662.     /**
  663.      * Kills the script on fatal database errors
  664.      * 
  665.      * @access private
  666.      */
  667.     function _dberror(){
  668.         die("Error in query: ".mysql_error($this->dbcon));
  669.     }
  670.     /**
  671.      * This function checks the user agent for signs that it's a WAP device
  672.      * Returns true if a generic ID is found, otherwise false.
  673.      * This is a last resort function that is only called if the device in question
  674.      * does not exist in the WURFL and the class is forced to find another way to
  675.      * identify the device.
  676.      *
  677.      * @param string User agent
  678.      * @access private
  679.      * @return boolean success
  680.      */
  681.     function _getGenericID($_user_agent){
  682.         $this->_toLog('getGenericID'"I couldn't find the device in my list, the headers are my last chance"LOG_NOTICE);
  683.         if strstr($_user_agent'UP.Browser/'&& strstr($_user_agent'(GUI)') ) {
  684.             $this->browser_is_wap = true;
  685.             $this->user_agent $_user_agent;
  686.             $this->wurfl_agent 'upgui_generic';
  687.             $this->id 'upgui_generic';
  688.         else if strstr($_user_agent'UP.Browser/') ) {
  689.             $this->browser_is_wap = true;
  690.             $this->user_agent $_user_agent;
  691.             $this->wurfl_agent 'uptext_generic';
  692.             $this->id 'uptext_generic';
  693.         else if eregi('wml'$this->http_accept|| eregi('wap'$this->http_accept) ) {
  694.             $this->browser_is_wap = true;
  695.             $this->user_agent $_user_agent;
  696.             $this->wurfl_agent 'generic';
  697.             $this->id 'generic';
  698.         else {
  699.             $this->_toLog('getGenericID''This should not be a WAP device, quitting'LOG_NOTICE);
  700.             $this->browser_is_wap=false;
  701.             $this->user_agent $_user_agent;
  702.             $this->wurfl_agent 'generic';
  703.             $this->id 'generic';
  704.             return(false);
  705.         }
  706.         return(true);
  707.     }
  708.     /**
  709.      * Given a string, will escape any unfriendly characters and return
  710.      *     a single quoted string to be used directly in an SQL statement to a
  711.      *     MySQL server.
  712.      * Given a real number it will return the number without quotes so MySQL
  713.      *     sees it as a number instead of a string.
  714.      * Given a null string ('') it will return the MySQL keyword NULL.
  715.      * 
  716.      * Example:  it's a fine day -> 'it\'s a fine day'
  717.      * @param mixed Input variable to be prepared
  718.      * @access private
  719.      */
  720.     function _sqlPrep($value){
  721.         if (get_magic_quotes_gpc()) $value stripslashes($value);
  722.         if($value == ''$value 'NULL';
  723.         else if (!is_numeric($value|| $value[0== '0'$value "'" mysql_real_escape_string($value"'"//Quote if not integer
  724.         return($value);
  725.     }
  726.  
  727. ?>

Documentation generated on Fri, 27 Apr 2007 12:10:18 -0400 by phpDocumentor 1.3.1