<?php /** * Zend Framework * * LICENSE * * This source file is subject to the new BSD license that is bundled * with this package in the file LICENSE.txt. * It is also available through the world-wide-web at this URL: * http://framework.zend.com/license/new-bsd * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to license@zend.com so we can send you a copy immediately. * * @category Zend * @package Zend_Http * @subpackage UserAgent * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ require_once 'Zend/Http/UserAgent/AbstractDevice.php'; /** * Mobile browser type matcher * * @category Zend * @package Zend_Http * @subpackage UserAgent * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Http_UserAgent_Mobile extends Zend_Http_UserAgent_AbstractDevice { const DEFAULT_FEATURES_ADAPTER_CLASSNAME = 'Zend_Http_UserAgent_Features_Adapter_Browscap'; const DEFAULT_FEATURES_ADAPTER_PATH = 'Zend/Http/UserAgent/Features/Adapter/Browscap.php'; /** * User Agent Signatures * * @var array */ protected static $_uaSignatures = array( 'iphone', 'ipod', 'ipad', 'android', 'blackberry', 'opera mini', 'opera mobi', 'palm', 'palmos', 'elaine', 'windows ce', 'icab', '_mms', 'ahong', 'archos', 'armv', 'astel', 'avantgo', 'benq', 'blazer', 'brew', 'com2', 'compal', 'danger', 'pocket', 'docomo', 'epoc', 'ericsson', 'eudoraweb', 'hiptop', 'htc-', 'htc_', 'iemobile', 'iris', 'j-phone', 'kddi', 'kindle', 'lg ', 'lg-', 'lg/', 'lg;lx', 'lge vx', 'lge', 'lge-', 'lge-cx', 'lge-lx', 'lge-mx', 'linux armv', 'maemo', 'midp', 'mini 9.5', 'minimo', 'mob-x', 'mobi', 'mobile', 'mobilephone', 'mot 24', 'mot-', 'motorola', 'n410', 'netfront', 'nintendo wii', 'nintendo', 'nitro', 'nokia', 'novarra-vision', 'nuvifone', 'openweb', 'opwv', 'palmsource', 'pdxgw', 'phone', 'playstation', 'polaris', 'portalmmm', 'qt embedded', 'reqwirelessweb', 'sagem', 'sam-r', 'samsu', 'samsung', 'sec-', 'sec-sgh', 'semc-browser', 'series60', 'series70', 'series80', 'series90', 'sharp', 'sie-m', 'sie-s', 'smartphone', 'sony cmd', 'sonyericsson', 'sprint', 'spv', 'symbian os', 'symbian', 'symbianos', 'telco', 'teleca', 'treo', 'up.browser', 'up.link', 'vodafone', 'vodaphone', 'webos', 'wml', 'windows phone os 7', 'wireless', 'wm5 pie', 'wms pie', 'xiino', 'wap', 'up/', 'psion', 'j2me', 'klondike', 'kbrowser' ); /** * @var array */ protected static $_haTerms = array( 'midp', 'wml', 'vnd.rim', 'vnd.wap', 'j2me', ); /** * first 4 letters of mobile User Agent chains * * @var array */ protected static $_uaBegin = array( 'w3c ', 'acs-', 'alav', 'alca', 'amoi', 'audi', 'avan', 'benq', 'bird', 'blac', 'blaz', 'brew', 'cell', 'cldc', 'cmd-', 'dang', 'doco', 'eric', 'hipt', 'inno', 'ipaq', 'java', 'jigs', 'kddi', 'keji', 'leno', 'lg-c', 'lg-d', 'lg-g', 'lge-', 'maui', 'maxo', 'midp', 'mits', 'mmef', 'mobi', 'mot-', 'moto', 'mwbp', 'nec-', 'newt', 'noki', 'palm', 'pana', 'pant', 'phil', 'play', 'port', 'prox', 'qwap', 'sage', 'sams', 'sany', 'sch-', 'sec-', 'send', 'seri', 'sgh-', 'shar', 'sie-', 'siem', 'smal', 'smar', 'sony', 'sph-', 'symb', 't-mo', 'teli', 'tim-', 'tosh', 'tsm-', 'upg1', 'upsi', 'vk-v', 'voda', 'wap-', 'wapa', 'wapi', 'wapp', 'wapr', 'webc', 'winw', 'winw', 'xda', 'xda-', ); /** * Comparison of the UserAgent chain and User Agent signatures * * @param string $userAgent User Agent chain * @param array $server $_SERVER like param * @return bool */ public static function match($userAgent, $server) { // To have a quick identification, try light-weight tests first if (isset($server['all_http'])) { if (strpos(strtolower(str_replace(' ', '', $server['all_http'])), 'operam') !== false) { // Opera Mini or Opera Mobi return true; } } if (isset($server['http_x_wap_profile']) || isset($server['http_profile'])) { return true; } if (isset($server['http_accept'])) { if (self::_matchAgentAgainstSignatures($server['http_accept'], self::$_haTerms)) { return true; } } if (self::userAgentStart($userAgent)) { return true; } if (self::_matchAgentAgainstSignatures($userAgent, self::$_uaSignatures)) { return true; } return false; } /** * Retrieve beginning clause of user agent * * @param string $userAgent * @return string */ public static function userAgentStart($userAgent) { $mobile_ua = strtolower(substr($userAgent, 0, 4)); return (in_array($mobile_ua, self::$_uaBegin)); } /** * Constructor * * @return void */ public function __construct($userAgent = null, array $server = array(), array $config = array()) { // For mobile detection, an adapter must be defined if (empty($config['mobile']['features'])) { $config['mobile']['features']['path'] = self::DEFAULT_FEATURES_ADAPTER_PATH; $config['mobile']['features']['classname'] = self::DEFAULT_FEATURES_ADAPTER_CLASSNAME; } parent::__construct($userAgent, $server, $config); } /** * Gives the current browser type * * @return string */ public function getType() { return 'mobile'; } /** * Look for features * * @return string */ protected function _defineFeatures() { $this->setFeature('is_wireless_device', false, 'product_info'); parent::_defineFeatures(); if (isset($this->_aFeatures["mobile_browser"])) { $this->setFeature("browser_name", $this->_aFeatures["mobile_browser"]); $this->_browser = $this->_aFeatures["mobile_browser"]; } if (isset($this->_aFeatures["mobile_browser_version"])) { $this->setFeature("browser_version", $this->_aFeatures["mobile_browser_version"]); $this->_browserVersion = $this->_aFeatures["mobile_browser_version"]; } // markup if ($this->getFeature('device_os') == 'iPhone OS' || $this->getFeature('device_os_token') == 'iPhone OS' ) { $this->setFeature('markup', 'iphone'); } else { $this->setFeature('markup', $this->getMarkupLanguage($this->getFeature('preferred_markup'))); } // image format $this->_images = array(); if ($this->getFeature('png')) { $this->_images[] = 'png'; } if ($this->getFeature('jpg')) { $this->_images[] = 'jpg'; } if ($this->getFeature('gif')) { $this->_images[] = 'gif'; } if ($this->getFeature('wbmp')) { $this->_images[] = 'wbmp'; } return $this->_aFeatures; } /** * Determine markup language expected * * @access public * @return __TYPE__ */ public function getMarkupLanguage($preferredMarkup = null) { $return = ''; switch ($preferredMarkup) { case 'wml_1_1': case 'wml_1_2': case 'wml_1_3': $return = 'wml'; //text/vnd.wap.wml encoding="ISO-8859-15" case 'html_wi_imode_compact_generic': case 'html_wi_imode_html_1': case 'html_wi_imode_html_2': case 'html_wi_imode_html_3': case 'html_wi_imode_html_4': case 'html_wi_imode_html_5': $return = 'chtml'; //text/html case 'html_wi_oma_xhtmlmp_1_0': //application/vnd.wap.xhtml+xml case 'html_wi_w3_xhtmlbasic': //application/xhtml+xml DTD XHTML Basic 1.0 $return = 'xhtml'; case 'html_web_3_2': //text/html DTD Html 3.2 Final case 'html_web_4_0': //text/html DTD Html 4.01 Transitional $return = ''; } return $return; } /** * Determine image format support * * @return array */ public function getImageFormatSupport() { return $this->_images; } /** * Determine maximum image height supported * * @return int */ public function getMaxImageHeight() { return $this->getFeature('max_image_height'); } /** * Determine maximum image width supported * * @return int */ public function getMaxImageWidth() { return $this->getFeature('max_image_width'); } /** * Determine physical screen height * * @return int */ public function getPhysicalScreenHeight() { return $this->getFeature('physical_screen_height'); } /** * Determine physical screen width * * @return int */ public function getPhysicalScreenWidth() { return $this->getFeature('physical_screen_width'); } /** * Determine preferred markup * * @return string */ public function getPreferredMarkup() { return $this->getFeature("markup"); } /** * Determine X/HTML support level * * @return int */ public function getXhtmlSupportLevel() { return $this->getFeature('xhtml_support_level'); } /** * Does the device support Flash? * * @return bool */ public function hasFlashSupport() { return $this->getFeature('fl_browser'); } /** * Does the device support PDF? * * @return bool */ public function hasPdfSupport() { return $this->getFeature('pdf_support'); } /** * Does the device have an associated phone number? * * @return bool */ public function hasPhoneNumber() { return $this->getFeature('can_assign_phone_number'); } /** * Does the device support HTTPS? * * @return bool */ public function httpsSupport() { return ($this->getFeature('https_support') == 'supported'); } }