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

Source for file UserAgentUtils.php

Documentation is available at UserAgentUtils.php

  1. <?php
  2. /**
  3.  * Tera_WURFL - PHP MySQL driven WURFL
  4.  * 
  5.  * Tera-WURFL was written by Steve Kamerman, and is based on the
  6.  * Java WURFL Evolution package by Luca Passani and WURFL PHP Tools by Andrea Trassati.
  7.  * This version uses a MySQL database to store the entire WURFL file, multiple patch
  8.  * files, and a persistent caching mechanism to provide extreme performance increases.
  9.  * 
  10.  * @package TeraWurfl
  11.  * @author Steve Kamerman <stevekamerman AT gmail.com>
  12.  * @version Stable 2.1.3 $Date: 2010/09/18 15:43:21
  13.  * @license http://www.mozilla.org/MPL/ MPL Vesion 1.1
  14.  */
  15. /**
  16.  * Provides static functions for working with User Agents
  17.  * @package TeraWurfl
  18.  *
  19.  */
  20.     
  21.     public static $WORST_MATCH 7;
  22.     
  23.     public function __construct(){
  24.         
  25.     }
  26.     /**
  27.      * Find the matching Device ID for a given User Agent using RIS (Reduction in String)
  28.      * @param string User Agent
  29.      * @param int How short the strings are allowed to get before a match is abandoned
  30.      * @param UserAgentMatcher The UserAgentMatcher instance that is matching the User Agent
  31.      * @return string WURFL ID
  32.      */
  33.     public static function risMatch($ua,$tolerance,UserAgentMatcher $matcher){
  34.         // PHP RIS Function
  35.         $devices =$matcher->deviceList;
  36.         // Exact match
  37.         $key array_search($ua,$devices);
  38.         if($key !== false){
  39.             return $key;
  40.         }
  41.         // Narrow results to those that match the tolerance level
  42.         $curlen strlen($ua);
  43.         while($curlen >= $tolerance){
  44.             foreach($devices as $testID => $testUA){
  45.                 // Comparing substrings may be faster, but you would need to use strcmp() on the subs anyway,
  46.                 // so this is probably the fastest - maybe preg /^$test/ would be faster???
  47.                 //echo "testUA: $testUA, ua: $ua\n<br/>";
  48.                 if(strpos($testUA,$ua=== 0){
  49.                     return $testID;
  50.                 }
  51.             }
  52.             $ua substr($ua,0,strlen($ua)-1);
  53.             $curlen strlen($ua);
  54.         }
  55.         return WurflConstants::$GENERIC;
  56.     }
  57.     /**
  58.      * Find the matching Device ID for a given User Agent using LD (Leveshtein Distance)
  59.      * @param string User Agent
  60.      * @param int Tolerance that is still considered a match
  61.      * @param UserAgentMatcher The UserAgentMatcher instance that is matching the User Agent
  62.      * @return string WURFL ID
  63.      */
  64.     public static function ldMatch($ua,$tolerance=null,$matcher){
  65.         // PHP Leveshtein Distance Function
  66.         if(is_null($tolerance)){
  67.             $tolerance self::$WORST_MATCH;
  68.         }
  69.         $devices =$matcher->deviceList;
  70.         $key array_search($ua,$devices);
  71.         if($key !== false){
  72.             return $key;
  73.         }
  74.         $best $tolerance;
  75.         $current 0;
  76.         $match WurflConstants::$GENERIC;
  77.         foreach($devices as $testID => $testUA){
  78.             $current levenshtein($ua,$testUA);
  79.             //echo "<hr/>$ua<br/>$testUA<br/>LD: $current<br/>";
  80.             if($current <= $best){
  81.                 $best $current;
  82.                 $match $testID;
  83.             }
  84.         }
  85.         return $match;
  86.     }
  87.     /**
  88.      * Number of slashes ('/') found in the given user agent
  89.      * @param String User Agent
  90.      * @return int Count
  91.      */
  92.     public static function numSlashes($userAgent){
  93.         return substr_count($userAgent,'/');
  94.     }
  95.     /**
  96.      * The character position of the first slash.  If there are no slashes, returns string length
  97.      * @param String User Agent
  98.      * @return int Character position
  99.      */
  100.     public static function firstSlash($userAgent){
  101.         $position strpos($userAgent,'/');
  102.         return ($position!==false)$positionstrlen($userAgent);
  103.     }
  104.     /**
  105.      * The character position of the second slash.  If there is no second slash, returns string length
  106.      * @param String User Agent
  107.      * @return int Character position
  108.      */
  109.     public static function secondSlash($userAgent){
  110.         $first strpos($userAgent,'/');
  111.         $first++;
  112.         $position strpos($userAgent,'/',$first);
  113.         return ($position!==false)$positionstrlen($userAgent);
  114.     }
  115.     /**
  116.      * The character position of the first space.  If there are no spaces, returns string length
  117.      * @param String User Agent
  118.      * @return int Character position
  119.      */
  120.     public static function firstSpace($userAgent){
  121.         $position strpos($userAgent,' ');
  122.         return ($position!==false)$positionstrlen($userAgent);
  123.     }
  124.     /**
  125.      * The character position of the first open parenthisis.  If there are no open parenthisis, returns string length
  126.      * @param String User Agent
  127.      * @return int Character position
  128.      */
  129.     
  130.     public static function firstOpenParen($userAgent){
  131.         $position strpos($userAgent,'(');
  132.         return ($position!==false)$positionstrlen($userAgent);
  133.     }
  134.     /**
  135.      * Removes garbage from user agent string
  136.      * @param String User agent
  137.      * @return String User agent
  138.      */
  139.     public static function cleanUserAgent($ua){
  140.         $ua self::removeUPLinkFromUA($ua);
  141.         // Remove serial number
  142.         $ua preg_replace('/\/SN\d{15}/','/SNXXXXXXXXXXXXXXX',$ua);
  143.         // Remove locale identifier
  144.         $ua preg_replace('/([ ;])[a-zA-Z]{2}-[a-zA-Z]{2}([ ;\)])/','$1xx-xx$2',$ua);
  145.         $ua self::normalizeBlackberry($ua);
  146.         $ua rtrim($ua);
  147.         return $ua;
  148.     }
  149.     /**
  150.      * Normalizes BlackBerry user agent strings
  151.      * @param String User agent
  152.      * @return String User agent
  153.      */
  154.     public static function normalizeBlackberry($ua){
  155.         $pos strpos($ua,'BlackBerry');
  156.         if($pos !== false && $pos 0$ua substr($ua,$pos);
  157.         return $ua;
  158.     }
  159.     /**
  160.      * Removes UP.Link traces from user agent strings
  161.      * @param String User agent
  162.      * @return String User agent
  163.      */
  164.     public static function removeUPLinkFromUA($ua){
  165.         // Remove the gateway signatures from UA (UP.Link/x.x.x)
  166.         $index strpos($ua,'UP.Link');
  167.         if($index===false){
  168.             return $ua;
  169.         }else{
  170.             // Return the UA up to the UP.Link/xxxxxx part
  171.             return substr($ua,0,$index);
  172.         }
  173.     }
  174.     /**
  175.      * Removes Vodafone garbage from user agent string
  176.      * @param String User agent
  177.      * @return String User agent
  178.      */
  179.     public static function removeVodafonePrefix($ua){
  180.         return preg_replace('/^Vodafone\/(\d\.\d\/)?/','',$ua,1);
  181.     }
  182.     /**
  183.      * Check if user agent contains string or array of strings
  184.      * @param String User agent
  185.      * @param Mixed String or Array of strings
  186.      * @return Bool 
  187.      */
  188.     public static function checkIfContains($ua,$find){
  189.         
  190.         if(is_array($find)){
  191.             foreach($find as $part){
  192.                 if(strpos($ua,$part)!==false){
  193.                     return true;
  194.                 }
  195.             }
  196.             return false;
  197.         }else{
  198.             return (strpos($ua,$find)!==false);
  199.         }
  200.     }
  201.     /**
  202.      * Returns the character position (index) of the target string in the given user agent, starting from a given index.  If target is not in user agent, returns length of user agent.
  203.      * @param String User agent
  204.      * @param String Target string to search for
  205.      * @param int Character postition in the user agent at which to start looking for the target
  206.      * @return int Character position (index) or user agent length
  207.      */
  208.     public static function indexOfOrLength($ua$target$startingIndex{
  209.         $length strlen($ua);
  210.         if($startingIndex === false{
  211.             return $length;
  212.         }
  213.         $pos strpos($ua$target$startingIndex);
  214.         return ($pos === false)$length $pos;
  215.     }
  216.     /**
  217.      * The character postition of the Nth occurance of a target string in a user agent
  218.      * @param String User agent
  219.      * @param String Target string to search for in user agent
  220.      * @param int The Nth occurence to find
  221.      * @return int Character position
  222.      */
  223.     public static function ordinalIndexOf($ua$needle$ordinal{
  224.         if (is_null($ua|| empty($ua|| !is_integer($ordinal)){
  225.             return -1;
  226.         }
  227.         $found 0;
  228.         $index = -1;
  229.         do{
  230.             $index strpos($ua$needle$index 1);
  231.             $index is_int($index)$index: -1;
  232.             if ($index 0{
  233.                 return $index;
  234.             }
  235.             $found++;
  236.         }while($found $ordinal);
  237.         return $index;
  238.     
  239.     }
  240.     /**
  241.      * Checks for traces of mobile device signatures and returns an appropriate generic WURFL Device ID
  242.      * @param String User agent
  243.      * @return String WURFL ID
  244.      */
  245.     public static function lastAttempts($ua){
  246.         //before we give up and return generic, one last
  247.         //attempt to catch well-behaved Nokia and Openwave browsers!
  248.         if(self::checkIfContains($ua,'UP.Browser/7'))
  249.             return 'opwv_v7_generic';
  250.         if(self::checkIfContains($ua,'UP.Browser/6'))
  251.             return 'opwv_v6_generic';
  252.         if(self::checkIfContains($ua,'UP.Browser/5'))
  253.             return 'upgui_generic';
  254.         if(self::checkIfContains($ua,'UP.Browser/4'))
  255.             return 'uptext_generic';
  256.         if(self::checkIfContains($ua,'UP.Browser/3'))
  257.             return 'uptext_generic';
  258.         if(self::checkIfContains($ua,'Series60'))
  259.             return 'nokia_generic_series60';
  260.         if(self::checkIfContains($ua,'Mozilla/4.0'))
  261.             return 'generic_web_browser';
  262.         if(self::checkIfContains($ua,'Mozilla/5.0'))
  263.             return 'generic_web_browser';
  264.         if(self::checkIfContains($ua,'Mozilla/6.0'))
  265.             return 'generic_web_browser';
  266.         
  267.         return WurflConstants::$GENERIC;
  268.     }
  269.     /**
  270.      * The given user agent is definitely from a mobile device
  271.      * @param String User agent
  272.      * @return Bool 
  273.      */
  274.     public static function isMobileBrowser($ua){
  275.         $lowerua strtolower($ua);
  276.         if(self::isDesktopBrowser($ua)){
  277.             return false;
  278.         }
  279.         if(UserAgentMatcher::contains($lowerua,WurflConstants::$MOBILE_BROWSERS)) return true;
  280.         if(UserAgentMatcher::regexContains($ua,array(
  281.                 // ARM Processor
  282.                 '/armv[5-9][l0-9]/',
  283.                 // Screen resolution in UA
  284.                 '/[^\d]\d{3}x\d{3}/'
  285.             )
  286.         )){
  287.             return true;
  288.         }
  289.         return false;
  290.     }
  291.     /**
  292.      * The given user agent is definitely from a desktop browser
  293.      * @param String User agent
  294.      * @return Bool 
  295.      */
  296.     public static function isDesktopBrowser($ua){
  297.         $lowerua strtolower($ua);
  298.         foreach(WurflConstants::$DESKTOP_BROWSERS as $browser_signature){
  299.             if(strpos($lowerua$browser_signature!== false){
  300.                 return true;
  301.             }
  302.         }
  303.     }
  304.     /**
  305.      * The given user agent is definitely from a bot/crawler
  306.      * @param String User agent
  307.      * @return Bool 
  308.      */
  309.     public static function isRobot($ua){
  310.         $lowerua strtolower($ua);
  311.         foreach(WurflConstants::$ROBOTS as $browser_signature){
  312.             if(strstr($lowerua$browser_signature)){
  313.                 return true;
  314.             }
  315.         }
  316.         return false;
  317.     }
  318.     public static function LD($s,$t){
  319.         // PHP's levenshtein() function requires arguments to be <= 255 chars
  320.         if(strlen($s255 || strlen($t255){
  321.             return levenshtein(substr($s,0,255),substr($t,0,255));
  322.         }
  323.         return levenshtein($s,$t);
  324.     }
  325. }

Documentation generated on Sun, 19 Sep 2010 00:16:08 +0000 by phpDocumentor 1.4.3