Mobile.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  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 (!empty($this->_aFeatures["mobile_browser"])) {
  338. $this->setFeature("browser_name", $this->_aFeatures["mobile_browser"]);
  339. }
  340. if (!empty($this->_aFeatures["mobile_browser_version"])) {
  341. $this->setFeature("browser_version", $this->_aFeatures["mobile_browser_version"]);
  342. }
  343. // markup
  344. if ($this->getFeature('device_os') == 'iPhone OS'
  345. || $this->getFeature('device_os_token') == 'iPhone OS'
  346. ) {
  347. $this->setFeature('markup', 'iphone');
  348. } else {
  349. $this->setFeature('markup', $this->getMarkupLanguage($this->getFeature('preferred_markup')));
  350. }
  351. // image format
  352. $this->_images = array();
  353. if ($this->getFeature('png')) {
  354. $this->_images[] = 'png';
  355. }
  356. if ($this->getFeature('jpg')) {
  357. $this->_images[] = 'jpg';
  358. }
  359. if ($this->getFeature('gif')) {
  360. $this->_images[] = 'gif';
  361. }
  362. if ($this->getFeature('wbmp')) {
  363. $this->_images[] = 'wbmp';
  364. }
  365. return $this->_aFeatures;
  366. }
  367. /**
  368. * Determine markup language expected
  369. *
  370. * @access public
  371. * @return __TYPE__
  372. */
  373. public function getMarkupLanguage($preferredMarkup = null)
  374. {
  375. $return = '';
  376. switch ($preferredMarkup) {
  377. case 'wml_1_1':
  378. case 'wml_1_2':
  379. case 'wml_1_3':
  380. $return = 'wml'; //text/vnd.wap.wml encoding="ISO-8859-15"
  381. case 'html_wi_imode_compact_generic':
  382. case 'html_wi_imode_html_1':
  383. case 'html_wi_imode_html_2':
  384. case 'html_wi_imode_html_3':
  385. case 'html_wi_imode_html_4':
  386. case 'html_wi_imode_html_5':
  387. $return = 'chtml'; //text/html
  388. case 'html_wi_oma_xhtmlmp_1_0': //application/vnd.wap.xhtml+xml
  389. case 'html_wi_w3_xhtmlbasic': //application/xhtml+xml DTD XHTML Basic 1.0
  390. $return = 'xhtml';
  391. case 'html_web_3_2': //text/html DTD Html 3.2 Final
  392. case 'html_web_4_0': //text/html DTD Html 4.01 Transitional
  393. $return = '';
  394. }
  395. return $return;
  396. }
  397. /**
  398. * Determine image format support
  399. *
  400. * @return array
  401. */
  402. public function getImageFormatSupport()
  403. {
  404. return $this->_images;
  405. }
  406. /**
  407. * Determine maximum image height supported
  408. *
  409. * @return int
  410. */
  411. public function getMaxImageHeight()
  412. {
  413. return $this->getFeature('max_image_height');
  414. }
  415. /**
  416. * Determine maximum image width supported
  417. *
  418. * @return int
  419. */
  420. public function getMaxImageWidth()
  421. {
  422. return $this->getFeature('max_image_width');
  423. }
  424. /**
  425. * Determine physical screen height
  426. *
  427. * @return int
  428. */
  429. public function getPhysicalScreenHeight()
  430. {
  431. return $this->getFeature('physical_screen_height');
  432. }
  433. /**
  434. * Determine physical screen width
  435. *
  436. * @return int
  437. */
  438. public function getPhysicalScreenWidth()
  439. {
  440. return $this->getFeature('physical_screen_width');
  441. }
  442. /**
  443. * Determine preferred markup
  444. *
  445. * @return string
  446. */
  447. public function getPreferredMarkup()
  448. {
  449. return $this->getFeature("markup");
  450. }
  451. /**
  452. * Determine X/HTML support level
  453. *
  454. * @return int
  455. */
  456. public function getXhtmlSupportLevel()
  457. {
  458. return $this->getFeature('xhtml_support_level');
  459. }
  460. /**
  461. * Does the device support Flash?
  462. *
  463. * @return bool
  464. */
  465. public function hasFlashSupport()
  466. {
  467. return $this->getFeature('fl_browser');
  468. }
  469. /**
  470. * Does the device support PDF?
  471. *
  472. * @return bool
  473. */
  474. public function hasPdfSupport()
  475. {
  476. return $this->getFeature('pdf_support');
  477. }
  478. /**
  479. * Does the device have an associated phone number?
  480. *
  481. * @return bool
  482. */
  483. public function hasPhoneNumber()
  484. {
  485. return $this->getFeature('can_assign_phone_number');
  486. }
  487. /**
  488. * Does the device support HTTPS?
  489. *
  490. * @return bool
  491. */
  492. public function httpsSupport()
  493. {
  494. return ($this->getFeature('https_support') == 'supported');
  495. }
  496. }