web/lib/Zend/Http/UserAgent/AbstractDevice.php
changeset 886 1e110b03ae96
parent 807 877f952ae2bd
child 1230 68c69c656a2c
equal deleted inserted replaced
885:2251fb41dbc7 886:1e110b03ae96
    13  * to license@zend.com so we can send you a copy immediately.
    13  * to license@zend.com so we can send you a copy immediately.
    14  *
    14  *
    15  * @category   Zend
    15  * @category   Zend
    16  * @package    Zend_Http
    16  * @package    Zend_Http
    17  * @subpackage UserAgent
    17  * @subpackage UserAgent
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
    18  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    20  */
    20  */
    21 
    21 
    22 require_once 'Zend/Http/UserAgent/Device.php';
    22 require_once 'Zend/Http/UserAgent/Device.php';
    23 
    23 
    25  * Abstract Class to define a browser device.
    25  * Abstract Class to define a browser device.
    26  *
    26  *
    27  * @category   Zend
    27  * @category   Zend
    28  * @package    Zend_Http
    28  * @package    Zend_Http
    29  * @subpackage UserAgent
    29  * @subpackage UserAgent
    30  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
    30  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
    31  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    31  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    32  */
    32  */
    33 abstract class Zend_Http_UserAgent_AbstractDevice
    33 abstract class Zend_Http_UserAgent_AbstractDevice
    34     implements Zend_Http_UserAgent_Device
    34     implements Zend_Http_UserAgent_Device
    35 {
    35 {
    47      */
    47      */
    48     protected $_browserVersion = '';
    48     protected $_browserVersion = '';
    49 
    49 
    50     /**
    50     /**
    51      * Configuration
    51      * Configuration
    52      * 
    52      *
    53      * @var array
    53      * @var array
    54      */
    54      */
    55     protected $_config;
    55     protected $_config;
    56 
    56 
    57     /**
    57     /**
    61      */
    61      */
    62     protected $_userAgent;
    62     protected $_userAgent;
    63 
    63 
    64     /**
    64     /**
    65      * Server variable
    65      * Server variable
    66      * 
    66      *
    67      * @var array
    67      * @var array
    68      */
    68      */
    69     protected $_server;
    69     protected $_server;
    70 
    70 
    71     /**
    71     /**
    72      * Image types
    72      * Image types
    73      * 
    73      *
    74      * @var array
    74      * @var array
    75      */
    75      */
    76     protected $_images = array(
    76     protected $_images = array(
    77         'jpeg', 
    77         'jpeg',
    78         'gif', 
    78         'gif',
    79         'png', 
    79         'png',
    80         'pjpeg', 
    80         'pjpeg',
    81         'x-png', 
    81         'x-png',
    82         'bmp',
    82         'bmp',
    83     );
    83     );
    84 
    84 
    85     /**
    85     /**
    86      * Browser/Device features
    86      * Browser/Device features
    98 
    98 
    99     /**
    99     /**
   100      * Constructor
   100      * Constructor
   101      *
   101      *
   102      * @param  null|string|array $userAgent If array, restores from serialized version
   102      * @param  null|string|array $userAgent If array, restores from serialized version
   103      * @param  array $server 
   103      * @param  array $server
   104      * @param  array $config 
   104      * @param  array $config
   105      * @return void
   105      * @return void
   106      */
   106      */
   107     public function __construct($userAgent = null, array $server = array(), array $config = array())
   107     public function __construct($userAgent = null, array $server = array(), array $config = array())
   108     {
   108     {
   109         if (is_array($userAgent)) {
   109         if (is_array($userAgent)) {
   119         }
   119         }
   120     }
   120     }
   121 
   121 
   122     /**
   122     /**
   123      * Serialize object
   123      * Serialize object
   124      * 
   124      *
   125      * @return string
   125      * @return string
   126      */
   126      */
   127     public function serialize()
   127     public function serialize()
   128     {
   128     {
   129         $spec = array(
   129         $spec = array(
   137         return serialize($spec);
   137         return serialize($spec);
   138     }
   138     }
   139 
   139 
   140     /**
   140     /**
   141      * Unserialize
   141      * Unserialize
   142      * 
   142      *
   143      * @param  string $serialized 
   143      * @param  string $serialized
   144      * @return void
   144      * @return void
   145      */
   145      */
   146     public function unserialize($serialized)
   146     public function unserialize($serialized)
   147     {
   147     {
   148         $spec = unserialize($serialized);
   148         $spec = unserialize($serialized);
   149         $this->_restoreFromArray($spec);
   149         $this->_restoreFromArray($spec);
   150     }
   150     }
   151 
   151 
   152     /**
   152     /**
   153      * Restore object state from array
   153      * Restore object state from array
   154      * 
   154      *
   155      * @param  array $spec 
   155      * @param  array $spec
   156      * @return void
   156      * @return void
   157      */
   157      */
   158     protected function _restoreFromArray(array $spec)
   158     protected function _restoreFromArray(array $spec)
   159     {
   159     {
   160         foreach ($spec as $key => $value) {
   160         foreach ($spec as $key => $value) {
   174         $features = $this->_loadFeaturesAdapter();
   174         $features = $this->_loadFeaturesAdapter();
   175 
   175 
   176         if (is_array($features)) {
   176         if (is_array($features)) {
   177             $this->_aFeatures = array_merge($this->_aFeatures, $features);
   177             $this->_aFeatures = array_merge($this->_aFeatures, $features);
   178         }
   178         }
   179         
   179 
   180         return $this->_aFeatures;
   180         return $this->_aFeatures;
   181     }
   181     }
   182 
   182 
   183     /**
   183     /**
   184      * Gets the browser type identifier
   184      * Gets the browser type identifier
   193      * @param  string $feature The feature to check.
   193      * @param  string $feature The feature to check.
   194      * @return bool
   194      * @return bool
   195      */
   195      */
   196     public function hasFeature($feature)
   196     public function hasFeature($feature)
   197     {
   197     {
   198         return (!empty($this->_aFeatures[$feature]));
   198         return (isset($this->_aFeatures[$feature]) && !is_null($this->_aFeatures[$feature]));
   199     }
   199     }
   200 
   200 
   201     /**
   201     /**
   202      * Gets the value of the current browser/device feature
   202      * Gets the value of the current browser/device feature
   203      *
   203      *
   284      * @return void
   284      * @return void
   285      */
   285      */
   286     protected function _getDefaultFeatures()
   286     protected function _getDefaultFeatures()
   287     {
   287     {
   288         $server = array();
   288         $server = array();
   289         
   289 
   290         // gets info from user agent chain 
   290         // gets info from user agent chain
   291         $uaExtract = $this->extractFromUserAgent($this->getUserAgent());
   291         $uaExtract = $this->extractFromUserAgent($this->getUserAgent());
   292         
   292 
   293         if (is_array($uaExtract)) {
   293         if (is_array($uaExtract)) {
   294             foreach ($uaExtract as $key => $info) {
   294             foreach ($uaExtract as $key => $info) {
   295                 $this->setFeature($key, $info, 'product_info');
   295                 $this->setFeature($key, $info, 'product_info');
   296             }
   296             }
   297         }
   297         }
   298         
   298 
   299         if (isset($uaExtract['browser_name'])) {
   299         if (isset($uaExtract['browser_name'])) {
   300             $this->_browser = $uaExtract['browser_name'];
   300             $this->_browser = $uaExtract['browser_name'];
   301         }
   301         }
   302         if (isset($uaExtract['browser_version'])) {
   302         if (isset($uaExtract['browser_version'])) {
   303             $this->_browserVersion = $uaExtract['browser_version'];
   303             $this->_browserVersion = $uaExtract['browser_version'];
   304         }
   304         }
   305         if (isset($uaExtract['device_os'])) {
   305         if (isset($uaExtract['device_os'])) {
   306             $this->device_os = $uaExtract['device_os_name'];
   306             $this->device_os = $uaExtract['device_os_name'];
   307         }
   307         }
   308         
   308 
   309         /* browser & device info */
   309         /* browser & device info */
   310         $this->setFeature('is_wireless_device', false, 'product_info');
   310         $this->setFeature('is_wireless_device', false, 'product_info');
   311         $this->setFeature('is_mobile', false, 'product_info');
   311         $this->setFeature('is_mobile', false, 'product_info');
   312         $this->setFeature('is_desktop', false, 'product_info');
   312         $this->setFeature('is_desktop', false, 'product_info');
   313         $this->setFeature('is_tablet', false, 'product_info');
   313         $this->setFeature('is_tablet', false, 'product_info');
   314         $this->setFeature('is_bot', false, 'product_info');
   314         $this->setFeature('is_bot', false, 'product_info');
   315         $this->setFeature('is_email', false, 'product_info');
   315         $this->setFeature('is_email', false, 'product_info');
   316         $this->setFeature('is_text', false, 'product_info');
   316         $this->setFeature('is_text', false, 'product_info');
   317         $this->setFeature('device_claims_web_support', false, 'product_info');
   317         $this->setFeature('device_claims_web_support', false, 'product_info');
   318         
   318 
   319         $this->setFeature('is_' . strtolower($this->getType()), true, 'product_info');
   319         $this->setFeature('is_' . strtolower($this->getType()), true, 'product_info');
   320         
   320 
   321         /* sets the browser name */
   321         /* sets the browser name */
   322         if (isset($this->list) && empty($this->_browser)) {
   322         if (isset($this->list) && empty($this->_browser)) {
   323             $lowerUserAgent = strtolower($this->getUserAgent());
   323             $lowerUserAgent = strtolower($this->getUserAgent());
   324             foreach ($this->list as $browser_signature) {
   324             foreach ($this->list as $browser_signature) {
   325                 if (strpos($lowerUserAgent, $browser_signature) !== false) {
   325                 if (strpos($lowerUserAgent, $browser_signature) !== false) {
   326                     $this->_browser = strtolower($browser_signature);
   326                     $this->_browser = strtolower($browser_signature);
   327                     $this->setFeature('browser_name', $this->_browser, 'product_info');
   327                     $this->setFeature('browser_name', $this->_browser, 'product_info');
   328                 }
   328                 }
   329             }
   329             }
   330         }
   330         }
   331         
   331 
   332         /* sets the client IP */
   332         /* sets the client IP */
   333         if (isset($this->_server['remote_addr'])) {
   333         if (isset($this->_server['remote_addr'])) {
   334             $this->setFeature('client_ip', $this->_server['remote_addr'], 'product_info');
   334             $this->setFeature('client_ip', $this->_server['remote_addr'], 'product_info');
   335         } elseif (isset($this->_server['http_x_forwarded_for'])) {
   335         } elseif (isset($this->_server['http_x_forwarded_for'])) {
   336             $this->setFeature('client_ip', $this->_server['http_x_forwarded_for'], 'product_info');
   336             $this->setFeature('client_ip', $this->_server['http_x_forwarded_for'], 'product_info');
   337         } elseif (isset($this->_server['http_client_ip'])) {
   337         } elseif (isset($this->_server['http_client_ip'])) {
   338             $this->setFeature('client_ip', $this->_server['http_client_ip'], 'product_info');
   338             $this->setFeature('client_ip', $this->_server['http_client_ip'], 'product_info');
   339         }
   339         }
   340         
   340 
   341         /* sets the server infos */
   341         /* sets the server infos */
   342         if (isset($this->_server['server_software'])) {
   342         if (isset($this->_server['server_software'])) {
   343             if (strpos($this->_server['server_software'], 'Apache') !== false || strpos($this->_server['server_software'], 'LiteSpeed') !== false) {
   343             if (strpos($this->_server['server_software'], 'Apache') !== false || strpos($this->_server['server_software'], 'LiteSpeed') !== false) {
   344                 $server['version'] = 1;
   344                 $server['version'] = 1;
   345                 if (strpos($this->_server['server_software'], 'Apache/2') !== false) {
   345                 if (strpos($this->_server['server_software'], 'Apache/2') !== false) {
   346                     $server['version'] = 2;
   346                     $server['version'] = 2;
   347                 }
   347                 }
   348                 $server['server'] = 'apache';
   348                 $server['server'] = 'apache';
   349             }
   349             }
   350             
   350 
   351             if (strpos($this->_server['server_software'], 'Microsoft-IIS') !== false) {
   351             if (strpos($this->_server['server_software'], 'Microsoft-IIS') !== false) {
   352                 $server['server'] = 'iis';
   352                 $server['server'] = 'iis';
   353             }
   353             }
   354             
   354 
   355             if (strpos($this->_server['server_software'], 'Unix') !== false) {
   355             if (strpos($this->_server['server_software'], 'Unix') !== false) {
   356                 $server['os'] = 'unix';
   356                 $server['os'] = 'unix';
   357                 if (isset($_ENV['MACHTYPE'])) {
   357                 if (isset($_ENV['MACHTYPE'])) {
   358                     if (strpos($_ENV['MACHTYPE'], 'linux') !== false) {
   358                     if (strpos($_ENV['MACHTYPE'], 'linux') !== false) {
   359                         $server['os'] = 'linux';
   359                         $server['os'] = 'linux';
   360                     }
   360                     }
   361                 }
   361                 }
   362             } elseif (strpos($this->_server['server_software'], 'Win') !== false) {
   362             } elseif (strpos($this->_server['server_software'], 'Win') !== false) {
   363                 $server['os'] = 'windows';
   363                 $server['os'] = 'windows';
   364             }
   364             }
   365             
   365 
   366             if (preg_match('/Apache\/([0-9\.]*)/', $this->_server['server_software'], $arr)) {
   366             if (preg_match('/Apache\/([0-9\.]*)/', $this->_server['server_software'], $arr)) {
   367                 if ($arr[1]) {
   367                 if ($arr[1]) {
   368                     $server['version'] = $arr[1];
   368                     $server['version'] = $arr[1];
   369                     $server['server']  = 'apache';
   369                     $server['server']  = 'apache';
   370                 }
   370                 }
   371             }
   371             }
   372         }
   372         }
   373         
   373 
   374         $this->setFeature('php_version', phpversion(), 'server_info');
   374         $this->setFeature('php_version', phpversion(), 'server_info');
   375         if (isset($server['server'])) {
   375         if (isset($server['server'])) {
   376             $this->setFeature('server_os', $server['server'], 'server_info');
   376             $this->setFeature('server_os', $server['server'], 'server_info');
   377         }
   377         }
   378         if (isset($server['version'])) {
   378         if (isset($server['version'])) {
   399      * @return array
   399      * @return array
   400      */
   400      */
   401     public static function extractFromUserAgent($userAgent)
   401     public static function extractFromUserAgent($userAgent)
   402     {
   402     {
   403         $userAgent = trim($userAgent);
   403         $userAgent = trim($userAgent);
   404         
   404 
   405         /**
   405         /**
   406          * @see http://www.texsoft.it/index.php?c=software&m=sw.php.useragent&l=it
   406          * @see http://www.texsoft.it/index.php?c=software&m=sw.php.useragent&l=it
   407          */
   407          */
   408         $pattern =  "(([^/\s]*)(/(\S*))?)(\s*\[[a-zA-Z][a-zA-Z]\])?\s*(\\((([^()]|(\\([^()]*\\)))*)\\))?\s*";
   408         $pattern =  "(([^/\s]*)(/(\S*))?)(\s*\[[a-zA-Z][a-zA-Z]\])?\s*(\\((([^()]|(\\([^()]*\\)))*)\\))?\s*";
   409         preg_match("#^$pattern#", $userAgent, $match);
   409         preg_match("#^$pattern#", $userAgent, $match);
   410 
   410 
   411         $comment = array();
   411         $comment = array();
   412         if (isset($match[7])) {
   412         if (isset($match[7])) {
   413             $comment = explode(';', $match[7]);
   413             $comment = explode(';', $match[7]);
   414         }
   414         }
   415         
   415 
   416         // second part if exists
   416         // second part if exists
   417         $end = substr($userAgent, strlen($match[0]));
   417         $end = substr($userAgent, strlen($match[0]));
   418         if (!empty($end)) {
   418         if (!empty($end)) {
   419             $result['others']['full'] = $end;
   419             $result['others']['full'] = $end;
   420         }
   420         }
   421         
   421 
   422         $match2 = array();
   422         $match2 = array();
   423         if (isset($result['others'])) {
   423         if (isset($result['others'])) {
   424             preg_match_all('/(([^\/\s]*)(\/)?([^\/\(\)\s]*)?)(\s\((([^\)]*)*)\))?/i', $result['others']['full'], $match2);
   424             preg_match_all('/(([^\/\s]*)(\/)?([^\/\(\)\s]*)?)(\s\((([^\)]*)*)\))?/i', $result['others']['full'], $match2);
   425         }
   425         }
   426         $result['user_agent']   = trim($match[1]);
   426         $result['user_agent']   = trim($match[1]);
   449             $i = 0;
   449             $i = 0;
   450             $max = count($match2[0]);
   450             $max = count($match2[0]);
   451             for ($i = 0; $i < $max; $i ++) {
   451             for ($i = 0; $i < $max; $i ++) {
   452                 if (!empty($match2[0][$i])) {
   452                 if (!empty($match2[0][$i])) {
   453                     $result['others']['detail'][] = array(
   453                     $result['others']['detail'][] = array(
   454                         $match2[0][$i], 
   454                         $match2[0][$i],
   455                         $match2[2][$i], 
   455                         $match2[2][$i],
   456                         $match2[4][$i],
   456                         $match2[4][$i],
   457                     );
   457                     );
   458                 }
   458                 }
   459             }
   459             }
   460         }
   460         }
   461         
   461 
   462         /** Security level */
   462         /** Security level */
   463         $security = array(
   463         $security = array(
   464             'N' => 'no security', 
   464             'N' => 'no security',
   465             'U' => 'strong security', 
   465             'U' => 'strong security',
   466             'I' => 'weak security',
   466             'I' => 'weak security',
   467         );
   467         );
   468         if (!empty($result['browser_token'])) {
   468         if (!empty($result['browser_token'])) {
   469             if (isset($security[$result['browser_token']])) {
   469             if (isset($security[$result['browser_token']])) {
   470                 $result['security_level'] = $security[$result['browser_token']];
   470                 $result['security_level'] = $security[$result['browser_token']];
   471                 unset($result['browser_token']);
   471                 unset($result['browser_token']);
   472             }
   472             }
   473         }
   473         }
   474         
   474 
   475         $product = strtolower($result['browser_name']);
   475         $product = strtolower($result['browser_name']);
   476         
   476 
   477         // Mozilla : true && false
   477         // Mozilla : true && false
   478         $compatibleOrIe = false;
   478         $compatibleOrIe = false;
   479         if (isset($result['compatibility_flag']) && isset($result['comment'])) {
   479         if (isset($result['compatibility_flag']) && isset($result['comment'])) {
   480             $compatibleOrIe = ($result['compatibility_flag'] == 'compatible' || strpos($result['comment']['full'], "MSIE") !== false);
   480             $compatibleOrIe = ($result['compatibility_flag'] == 'compatible' || strpos($result['comment']['full'], "MSIE") !== false);
   481         }
   481         }
   490                         $real[0][1]               = trim($v);
   490                         $real[0][1]               = trim($v);
   491                         $result['browser_engine'] = "MSIE";
   491                         $result['browser_engine'] = "MSIE";
   492                         $real[1][0]               = "Internet Explorer";
   492                         $real[1][0]               = "Internet Explorer";
   493                         $temp                     = explode(' ', trim($v));
   493                         $temp                     = explode(' ', trim($v));
   494                         $real[3][0]               = $temp[1];
   494                         $real[3][0]               = $temp[1];
   495                     
   495 
   496                     }
   496                     }
   497                     if (strpos($v, 'Win') !== false) {
   497                     if (strpos($v, 'Win') !== false) {
   498                         $result['device_os_token'] = trim($v);
   498                         $result['device_os_token'] = trim($v);
   499                     }
   499                     }
   500                 }
   500                 }
   501             }
   501             }
   502             
   502 
   503             if (!empty($real[0])) {
   503             if (!empty($real[0])) {
   504                 $result['browser_name']    = $real[1][0];
   504                 $result['browser_name']    = $real[1][0];
   505                 $result['browser_version'] = $real[3][0];
   505                 $result['browser_version'] = $real[3][0];
   506             } else {
   506             } else {
   507                 $result['browser_name']    = $result['browser_token'];
   507                 if(isset($result['browser_token'])) {
       
   508                     $result['browser_name']    = $result['browser_token'];
       
   509                 }
   508                 $result['browser_version'] = '??';
   510                 $result['browser_version'] = '??';
   509             }
   511             }
   510         } elseif ($product == 'mozilla' && $result['browser_version'] < 5.0) {
   512         } elseif ($product == 'mozilla' && $result['browser_version'] < 5.0) {
   511             // handles the real Mozilla (or old Netscape if version < 5.0)
   513             // handles the real Mozilla (or old Netscape if version < 5.0)
   512             $result['browser_name'] = 'Netscape';
   514             $result['browser_name'] = 'Netscape';
   513         }
   515         }
   514         
   516 
   515         /** windows */
   517         /** windows */
   516         if ($result['browser_name'] == 'MSIE') {
   518         if ($result['browser_name'] == 'MSIE') {
   517             $result['browser_engine'] = 'MSIE';
   519             $result['browser_engine'] = 'MSIE';
   518             $result['browser_name']   = 'Internet Explorer';
   520             $result['browser_name']   = 'Internet Explorer';
   519         }
   521         }
   520         if (isset($result['device_os_token'])) {
   522         if (isset($result['device_os_token'])) {
   521             if (strpos($result['device_os_token'], 'Win') !== false) {
   523             if (strpos($result['device_os_token'], 'Win') !== false) {
   522                 
   524 
   523                 $windows = array(
   525                 $windows = array(
   524                     'Windows NT 6.1'          => 'Windows 7', 
   526                     'Windows NT 6.1'          => 'Windows 7',
   525                     'Windows NT 6.0'          => 'Windows Vista', 
   527                     'Windows NT 6.0'          => 'Windows Vista',
   526                     'Windows NT 5.2'          => 'Windows Server 2003', 
   528                     'Windows NT 5.2'          => 'Windows Server 2003',
   527                     'Windows NT 5.1'          => 'Windows XP', 
   529                     'Windows NT 5.1'          => 'Windows XP',
   528                     'Windows NT 5.01'         => 'Windows 2000 SP1', 
   530                     'Windows NT 5.01'         => 'Windows 2000 SP1',
   529                     'Windows NT 5.0'          => 'Windows 2000', 
   531                     'Windows NT 5.0'          => 'Windows 2000',
   530                     'Windows NT 4.0'          => 'Microsoft Windows NT 4.0', 
   532                     'Windows NT 4.0'          => 'Microsoft Windows NT 4.0',
   531                     'WinNT'                   => 'Microsoft Windows NT 4.0', 
   533                     'WinNT'                   => 'Microsoft Windows NT 4.0',
   532                     'Windows 98; Win 9x 4.90' => 'Windows Me', 
   534                     'Windows 98; Win 9x 4.90' => 'Windows Me',
   533                     'Windows 98'              => 'Windows 98', 
   535                     'Windows 98'              => 'Windows 98',
   534                     'Win98'                   => 'Windows 98', 
   536                     'Win98'                   => 'Windows 98',
   535                     'Windows 95'              => 'Windows 95', 
   537                     'Windows 95'              => 'Windows 95',
   536                     'Win95'                   => 'Windows 95', 
   538                     'Win95'                   => 'Windows 95',
   537                     'Windows CE'              => 'Windows CE',
   539                     'Windows CE'              => 'Windows CE',
   538                 );
   540                 );
   539                 if (isset($windows[$result['device_os_token']])) {
   541                 if (isset($windows[$result['device_os_token']])) {
   540                     $result['device_os_name'] = $windows[$result['device_os_token']];
   542                     $result['device_os_name'] = $windows[$result['device_os_token']];
   541                 } else {
   543                 } else {
   542                     $result['device_os_name'] = $result['device_os_token'];
   544                     $result['device_os_name'] = $result['device_os_token'];
   543                 }
   545                 }
   544             }
   546             }
   545         }
   547         }
   546         
   548 
   547         // iphone 
   549         // iphone
   548         $apple_device = array(
   550         $apple_device = array(
   549             'iPhone', 
   551             'iPhone',
   550             'iPod', 
   552             'iPod',
   551             'iPad',
   553             'iPad',
   552         );
   554         );
   553         if (isset($result['compatibility_flag'])) {
   555         if (isset($result['compatibility_flag'])) {
   554             if (in_array($result['compatibility_flag'], $apple_device)) {
   556             if (in_array($result['compatibility_flag'], $apple_device)) {
   555                 $result['device']           = strtolower($result['compatibility_flag']);
   557                 $result['device']           = strtolower($result['compatibility_flag']);
   556                 $result['device_os_token']  = 'iPhone OS';
   558                 $result['device_os_token']  = 'iPhone OS';
   557                 $result['browser_language'] = trim($comment[3]);
   559                 if (isset($comment[3])) {
   558                 $result['browser_version']  = $result['others']['detail'][1][2];
   560                     $result['browser_language'] = trim($comment[3]);
       
   561                 }
       
   562                 if (isset($result['others']['detail'][1])) {
       
   563                     $result['browser_version']  = $result['others']['detail'][1][2];
       
   564                 } elseif (isset($result['others']['detail']) && count($result['others']['detail'])) {
       
   565                     $result['browser_version']  = $result['others']['detail'][0][2];
       
   566                 }
   559                 if (!empty($result['others']['detail'][2])) {
   567                 if (!empty($result['others']['detail'][2])) {
   560                     $result['firmware'] = $result['others']['detail'][2][2];
   568                     $result['firmware'] = $result['others']['detail'][2][2];
   561                 }
   569                 }
   562                 if (!empty($result['others']['detail'][3])) {
   570                 if (!empty($result['others']['detail'][3])) {
   563                     $result['browser_name']  = $result['others']['detail'][3][1];
   571                     $result['browser_name']  = $result['others']['detail'][3][1];
   564                     $result['browser_build'] = $result['others']['detail'][3][2];
   572                     $result['browser_build'] = $result['others']['detail'][3][2];
   565                 }
   573                 }
   566             }
   574             }
   567         }
   575         }
   568         
   576 
   569         // Safari
   577         // Safari
   570         if (isset($result['others'])) {
   578         if (isset($result['others'])) {
   571             if ($result['others']['detail'][0][1] == 'AppleWebKit') {
   579             if ($result['others']['detail'][0][1] == 'AppleWebKit') {
   572                 $result['browser_engine'] = 'AppleWebKit';
   580                 $result['browser_engine'] = 'AppleWebKit';
   573                 if ($result['others']['detail'][1][1] == 'Version') {
   581                 if (isset($result['others']['detail'][1]) && $result['others']['detail'][1][1] == 'Version') {
   574                     $result['browser_version'] = $result['others']['detail'][1][2];
   582                     $result['browser_version'] = $result['others']['detail'][1][2];
   575                 } else {
   583                 } else {
   576                     $result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][2];
   584                     $result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][2];
   577                 }
   585                 }
   578                 if (isset($comment[3])) {
   586                 if (isset($comment[3])) {
   579                      $result['browser_language'] = trim($comment[3]);
   587                      $result['browser_language'] = trim($comment[3]);
   580                 }
   588                 }
   581                 
   589 
   582                 $last = $result['others']['detail'][count($result['others']['detail']) - 1][1];
   590                 $last = $result['others']['detail'][count($result['others']['detail']) - 1][1];
   583                 
   591 
   584                 if (empty($result['others']['detail'][2][1]) || $result['others']['detail'][2][1] == 'Safari') {
   592                 if (empty($result['others']['detail'][2][1]) || $result['others']['detail'][2][1] == 'Safari') {
   585                     $result['browser_name']    = ($result['others']['detail'][1][1] && $result['others']['detail'][1][1] != 'Version' ? $result['others']['detail'][1][1] : 'Safari');
   593                     if (isset($result['others']['detail'][1])) {
   586                     $result['browser_version'] = ($result['others']['detail'][1][2] ? $result['others']['detail'][1][2] : $result['others']['detail'][0][2]);
   594                         $result['browser_name']    = ($result['others']['detail'][1][1] && $result['others']['detail'][1][1] != 'Version' ? $result['others']['detail'][1][1] : 'Safari');
       
   595                         $result['browser_version'] = ($result['others']['detail'][1][2] ? $result['others']['detail'][1][2] : $result['others']['detail'][0][2]);
       
   596                     } else {
       
   597                         $result['browser_name']    = ($result['others']['detail'][0][1] && $result['others']['detail'][0][1] != 'Version' ? $result['others']['detail'][0][1] : 'Safari');
       
   598                         $result['browser_version'] = $result['others']['detail'][0][2];
       
   599                     }
   587                 } else {
   600                 } else {
   588                     $result['browser_name']    = $result['others']['detail'][2][1];
   601                     $result['browser_name']    = $result['others']['detail'][2][1];
   589                     $result['browser_version'] = $result['others']['detail'][2][2];
   602                     $result['browser_version'] = $result['others']['detail'][2][2];
   590                     
   603 
   591                     // mobile version
   604                     // mobile version
   592                     if ($result['browser_name'] == 'Mobile') {
   605                     if ($result['browser_name'] == 'Mobile') {
   593                         $result['browser_name'] = 'Safari ' . $result['browser_name'];
   606                         $result['browser_name'] = 'Safari ' . $result['browser_name'];
   594                         if ($result['others']['detail'][1][1] == 'Version') {
   607                         if ($result['others']['detail'][1][1] == 'Version') {
   595                             $result['browser_version'] = $result['others']['detail'][1][2];
   608                             $result['browser_version'] = $result['others']['detail'][1][2];
   596                         }
   609                         }
   597                     }
   610                     }
   598                 }
   611                 }
   599                 
   612 
   600                 // For Safari < 2.2, AppleWebKit version gives the Safari version
   613                 // For Safari < 2.2, AppleWebKit version gives the Safari version
   601                 if (strpos($result['browser_version'], '.') > 2 || (int) $result['browser_version'] > 20) {
   614                 if (strpos($result['browser_version'], '.') > 2 || (int) $result['browser_version'] > 20) {
   602                     $temp = explode('.', $result['browser_version']);
   615                     $temp = explode('.', $result['browser_version']);
   603                     $build = (int) $temp[0];
   616                     $build = (int) $temp[0];
   604                     $awkVersion = array(
   617                     $awkVersion = array(
   605                         48  => '0.8', 
   618                         48  => '0.8',
   606                         73  => '0.9', 
   619                         73  => '0.9',
   607                         85  => '1.0', 
   620                         85  => '1.0',
   608                         103 => '1.1', 
   621                         103 => '1.1',
   609                         124 => '1.2', 
   622                         124 => '1.2',
   610                         300 => '1.3', 
   623                         300 => '1.3',
   611                         400 => '2.0',
   624                         400 => '2.0',
   612                     );
   625                     );
   613                     foreach ($awkVersion as $k => $v) {
   626                     foreach ($awkVersion as $k => $v) {
   614                         if ($build >= $k) {
   627                         if ($build >= $k) {
   615                             $result['browser_version'] = $v;
   628                             $result['browser_version'] = $v;
   616                         }
   629                         }
   617                     }
   630                     }
   618                 }
   631                 }
   619             }
   632             }
   620             
   633 
   621             // Gecko (Firefox or compatible)
   634             // Gecko (Firefox or compatible)
   622             if ($result['others']['detail'][0][1] == 'Gecko') {
   635             if ($result['others']['detail'][0][1] == 'Gecko') {
   623                 $searchRV = true;
   636                 $searchRV = true;
   624                 if (!empty($result['others']['detail'][1][1]) && !empty($result['others']['detail'][count($result['others']['detail']) - 1][2]) || strpos(strtolower($result['others']['full']), 'opera') !== false) {
   637                 if (!empty($result['others']['detail'][1][1]) && !empty($result['others']['detail'][count($result['others']['detail']) - 1][2]) || strpos(strtolower($result['others']['full']), 'opera') !== false) {
   625                     $searchRV = false;
   638                     $searchRV = false;
   626                     $result['browser_engine'] = $result['others']['detail'][0][1];
   639                     $result['browser_engine'] = $result['others']['detail'][0][1];
   627                     
   640 
   628                     // the name of the application is at the end indepenently 
   641                     // the name of the application is at the end indepenently
   629                     // of quantity of information in $result['others']['detail']
   642                     // of quantity of information in $result['others']['detail']
   630                     $last = count($result['others']['detail']) - 1;
   643                     $last = count($result['others']['detail']) - 1;
   631                     
   644 
   632                     // exception : if the version of the last information is 
   645                     // exception : if the version of the last information is
   633                     // empty we take the previous one
   646                     // empty we take the previous one
   634                     if (empty($result['others']['detail'][$last][2])) {
   647                     if (empty($result['others']['detail'][$last][2])) {
   635                         $last --;
   648                         $last --;
   636                     }
   649                     }
   637                     
   650 
   638                     // exception : if the last one is 'Red Hat' or 'Debian' => 
   651                     // exception : if the last one is 'Red Hat' or 'Debian' =>
   639                     // use rv: to find browser_version */
   652                     // use rv: to find browser_version */
   640                     if (in_array($result['others']['detail'][$last][1], array(
   653                     if (in_array($result['others']['detail'][$last][1], array(
   641                         'Debian', 
   654                         'Debian',
   642                         'Hat',
   655                         'Hat',
   643                     ))) {
   656                     ))) {
   644                         $searchRV = true;
   657                         $searchRV = true;
   645                     }
   658                     }
   646                     $result['browser_name']    = $result['others']['detail'][$last][1];
   659                     $result['browser_name']    = $result['others']['detail'][$last][1];
   647                     $result['browser_version'] = $result['others']['detail'][$last][2];
   660                     $result['browser_version'] = $result['others']['detail'][$last][2];
   648                     if (isset($comment[4])) {
   661                     if (isset($comment[4])) {
   649                         $result['browser_build'] = trim($comment[4]);
   662                         $result['browser_build'] = trim($comment[4]);
   650                     }
   663                     }
   651                     $result['browser_language'] = trim($comment[3]);
   664                     if (isset($comment[3])) {
   652                     
   665                         $result['browser_language'] = trim($comment[3]);
       
   666                     }
       
   667 
   653                     // Netscape
   668                     // Netscape
   654                     if ($result['browser_name'] == 'Navigator' || $result['browser_name'] == 'Netscape6') {
   669                     if ($result['browser_name'] == 'Navigator' || $result['browser_name'] == 'Netscape6') {
   655                         $result['browser_name'] = 'Netscape';
   670                         $result['browser_name'] = 'Netscape';
   656                     }
   671                     }
   657                 }
   672                 }
   665                             }
   680                             }
   666                         }
   681                         }
   667                     }
   682                     }
   668                 }
   683                 }
   669             }
   684             }
   670             
   685 
   671             // Netscape
   686             // Netscape
   672             if ($result['others']['detail'][0][1] == 'Netscape') {
   687             if ($result['others']['detail'][0][1] == 'Netscape') {
   673                 $result['browser_name']    = 'Netscape';
   688                 $result['browser_name']    = 'Netscape';
   674                 $result['browser_version'] = $result['others']['detail'][0][2];
   689                 $result['browser_version'] = $result['others']['detail'][0][2];
   675             }
   690             }
   676             
   691 
   677             // Opera 
   692             // Opera
   678             // Opera: engine Presto
   693             // Opera: engine Presto
   679             if ($result['others']['detail'][0][1] == 'Presto') {
   694             if ($result['others']['detail'][0][1] == 'Presto') {
   680                 $result['browser_engine'] = 'Presto';
   695                 $result['browser_engine'] = 'Presto';
   681                 if (!empty($result['others']['detail'][1][2])) {
   696                 if (!empty($result['others']['detail'][1][2])) {
   682                     $result['browser_version'] = $result['others']['detail'][1][2];
   697                     $result['browser_version'] = $result['others']['detail'][1][2];
   683                 }
   698                 }
   684             }
   699             }
   685             
   700 
   686             // UA ends with 'Opera X.XX'
   701             // UA ends with 'Opera X.XX' or 'Opera/X.XX'
   687             if ($result['others']['detail'][0][1] == 'Opera') {
   702             if ($result['others']['detail'][0][1] == 'Opera') {
   688                 $result['browser_name']    = $result['others']['detail'][0][1];
   703                 $result['browser_name']    = $result['others']['detail'][0][1];
   689                 $result['browser_version'] = $result['others']['detail'][1][1];
   704                 // Opera X.XX
   690             }
   705                 if (isset($result['others']['detail'][1][1])) {
   691             
   706                     $result['browser_version'] = $result['others']['detail'][1][1];
       
   707                 // Opera/X.XX
       
   708                 } elseif (isset($result['others']['detail'][0][2])) {
       
   709                     $result['browser_version'] = $result['others']['detail'][0][2];
       
   710                 }
       
   711             }
       
   712 
   692             // Opera Mini
   713             // Opera Mini
   693             if (isset($result["browser_token"])) {
   714             if (isset($result["browser_token"])) {
   694                 if (strpos($result["browser_token"], 'Opera Mini') !== false) {
   715                 if (strpos($result["browser_token"], 'Opera Mini') !== false) {
   695                     $result['browser_name'] = 'Opera Mini';
   716                     $result['browser_name'] = 'Opera Mini';
   696                 }
   717                 }
   697             }
   718             }
   698             
   719 
   699             // Symbian
   720             // Symbian
   700             if ($result['others']['detail'][0][1] == 'SymbianOS') {
   721             if ($result['others']['detail'][0][1] == 'SymbianOS') {
   701                 $result['device_os_token'] = 'SymbianOS';
   722                 $result['device_os_token'] = 'SymbianOS';
   702             }
   723             }
   703         }
   724         }
   704         
   725 
   705         // UA ends with 'Opera X.XX'
   726         // UA ends with 'Opera X.XX'
   706         if (isset($result['browser_name']) && isset($result['browser_engine'])) {
   727         if (isset($result['browser_name']) && isset($result['browser_engine'])) {
   707             if ($result['browser_name'] == 'Opera' && $result['browser_engine'] == 'Gecko' && empty($result['browser_version'])) {
   728             if ($result['browser_name'] == 'Opera' && $result['browser_engine'] == 'Gecko' && empty($result['browser_version'])) {
   708                 $result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][1];
   729                 $result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][1];
   709             }
   730             }
   710         }
   731         }
   711         
   732 
   712         // cleanup
   733         // cleanup
   713         if (isset($result['browser_version']) && isset($result['browser_build'])) {
   734         if (isset($result['browser_version']) && isset($result['browser_build'])) {
   714             if ($result['browser_version'] == $result['browser_build']) {
   735             if ($result['browser_version'] == $result['browser_build']) {
   715                 unset($result['browser_build']);
   736                 unset($result['browser_build']);
   716             }
   737             }
   717         }
   738         }
   718         
   739 
   719         // compatibility
   740         // compatibility
   720         $compatibility['AppleWebKit'] = 'Safari';
   741         $compatibility['AppleWebKit'] = 'Safari';
   721         $compatibility['Gecko']       = 'Firefox';
   742         $compatibility['Gecko']       = 'Firefox';
   722         $compatibility['MSIE']        = 'Internet Explorer';
   743         $compatibility['MSIE']        = 'Internet Explorer';
   723         $compatibility['Presto']      = 'Opera';
   744         $compatibility['Presto']      = 'Opera';
   724         if (!empty($result['browser_engine'])) {
   745         if (!empty($result['browser_engine'])) {
   725             if (isset($compatibility[$result['browser_engine']])) {
   746             if (isset($compatibility[$result['browser_engine']])) {
   726                 $result['browser_compatibility'] = $compatibility[$result['browser_engine']];
   747                 $result['browser_compatibility'] = $compatibility[$result['browser_engine']];
   727             }
   748             }
   728         }
   749         }
   729         
   750 
   730         ksort($result);
   751         ksort($result);
   731         return $result;
   752         return $result;
   732     }
   753     }
   733 
   754 
   734     /**
   755     /**
   758                 $path = $config['path'];
   779                 $path = $config['path'];
   759             } else {
   780             } else {
   760                 require_once 'Zend/Http/UserAgent/Exception.php';
   781                 require_once 'Zend/Http/UserAgent/Exception.php';
   761                 throw new Zend_Http_UserAgent_Exception('The ' . $this->getType() . ' features adapter must have a "path" config parameter defined');
   782                 throw new Zend_Http_UserAgent_Exception('The ' . $this->getType() . ' features adapter must have a "path" config parameter defined');
   762             }
   783             }
   763             
   784 
   764             if (false === include_once ($path)) {
   785             if (false === include_once ($path)) {
   765                 require_once 'Zend/Http/UserAgent/Exception.php';
   786                 require_once 'Zend/Http/UserAgent/Exception.php';
   766                 throw new Zend_Http_UserAgent_Exception('The ' . $this->getType() . ' features adapter path that does not exist');
   787                 throw new Zend_Http_UserAgent_Exception('The ' . $this->getType() . ' features adapter path that does not exist');
   767             }
   788             }
   768         }
   789         }
   769         
   790 
   770         return call_user_func(array($className, 'getFromRequest'), $this->_server, $this->_config);
   791         return call_user_func(array($className, 'getFromRequest'), $this->_server, $this->_config);
   771     }
   792     }
   772 
   793 
   773     /**
   794     /**
   774      * Retrieve image format support
   795      * Retrieve image format support
   951         $this->_images = $_images;
   972         $this->_images = $_images;
   952     }
   973     }
   953 
   974 
   954     /**
   975     /**
   955      * Match a user agent string against a list of signatures
   976      * Match a user agent string against a list of signatures
   956      * 
   977      *
   957      * @param  string $userAgent 
   978      * @param  string $userAgent
   958      * @param  array $signatures 
   979      * @param  array $signatures
   959      * @return bool
   980      * @return bool
   960      */
   981      */
   961     protected static function _matchAgentAgainstSignatures($userAgent, $signatures)
   982     protected static function _matchAgentAgainstSignatures($userAgent, $signatures)
   962     {
   983     {
   963         $userAgent = strtolower($userAgent);
   984         $userAgent = strtolower($userAgent);