Mobile.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Http
  17. * @subpackage UserAgent
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. require_once 'Zend/Http/UserAgent/AbstractDevice.php';
  22. /**
  23. * Mobile browser type matcher
  24. *
  25. * @category Zend
  26. * @package Zend_Http
  27. * @subpackage UserAgent
  28. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_Http_UserAgent_Mobile extends Zend_Http_UserAgent_AbstractDevice
  32. {
  33. const DEFAULT_FEATURES_ADAPTER_CLASSNAME = 'Zend_Http_UserAgent_Features_Adapter_WurflApi';
  34. const DEFAULT_FEATURES_ADAPTER_PATH = 'Zend/Http/UserAgent/Features/Adapter/WurflApi.php';
  35. /**
  36. * User Agent Signatures
  37. *
  38. * @var array
  39. */
  40. protected static $_uaSignatures = array(
  41. 'iphone',
  42. 'ipod',
  43. 'ipad',
  44. 'android',
  45. 'blackberry',
  46. 'opera mini',
  47. 'opera mobi',
  48. 'palm',
  49. 'palmos',
  50. 'elaine',
  51. 'windows ce',
  52. ' ppc',
  53. '_mms',
  54. 'ahong',
  55. 'archos',
  56. 'armv',
  57. 'astel',
  58. 'avantgo',
  59. 'benq',
  60. 'blazer',
  61. 'brew',
  62. 'com2',
  63. 'compal',
  64. 'danger',
  65. 'pocket',
  66. 'docomo',
  67. 'epoc',
  68. 'ericsson',
  69. 'eudoraweb',
  70. 'hiptop',
  71. 'htc-',
  72. 'htc_',
  73. 'iemobile',
  74. 'ipad',
  75. 'iris',
  76. 'j-phone',
  77. 'kddi',
  78. 'kindle',
  79. 'lg ',
  80. 'lg-',
  81. 'lg/',
  82. 'lg;lx',
  83. 'lge vx',
  84. 'lge',
  85. 'lge-',
  86. 'lge-cx',
  87. 'lge-lx',
  88. 'lge-mx',
  89. 'linux armv',
  90. 'maemo',
  91. 'midp',
  92. 'mini 9.5',
  93. 'minimo',
  94. 'mob-x',
  95. 'mobi',
  96. 'mobile',
  97. 'mobilephone',
  98. 'mot 24',
  99. 'mot-',
  100. 'motorola',
  101. 'n410',
  102. 'netfront',
  103. 'nintendo wii',
  104. 'nintendo',
  105. 'nitro',
  106. 'nokia',
  107. 'novarra-vision',
  108. 'nuvifone',
  109. 'openweb',
  110. 'opwv',
  111. 'palmsource',
  112. 'pdxgw',
  113. 'phone',
  114. 'playstation',
  115. 'polaris',
  116. 'portalmmm',
  117. 'qt embedded',
  118. 'reqwirelessweb',
  119. 'sagem',
  120. 'sam-r',
  121. 'samsu',
  122. 'samsung',
  123. 'sec-',
  124. 'sec-sgh',
  125. 'semc-browser',
  126. 'series60',
  127. 'series70',
  128. 'series80',
  129. 'series90',
  130. 'sharp',
  131. 'sie-m',
  132. 'sie-s',
  133. 'smartphone',
  134. 'sony cmd',
  135. 'sonyericsson',
  136. 'sprint',
  137. 'spv',
  138. 'symbian os',
  139. 'symbian',
  140. 'symbianos',
  141. 'telco',
  142. 'teleca',
  143. 'treo',
  144. 'up.browser',
  145. 'up.link',
  146. 'vodafone',
  147. 'vodaphone',
  148. 'webos',
  149. 'webpro',
  150. 'windows phone os 7',
  151. 'wireless',
  152. 'wm5 pie',
  153. 'wms pie',
  154. 'xiino',
  155. 'wap',
  156. 'up/',
  157. 'psion',
  158. 'j2me',
  159. 'klondike',
  160. 'kbrowser'
  161. );
  162. /**
  163. * @var array
  164. */
  165. protected static $_haTerms = array(
  166. 'midp',
  167. 'wml',
  168. 'vnd.rim',
  169. 'vnd.wap',
  170. );
  171. /**
  172. * first 4 letters of mobile User Agent chains
  173. *
  174. * @var array
  175. */
  176. protected static $_uaBegin = array(
  177. 'w3c ',
  178. 'acs-',
  179. 'alav',
  180. 'alca',
  181. 'amoi',
  182. 'audi',
  183. 'avan',
  184. 'benq',
  185. 'bird',
  186. 'blac',
  187. 'blaz',
  188. 'brew',
  189. 'cell',
  190. 'cldc',
  191. 'cmd-',
  192. 'dang',
  193. 'doco',
  194. 'eric',
  195. 'hipt',
  196. 'inno',
  197. 'ipaq',
  198. 'java',
  199. 'jigs',
  200. 'kddi',
  201. 'keji',
  202. 'leno',
  203. 'lg-c',
  204. 'lg-d',
  205. 'lg-g',
  206. 'lge-',
  207. 'maui',
  208. 'maxo',
  209. 'midp',
  210. 'mits',
  211. 'mmef',
  212. 'mobi',
  213. 'mot-',
  214. 'moto',
  215. 'mwbp',
  216. 'nec-',
  217. 'newt',
  218. 'noki',
  219. 'oper',
  220. 'palm',
  221. 'pana',
  222. 'pant',
  223. 'phil',
  224. 'play',
  225. 'port',
  226. 'prox',
  227. 'qwap',
  228. 'sage',
  229. 'sams',
  230. 'sany',
  231. 'sch-',
  232. 'sec-',
  233. 'send',
  234. 'seri',
  235. 'sgh-',
  236. 'shar',
  237. 'sie-',
  238. 'siem',
  239. 'smal',
  240. 'smar',
  241. 'sony',
  242. 'sph-',
  243. 'symb',
  244. 't-mo',
  245. 'teli',
  246. 'tim-',
  247. 'tosh',
  248. 'tsm-',
  249. 'upg1',
  250. 'upsi',
  251. 'vk-v',
  252. 'voda',
  253. 'wap-',
  254. 'wapa',
  255. 'wapi',
  256. 'wapp',
  257. 'wapr',
  258. 'webc',
  259. 'winw',
  260. 'winw',
  261. 'xda',
  262. 'xda-',
  263. );
  264. /**
  265. * Comparison of the UserAgent chain and User Agent signatures
  266. *
  267. * @param string $userAgent User Agent chain
  268. * @param array $server $_SERVER like param
  269. * @return bool
  270. */
  271. public static function match($userAgent, $server)
  272. {
  273. // To have a quick identification, try light-weight tests first
  274. if (isset($server['all_http'])) {
  275. if (strpos(strtolower(str_replace(' ', '', $server['all_http'])), 'operam') !== false) {
  276. // Opera Mini or Opera Mobi
  277. return true;
  278. }
  279. }
  280. if (isset($server['http_x_wap_profile']) || isset($server['http_profile'])) {
  281. return true;
  282. }
  283. if (self::_matchAgentAgainstSignatures($userAgent, self::$_haTerms)) {
  284. return true;
  285. }
  286. if (self::userAgentStart($userAgent)) {
  287. return true;
  288. }
  289. if (self::_matchAgentAgainstSignatures($userAgent, self::$_uaSignatures)) {
  290. return true;
  291. }
  292. return false;
  293. }
  294. /**
  295. * Retrieve beginning clause of user agent
  296. *
  297. * @param string $userAgent
  298. * @return string
  299. */
  300. public static function userAgentStart($userAgent)
  301. {
  302. $mobile_ua = strtolower(substr($userAgent, 0, 4));
  303. return (in_array($mobile_ua, self::$_uaBegin));
  304. }
  305. /**
  306. * Constructor
  307. *
  308. * @return void
  309. */
  310. public function __construct($userAgent = null, array $server = array(), array $config = array())
  311. {
  312. // For mobile detection, an adapter must be defined
  313. if (empty($config['mobile']['features'])) {
  314. $config['mobile']['features']['path'] = self::DEFAULT_FEATURES_ADAPTER_PATH;
  315. $config['mobile']['features']['classname'] = self::DEFAULT_FEATURES_ADAPTER_CLASSNAME;
  316. }
  317. parent::__construct($userAgent, $server, $config);
  318. }
  319. /**
  320. * Gives the current browser type
  321. *
  322. * @return string
  323. */
  324. public function getType()
  325. {
  326. return 'mobile';
  327. }
  328. /**
  329. * Look for features
  330. *
  331. * @return string
  332. */
  333. protected function _defineFeatures()
  334. {
  335. $this->setFeature('is_wireless_device', false, 'product_info');
  336. parent::_defineFeatures();
  337. if (isset($this->_aFeatures["mobile_browser"])) {
  338. $this->setFeature("browser_name", $this->_aFeatures["mobile_browser"]);
  339. $this->_browser = $this->_aFeatures["mobile_browser"];
  340. }
  341. if (isset($this->_aFeatures["mobile_browser_version"])) {
  342. $this->setFeature("browser_version", $this->_aFeatures["mobile_browser_version"]);
  343. $this->_browserVersion = $this->_aFeatures["mobile_browser_version"];
  344. }
  345. // markup
  346. if ($this->getFeature('device_os') == 'iPhone OS'
  347. || $this->getFeature('device_os_token') == 'iPhone OS'
  348. ) {
  349. $this->setFeature('markup', 'iphone');
  350. } else {
  351. $this->setFeature('markup', $this->getMarkupLanguage($this->getFeature('preferred_markup')));
  352. }
  353. // image format
  354. $this->_images = array();
  355. if ($this->getFeature('png')) {
  356. $this->_images[] = 'png';
  357. }
  358. if ($this->getFeature('jpg')) {
  359. $this->_images[] = 'jpg';
  360. }
  361. if ($this->getFeature('gif')) {
  362. $this->_images[] = 'gif';
  363. }
  364. if ($this->getFeature('wbmp')) {
  365. $this->_images[] = 'wbmp';
  366. }
  367. return $this->_aFeatures;
  368. }
  369. /**
  370. * Determine markup language expected
  371. *
  372. * @access public
  373. * @return __TYPE__
  374. */
  375. public function getMarkupLanguage($preferredMarkup = null)
  376. {
  377. $return = '';
  378. switch ($preferredMarkup) {
  379. case 'wml_1_1':
  380. case 'wml_1_2':
  381. case 'wml_1_3':
  382. $return = 'wml'; //text/vnd.wap.wml encoding="ISO-8859-15"
  383. case 'html_wi_imode_compact_generic':
  384. case 'html_wi_imode_html_1':
  385. case 'html_wi_imode_html_2':
  386. case 'html_wi_imode_html_3':
  387. case 'html_wi_imode_html_4':
  388. case 'html_wi_imode_html_5':
  389. $return = 'chtml'; //text/html
  390. case 'html_wi_oma_xhtmlmp_1_0': //application/vnd.wap.xhtml+xml
  391. case 'html_wi_w3_xhtmlbasic': //application/xhtml+xml DTD XHTML Basic 1.0
  392. $return = 'xhtml';
  393. case 'html_web_3_2': //text/html DTD Html 3.2 Final
  394. case 'html_web_4_0': //text/html DTD Html 4.01 Transitional
  395. $return = '';
  396. }
  397. return $return;
  398. }
  399. /**
  400. * Determine image format support
  401. *
  402. * @return array
  403. */
  404. public function getImageFormatSupport()
  405. {
  406. return $this->_images;
  407. }
  408. /**
  409. * Determine maximum image height supported
  410. *
  411. * @return int
  412. */
  413. public function getMaxImageHeight()
  414. {
  415. return $this->getFeature('max_image_height');
  416. }
  417. /**
  418. * Determine maximum image width supported
  419. *
  420. * @return int
  421. */
  422. public function getMaxImageWidth()
  423. {
  424. return $this->getFeature('max_image_width');
  425. }
  426. /**
  427. * Determine physical screen height
  428. *
  429. * @return int
  430. */
  431. public function getPhysicalScreenHeight()
  432. {
  433. return $this->getFeature('physical_screen_height');
  434. }
  435. /**
  436. * Determine physical screen width
  437. *
  438. * @return int
  439. */
  440. public function getPhysicalScreenWidth()
  441. {
  442. return $this->getFeature('physical_screen_width');
  443. }
  444. /**
  445. * Determine preferred markup
  446. *
  447. * @return string
  448. */
  449. public function getPreferredMarkup()
  450. {
  451. return $this->getFeature("markup");
  452. }
  453. /**
  454. * Determine X/HTML support level
  455. *
  456. * @return int
  457. */
  458. public function getXhtmlSupportLevel()
  459. {
  460. return $this->getFeature('xhtml_support_level');
  461. }
  462. /**
  463. * Does the device support Flash?
  464. *
  465. * @return bool
  466. */
  467. public function hasFlashSupport()
  468. {
  469. return $this->getFeature('fl_browser');
  470. }
  471. /**
  472. * Does the device support PDF?
  473. *
  474. * @return bool
  475. */
  476. public function hasPdfSupport()
  477. {
  478. return $this->getFeature('pdf_support');
  479. }
  480. /**
  481. * Does the device have an associated phone number?
  482. *
  483. * @return bool
  484. */
  485. public function hasPhoneNumber()
  486. {
  487. return $this->getFeature('can_assign_phone_number');
  488. }
  489. /**
  490. * Does the device support HTTPS?
  491. *
  492. * @return bool
  493. */
  494. public function httpsSupport()
  495. {
  496. return ($this->getFeature('https_support') == 'supported');
  497. }
  498. }