Mobile.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  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. 'icab',
  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. 'wml',
  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. 'j2me'
  171. );
  172. /**
  173. * first 4 letters of mobile User Agent chains
  174. *
  175. * @var array
  176. */
  177. protected static $_uaBegin = array(
  178. 'w3c ',
  179. 'acs-',
  180. 'alav',
  181. 'alca',
  182. 'amoi',
  183. 'audi',
  184. 'avan',
  185. 'benq',
  186. 'bird',
  187. 'blac',
  188. 'blaz',
  189. 'brew',
  190. 'cell',
  191. 'cldc',
  192. 'cmd-',
  193. 'dang',
  194. 'doco',
  195. 'eric',
  196. 'hipt',
  197. 'inno',
  198. 'ipaq',
  199. 'java',
  200. 'jigs',
  201. 'kddi',
  202. 'keji',
  203. 'leno',
  204. 'lg-c',
  205. 'lg-d',
  206. 'lg-g',
  207. 'lge-',
  208. 'maui',
  209. 'maxo',
  210. 'midp',
  211. 'mits',
  212. 'mmef',
  213. 'mobi',
  214. 'mot-',
  215. 'moto',
  216. 'mwbp',
  217. 'nec-',
  218. 'newt',
  219. 'noki',
  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 (isset($server['http_accept'])) {
  284. if (self::_matchAgentAgainstSignatures($server['http_accept'], self::$_haTerms)) {
  285. return true;
  286. }
  287. }
  288. if (self::userAgentStart($userAgent)) {
  289. return true;
  290. }
  291. if (self::_matchAgentAgainstSignatures($userAgent, self::$_uaSignatures)) {
  292. return true;
  293. }
  294. return false;
  295. }
  296. /**
  297. * Retrieve beginning clause of user agent
  298. *
  299. * @param string $userAgent
  300. * @return string
  301. */
  302. public static function userAgentStart($userAgent)
  303. {
  304. $mobile_ua = strtolower(substr($userAgent, 0, 4));
  305. return (in_array($mobile_ua, self::$_uaBegin));
  306. }
  307. /**
  308. * Constructor
  309. *
  310. * @return void
  311. */
  312. public function __construct($userAgent = null, array $server = array(), array $config = array())
  313. {
  314. // For mobile detection, an adapter must be defined
  315. if (empty($config['mobile']['features'])) {
  316. $config['mobile']['features']['path'] = self::DEFAULT_FEATURES_ADAPTER_PATH;
  317. $config['mobile']['features']['classname'] = self::DEFAULT_FEATURES_ADAPTER_CLASSNAME;
  318. }
  319. parent::__construct($userAgent, $server, $config);
  320. }
  321. /**
  322. * Gives the current browser type
  323. *
  324. * @return string
  325. */
  326. public function getType()
  327. {
  328. return 'mobile';
  329. }
  330. /**
  331. * Look for features
  332. *
  333. * @return string
  334. */
  335. protected function _defineFeatures()
  336. {
  337. $this->setFeature('is_wireless_device', false, 'product_info');
  338. parent::_defineFeatures();
  339. if (isset($this->_aFeatures["mobile_browser"])) {
  340. $this->setFeature("browser_name", $this->_aFeatures["mobile_browser"]);
  341. $this->_browser = $this->_aFeatures["mobile_browser"];
  342. }
  343. if (isset($this->_aFeatures["mobile_browser_version"])) {
  344. $this->setFeature("browser_version", $this->_aFeatures["mobile_browser_version"]);
  345. $this->_browserVersion = $this->_aFeatures["mobile_browser_version"];
  346. }
  347. // markup
  348. if ($this->getFeature('device_os') == 'iPhone OS'
  349. || $this->getFeature('device_os_token') == 'iPhone OS'
  350. ) {
  351. $this->setFeature('markup', 'iphone');
  352. } else {
  353. $this->setFeature('markup', $this->getMarkupLanguage($this->getFeature('preferred_markup')));
  354. }
  355. // image format
  356. $this->_images = array();
  357. if ($this->getFeature('png')) {
  358. $this->_images[] = 'png';
  359. }
  360. if ($this->getFeature('jpg')) {
  361. $this->_images[] = 'jpg';
  362. }
  363. if ($this->getFeature('gif')) {
  364. $this->_images[] = 'gif';
  365. }
  366. if ($this->getFeature('wbmp')) {
  367. $this->_images[] = 'wbmp';
  368. }
  369. return $this->_aFeatures;
  370. }
  371. /**
  372. * Determine markup language expected
  373. *
  374. * @access public
  375. * @return __TYPE__
  376. */
  377. public function getMarkupLanguage($preferredMarkup = null)
  378. {
  379. $return = '';
  380. switch ($preferredMarkup) {
  381. case 'wml_1_1':
  382. case 'wml_1_2':
  383. case 'wml_1_3':
  384. $return = 'wml'; //text/vnd.wap.wml encoding="ISO-8859-15"
  385. case 'html_wi_imode_compact_generic':
  386. case 'html_wi_imode_html_1':
  387. case 'html_wi_imode_html_2':
  388. case 'html_wi_imode_html_3':
  389. case 'html_wi_imode_html_4':
  390. case 'html_wi_imode_html_5':
  391. $return = 'chtml'; //text/html
  392. case 'html_wi_oma_xhtmlmp_1_0': //application/vnd.wap.xhtml+xml
  393. case 'html_wi_w3_xhtmlbasic': //application/xhtml+xml DTD XHTML Basic 1.0
  394. $return = 'xhtml';
  395. case 'html_web_3_2': //text/html DTD Html 3.2 Final
  396. case 'html_web_4_0': //text/html DTD Html 4.01 Transitional
  397. $return = '';
  398. }
  399. return $return;
  400. }
  401. /**
  402. * Determine image format support
  403. *
  404. * @return array
  405. */
  406. public function getImageFormatSupport()
  407. {
  408. return $this->_images;
  409. }
  410. /**
  411. * Determine maximum image height supported
  412. *
  413. * @return int
  414. */
  415. public function getMaxImageHeight()
  416. {
  417. return $this->getFeature('max_image_height');
  418. }
  419. /**
  420. * Determine maximum image width supported
  421. *
  422. * @return int
  423. */
  424. public function getMaxImageWidth()
  425. {
  426. return $this->getFeature('max_image_width');
  427. }
  428. /**
  429. * Determine physical screen height
  430. *
  431. * @return int
  432. */
  433. public function getPhysicalScreenHeight()
  434. {
  435. return $this->getFeature('physical_screen_height');
  436. }
  437. /**
  438. * Determine physical screen width
  439. *
  440. * @return int
  441. */
  442. public function getPhysicalScreenWidth()
  443. {
  444. return $this->getFeature('physical_screen_width');
  445. }
  446. /**
  447. * Determine preferred markup
  448. *
  449. * @return string
  450. */
  451. public function getPreferredMarkup()
  452. {
  453. return $this->getFeature("markup");
  454. }
  455. /**
  456. * Determine X/HTML support level
  457. *
  458. * @return int
  459. */
  460. public function getXhtmlSupportLevel()
  461. {
  462. return $this->getFeature('xhtml_support_level');
  463. }
  464. /**
  465. * Does the device support Flash?
  466. *
  467. * @return bool
  468. */
  469. public function hasFlashSupport()
  470. {
  471. return $this->getFeature('fl_browser');
  472. }
  473. /**
  474. * Does the device support PDF?
  475. *
  476. * @return bool
  477. */
  478. public function hasPdfSupport()
  479. {
  480. return $this->getFeature('pdf_support');
  481. }
  482. /**
  483. * Does the device have an associated phone number?
  484. *
  485. * @return bool
  486. */
  487. public function hasPhoneNumber()
  488. {
  489. return $this->getFeature('can_assign_phone_number');
  490. }
  491. /**
  492. * Does the device support HTTPS?
  493. *
  494. * @return bool
  495. */
  496. public function httpsSupport()
  497. {
  498. return ($this->getFeature('https_support') == 'supported');
  499. }
  500. }