Mobile.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  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. );
  156. /**
  157. * @var array
  158. */
  159. protected static $_haTerms = array(
  160. 'midp',
  161. 'wml',
  162. 'vnd.rim',
  163. 'vnd.wap',
  164. );
  165. /**
  166. * first 4 letters of mobile User Agent chains
  167. *
  168. * @var array
  169. */
  170. protected static $_uaBegin = array(
  171. 'w3c ',
  172. 'acs-',
  173. 'alav',
  174. 'alca',
  175. 'amoi',
  176. 'audi',
  177. 'avan',
  178. 'benq',
  179. 'bird',
  180. 'blac',
  181. 'blaz',
  182. 'brew',
  183. 'cell',
  184. 'cldc',
  185. 'cmd-',
  186. 'dang',
  187. 'doco',
  188. 'eric',
  189. 'hipt',
  190. 'inno',
  191. 'ipaq',
  192. 'java',
  193. 'jigs',
  194. 'kddi',
  195. 'keji',
  196. 'leno',
  197. 'lg-c',
  198. 'lg-d',
  199. 'lg-g',
  200. 'lge-',
  201. 'maui',
  202. 'maxo',
  203. 'midp',
  204. 'mits',
  205. 'mmef',
  206. 'mobi',
  207. 'mot-',
  208. 'moto',
  209. 'mwbp',
  210. 'nec-',
  211. 'newt',
  212. 'noki',
  213. 'oper',
  214. 'palm',
  215. 'pana',
  216. 'pant',
  217. 'phil',
  218. 'play',
  219. 'port',
  220. 'prox',
  221. 'qwap',
  222. 'sage',
  223. 'sams',
  224. 'sany',
  225. 'sch-',
  226. 'sec-',
  227. 'send',
  228. 'seri',
  229. 'sgh-',
  230. 'shar',
  231. 'sie-',
  232. 'siem',
  233. 'smal',
  234. 'smar',
  235. 'sony',
  236. 'sph-',
  237. 'symb',
  238. 't-mo',
  239. 'teli',
  240. 'tim-',
  241. 'tosh',
  242. 'tsm-',
  243. 'upg1',
  244. 'upsi',
  245. 'vk-v',
  246. 'voda',
  247. 'wap-',
  248. 'wapa',
  249. 'wapi',
  250. 'wapp',
  251. 'wapr',
  252. 'webc',
  253. 'winw',
  254. 'winw',
  255. 'xda',
  256. 'xda-',
  257. );
  258. /**
  259. * Comparison of the UserAgent chain and User Agent signatures
  260. *
  261. * @param string $userAgent User Agent chain
  262. * @param array $server $_SERVER like param
  263. * @return bool
  264. */
  265. public static function match($userAgent, $server)
  266. {
  267. // To have a quick identification, try light-weight tests first
  268. if (isset($server['all_http'])) {
  269. if (strpos(strtolower(str_replace(' ', '', $server['all_http'])), 'operam') !== false) {
  270. // Opera Mini or Opera Mobi
  271. return true;
  272. }
  273. }
  274. if (isset($server['http_x_wap_profile']) || isset($server['http_profile'])) {
  275. return true;
  276. }
  277. if (self::_matchAgentAgainstSignatures($userAgent, self::$_haTerms)) {
  278. return true;
  279. }
  280. if (self::userAgentStart($userAgent)) {
  281. return true;
  282. }
  283. if (self::_matchAgentAgainstSignatures($userAgent, self::$_uaSignatures)) {
  284. return true;
  285. }
  286. return false;
  287. }
  288. /**
  289. * Retrieve beginning clause of user agent
  290. *
  291. * @param string $userAgent
  292. * @return string
  293. */
  294. public static function userAgentStart($userAgent)
  295. {
  296. $mobile_ua = strtolower(substr($userAgent, 0, 4));
  297. return (in_array($mobile_ua, self::$_uaBegin));
  298. }
  299. /**
  300. * Constructor
  301. *
  302. * @return void
  303. */
  304. public function __construct($userAgent = null, array $server = array(), array $config = array())
  305. {
  306. // For mobile detection, an adapter must be defined
  307. if (empty($config['mobile']['features'])) {
  308. $config['mobile']['features']['path'] = self::DEFAULT_FEATURES_ADAPTER_PATH;
  309. $config['mobile']['features']['classname'] = self::DEFAULT_FEATURES_ADAPTER_CLASSNAME;
  310. }
  311. parent::__construct($userAgent, $server, $config);
  312. }
  313. /**
  314. * Gives the current browser type
  315. *
  316. * @return string
  317. */
  318. public function getType()
  319. {
  320. return 'mobile';
  321. }
  322. /**
  323. * Look for features
  324. *
  325. * @return string
  326. */
  327. protected function _defineFeatures()
  328. {
  329. $this->setFeature('is_wireless_device', false, 'product_info');
  330. parent::_defineFeatures();
  331. if (!empty($this->_aFeatures["mobile_browser"])) {
  332. $this->setFeature("browser_name", $this->_aFeatures["mobile_browser"]);
  333. }
  334. if (!empty($this->_aFeatures["mobile_browser_version"])) {
  335. $this->setFeature("browser_version", $this->_aFeatures["mobile_browser_version"]);
  336. }
  337. // markup
  338. if ($this->getFeature('device_os') == 'iPhone OS'
  339. || $this->getFeature('device_os_token') == 'iPhone OS'
  340. ) {
  341. $this->setFeature('markup', 'iphone');
  342. } else {
  343. $this->setFeature('markup', $this->getMarkupLanguage($this->getFeature('preferred_markup')));
  344. }
  345. // image format
  346. $this->_images = array();
  347. if ($this->getFeature('png')) {
  348. $this->_images[] = 'png';
  349. }
  350. if ($this->getFeature('jpg')) {
  351. $this->_images[] = 'jpg';
  352. }
  353. if ($this->getFeature('gif')) {
  354. $this->_images[] = 'gif';
  355. }
  356. if ($this->getFeature('wbmp')) {
  357. $this->_images[] = 'wbmp';
  358. }
  359. return $this->_aFeatures;
  360. }
  361. /**
  362. * Determine markup language expected
  363. *
  364. * @access public
  365. * @return __TYPE__
  366. */
  367. public function getMarkupLanguage($preferredMarkup = null)
  368. {
  369. $return = '';
  370. switch ($preferredMarkup) {
  371. case 'wml_1_1':
  372. case 'wml_1_2':
  373. case 'wml_1_3':
  374. $return = 'wml'; //text/vnd.wap.wml encoding="ISO-8859-15"
  375. case 'html_wi_imode_compact_generic':
  376. case 'html_wi_imode_html_1':
  377. case 'html_wi_imode_html_2':
  378. case 'html_wi_imode_html_3':
  379. case 'html_wi_imode_html_4':
  380. case 'html_wi_imode_html_5':
  381. $return = 'chtml'; //text/html
  382. case 'html_wi_oma_xhtmlmp_1_0': //application/vnd.wap.xhtml+xml
  383. case 'html_wi_w3_xhtmlbasic': //application/xhtml+xml DTD XHTML Basic 1.0
  384. $return = 'xhtml';
  385. case 'html_web_3_2': //text/html DTD Html 3.2 Final
  386. case 'html_web_4_0': //text/html DTD Html 4.01 Transitional
  387. $return = '';
  388. }
  389. return $return;
  390. }
  391. /**
  392. * Determine image format support
  393. *
  394. * @return array
  395. */
  396. public function getImageFormatSupport()
  397. {
  398. return $this->_images;
  399. }
  400. /**
  401. * Determine maximum image height supported
  402. *
  403. * @return int
  404. */
  405. public function getMaxImageHeight()
  406. {
  407. return $this->getFeature('max_image_height');
  408. }
  409. /**
  410. * Determine maximum image width supported
  411. *
  412. * @return int
  413. */
  414. public function getMaxImageWidth()
  415. {
  416. return $this->getFeature('max_image_width');
  417. }
  418. /**
  419. * Determine physical screen height
  420. *
  421. * @return int
  422. */
  423. public function getPhysicalScreenHeight()
  424. {
  425. return $this->getFeature('physical_screen_height');
  426. }
  427. /**
  428. * Determine physical screen width
  429. *
  430. * @return int
  431. */
  432. public function getPhysicalScreenWidth()
  433. {
  434. return $this->getFeature('physical_screen_width');
  435. }
  436. /**
  437. * Determine preferred markup
  438. *
  439. * @return string
  440. */
  441. public function getPreferredMarkup()
  442. {
  443. return $this->getFeature("markup");
  444. }
  445. /**
  446. * Determine X/HTML support level
  447. *
  448. * @return int
  449. */
  450. public function getXhtmlSupportLevel()
  451. {
  452. return $this->getFeature('xhtml_support_level');
  453. }
  454. /**
  455. * Does the device support Flash?
  456. *
  457. * @return bool
  458. */
  459. public function hasFlashSupport()
  460. {
  461. return $this->getFeature('fl_browser');
  462. }
  463. /**
  464. * Does the device support PDF?
  465. *
  466. * @return bool
  467. */
  468. public function hasPdfSupport()
  469. {
  470. return $this->getFeature('pdf_support');
  471. }
  472. /**
  473. * Does the device have an associated phone number?
  474. *
  475. * @return bool
  476. */
  477. public function hasPhoneNumber()
  478. {
  479. return $this->getFeature('can_assign_phone_number');
  480. }
  481. /**
  482. * Does the device support HTTPS?
  483. *
  484. * @return bool
  485. */
  486. public function httpsSupport()
  487. {
  488. return ($this->getFeature('https_support') == 'supported');
  489. }
  490. }