PageRenderTime 29ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/library/Zend/Http/UserAgent/AbstractDevice.php

https://bitbucket.org/Ebozavrik/test-application
PHP | 1013 lines | 602 code | 100 blank | 311 comment | 152 complexity | 8984de4c371994d1bcf57e563f1ec4ba MD5 | raw file
  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-2012 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/Device.php';
  22. /**
  23. * Abstract Class to define a browser device.
  24. *
  25. * @category Zend
  26. * @package Zend_Http
  27. * @subpackage UserAgent
  28. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. abstract class Zend_Http_UserAgent_AbstractDevice
  32. implements Zend_Http_UserAgent_Device
  33. {
  34. /**
  35. * Browser signature
  36. *
  37. * @var string
  38. */
  39. protected $_browser = '';
  40. /**
  41. * Browser version
  42. *
  43. * @var string
  44. */
  45. protected $_browserVersion = '';
  46. /**
  47. * Configuration
  48. *
  49. * @var array
  50. */
  51. protected $_config;
  52. /**
  53. * User Agent chain
  54. *
  55. * @var string
  56. */
  57. protected $_userAgent;
  58. /**
  59. * Server variable
  60. *
  61. * @var array
  62. */
  63. protected $_server;
  64. /**
  65. * Image types
  66. *
  67. * @var array
  68. */
  69. protected $_images = array(
  70. 'jpeg',
  71. 'gif',
  72. 'png',
  73. 'pjpeg',
  74. 'x-png',
  75. 'bmp',
  76. );
  77. /**
  78. * Browser/Device features
  79. *
  80. * @var array
  81. */
  82. protected $_aFeatures = array();
  83. /**
  84. * Browser/Device features groups
  85. *
  86. * @var array
  87. */
  88. protected $_aGroup = array();
  89. /**
  90. * Constructor
  91. *
  92. * @param null|string|array $userAgent If array, restores from serialized version
  93. * @param array $server
  94. * @param array $config
  95. *
  96. * @return void
  97. */
  98. public function __construct ($userAgent = null, array $server = array(), array $config = array())
  99. {
  100. if (is_array($userAgent)) {
  101. // Restoring from serialized array
  102. $this->_restoreFromArray($userAgent);
  103. } else {
  104. // Constructing new object
  105. $this->setUserAgent($userAgent);
  106. $this->_server = $server;
  107. $this->_config = $config;
  108. $this->_getDefaultFeatures();
  109. $this->_defineFeatures();
  110. }
  111. }
  112. /**
  113. * Serialize object
  114. *
  115. * @return string
  116. */
  117. public function serialize ()
  118. {
  119. $spec = array(
  120. '_aFeatures' => $this->_aFeatures,
  121. '_aGroup' => $this->_aGroup,
  122. '_browser' => $this->_browser,
  123. '_browserVersion' => $this->_browserVersion,
  124. '_userAgent' => $this->_userAgent,
  125. '_images' => $this->_images,
  126. );
  127. return serialize($spec);
  128. }
  129. /**
  130. * Unserialize
  131. *
  132. * @param string $serialized
  133. *
  134. * @return void
  135. */
  136. public function unserialize ($serialized)
  137. {
  138. $spec = unserialize($serialized);
  139. $this->_restoreFromArray($spec);
  140. }
  141. /**
  142. * Restore object state from array
  143. *
  144. * @param array $spec
  145. *
  146. * @return void
  147. */
  148. protected function _restoreFromArray (array $spec)
  149. {
  150. foreach ($spec as $key => $value) {
  151. if (property_exists($this, $key)) {
  152. $this->{$key} = $value;
  153. }
  154. }
  155. }
  156. /**
  157. * Look for features
  158. *
  159. * @return array|null
  160. */
  161. protected function _defineFeatures ()
  162. {
  163. $features = $this->_loadFeaturesAdapter();
  164. if (is_array($features)) {
  165. $this->_aFeatures = array_merge($this->_aFeatures, $features);
  166. }
  167. return $this->_aFeatures;
  168. }
  169. /**
  170. * Gets the browser type identifier
  171. *
  172. * @return string
  173. */
  174. abstract public function getType ();
  175. /**
  176. * Check a feature for the current browser/device.
  177. *
  178. * @param string $feature The feature to check.
  179. *
  180. * @return bool
  181. */
  182. public function hasFeature ($feature)
  183. {
  184. return ( !empty( $this->_aFeatures[$feature] ) );
  185. }
  186. /**
  187. * Gets the value of the current browser/device feature
  188. *
  189. * @param string $feature Feature to search
  190. *
  191. * @return string|null
  192. */
  193. public function getFeature ($feature)
  194. {
  195. if ($this->hasFeature($feature)) {
  196. return $this->_aFeatures[$feature];
  197. }
  198. }
  199. /**
  200. * Set a feature for the current browser/device.
  201. *
  202. * @param string $feature The feature to set.
  203. * @param string $value (option) feature value.
  204. * @param string $group (option) Group to associate with the feature
  205. *
  206. * @return Zend_Http_UserAgent_AbstractDevice
  207. */
  208. public function setFeature ($feature, $value = false, $group = '')
  209. {
  210. $this->_aFeatures[$feature] = $value;
  211. if (!empty( $group )) {
  212. $this->setGroup($group, $feature);
  213. }
  214. return $this;
  215. }
  216. /**
  217. * Affects a feature to a group
  218. *
  219. * @param string $group Group name
  220. * @param string $feature Feature name
  221. *
  222. * @return Zend_Http_UserAgent_AbstractDevice
  223. */
  224. public function setGroup ($group, $feature)
  225. {
  226. if (!isset( $this->_aGroup[$group] )) {
  227. $this->_aGroup[$group] = array();
  228. }
  229. if (!in_array($feature, $this->_aGroup[$group])) {
  230. $this->_aGroup[$group][] = $feature;
  231. }
  232. return $this;
  233. }
  234. /**
  235. * Gets an array of features associated to a group
  236. *
  237. * @param string $group Group param
  238. *
  239. * @return array
  240. */
  241. public function getGroup ($group)
  242. {
  243. return $this->_aGroup[$group];
  244. }
  245. /**
  246. * Gets all the browser/device features
  247. *
  248. * @return array
  249. */
  250. public function getAllFeatures ()
  251. {
  252. return $this->_aFeatures;
  253. }
  254. /**
  255. * Gets all the browser/device features' groups
  256. *
  257. * @return array
  258. */
  259. public function getAllGroups ()
  260. {
  261. return $this->_aGroup;
  262. }
  263. /**
  264. * Sets all the standard features extracted from the User Agent chain and $this->_server
  265. * vars
  266. *
  267. * @return void
  268. */
  269. protected function _getDefaultFeatures ()
  270. {
  271. $server = array();
  272. // gets info from user agent chain
  273. $uaExtract = $this->extractFromUserAgent($this->getUserAgent());
  274. if (is_array($uaExtract)) {
  275. foreach ($uaExtract as $key => $info) {
  276. $this->setFeature($key, $info, 'product_info');
  277. }
  278. }
  279. if (isset( $uaExtract['browser_name'] )) {
  280. $this->_browser = $uaExtract['browser_name'];
  281. }
  282. if (isset( $uaExtract['browser_version'] )) {
  283. $this->_browserVersion = $uaExtract['browser_version'];
  284. }
  285. if (isset( $uaExtract['device_os'] )) {
  286. $this->device_os = $uaExtract['device_os_name'];
  287. }
  288. /* browser & device info */
  289. $this->setFeature('is_wireless_device', false, 'product_info');
  290. $this->setFeature('is_mobile', false, 'product_info');
  291. $this->setFeature('is_desktop', false, 'product_info');
  292. $this->setFeature('is_tablet', false, 'product_info');
  293. $this->setFeature('is_bot', false, 'product_info');
  294. $this->setFeature('is_email', false, 'product_info');
  295. $this->setFeature('is_text', false, 'product_info');
  296. $this->setFeature('device_claims_web_support', false, 'product_info');
  297. $this->setFeature('is_' . strtolower($this->getType()), true, 'product_info');
  298. /* sets the browser name */
  299. if (isset( $this->list ) && empty( $this->_browser )) {
  300. $lowerUserAgent = strtolower($this->getUserAgent());
  301. foreach ($this->list as $browser_signature) {
  302. if (strpos($lowerUserAgent, $browser_signature) !== false) {
  303. $this->_browser = strtolower($browser_signature);
  304. $this->setFeature('browser_name', $this->_browser, 'product_info');
  305. }
  306. }
  307. }
  308. /* sets the client IP */
  309. if (isset( $this->_server['remote_addr'] )) {
  310. $this->setFeature('client_ip', $this->_server['remote_addr'], 'product_info');
  311. } elseif (isset( $this->_server['http_x_forwarded_for'] )) {
  312. $this->setFeature('client_ip', $this->_server['http_x_forwarded_for'], 'product_info');
  313. } elseif (isset( $this->_server['http_client_ip'] )) {
  314. $this->setFeature('client_ip', $this->_server['http_client_ip'], 'product_info');
  315. }
  316. /* sets the server infos */
  317. if (isset( $this->_server['server_software'] )) {
  318. if (strpos($this->_server['server_software'], 'Apache') !== false || strpos($this->_server['server_software'], 'LiteSpeed') !== false) {
  319. $server['version'] = 1;
  320. if (strpos($this->_server['server_software'], 'Apache/2') !== false) {
  321. $server['version'] = 2;
  322. }
  323. $server['server'] = 'apache';
  324. }
  325. if (strpos($this->_server['server_software'], 'Microsoft-IIS') !== false) {
  326. $server['server'] = 'iis';
  327. }
  328. if (strpos($this->_server['server_software'], 'Unix') !== false) {
  329. $server['os'] = 'unix';
  330. if (isset( $_ENV['MACHTYPE'] )) {
  331. if (strpos($_ENV['MACHTYPE'], 'linux') !== false) {
  332. $server['os'] = 'linux';
  333. }
  334. }
  335. } elseif (strpos($this->_server['server_software'], 'Win') !== false) {
  336. $server['os'] = 'windows';
  337. }
  338. if (preg_match('/Apache\/([0-9\.]*)/', $this->_server['server_software'], $arr)) {
  339. if ($arr[1]) {
  340. $server['version'] = $arr[1];
  341. $server['server'] = 'apache';
  342. }
  343. }
  344. }
  345. $this->setFeature('php_version', phpversion(), 'server_info');
  346. if (isset( $server['server'] )) {
  347. $this->setFeature('server_os', $server['server'], 'server_info');
  348. }
  349. if (isset( $server['version'] )) {
  350. $this->setFeature('server_os_version', $server['version'], 'server_info');
  351. }
  352. if (isset( $this->_server['http_accept'] )) {
  353. $this->setFeature('server_http_accept', $this->_server['http_accept'], 'server_info');
  354. }
  355. if (isset( $this->_server['http_accept_language'] )) {
  356. $this->setFeature('server_http_accept_language', $this->_server['http_accept_language'], 'server_info');
  357. }
  358. if (isset( $this->_server['server_addr'] )) {
  359. $this->setFeature('server_ip', $this->_server['server_addr'], 'server_info');
  360. }
  361. if (isset( $this->_server['server_name'] )) {
  362. $this->setFeature('server_name', $this->_server['server_name'], 'server_info');
  363. }
  364. }
  365. /**
  366. * Extract and sets informations from the User Agent chain
  367. *
  368. * @param string $userAgent User Agent chain
  369. *
  370. * @return array
  371. */
  372. public static function extractFromUserAgent ($userAgent)
  373. {
  374. $userAgent = trim($userAgent);
  375. /**
  376. * @see http://www.texsoft.it/index.php?c=software&m=sw.php.useragent&l=it
  377. */
  378. $pattern = "(([^/\s]*)(/(\S*))?)(\s*\[[a-zA-Z][a-zA-Z]\])?\s*(\\((([^()]|(\\([^()]*\\)))*)\\))?\s*";
  379. preg_match("#^$pattern#", $userAgent, $match);
  380. $comment = array();
  381. if (isset( $match[7] )) {
  382. $comment = explode(';', $match[7]);
  383. }
  384. // second part if exists
  385. $end = substr($userAgent, strlen($match[0]));
  386. if (!empty( $end )) {
  387. $result['others']['full'] = $end;
  388. }
  389. $match2 = array();
  390. if (isset( $result['others'] )) {
  391. preg_match_all('/(([^\/\s]*)(\/)?([^\/\(\)\s]*)?)(\s\((([^\)]*)*)\))?/i', $result['others']['full'], $match2);
  392. }
  393. $result['user_agent'] = trim($match[1]);
  394. $result['product_name'] = isset( $match[2] ) ? trim($match[2]) : '';
  395. $result['browser_name'] = $result['product_name'];
  396. if (isset( $match[4] ) && trim($match[4])) {
  397. $result['product_version'] = trim($match[4]);
  398. $result['browser_version'] = trim($match[4]);
  399. }
  400. if (count($comment) && !empty( $comment[0] )) {
  401. $result['comment']['full'] = trim($match[7]);
  402. $result['comment']['detail'] = $comment;
  403. $result['compatibility_flag'] = trim($comment[0]);
  404. if (isset( $comment[1] )) {
  405. $result['browser_token'] = trim($comment[1]);
  406. }
  407. if (isset( $comment[2] )) {
  408. $result['device_os_token'] = trim($comment[2]);
  409. }
  410. }
  411. if (empty( $result['device_os_token'] ) && !empty( $result['compatibility_flag'] )) {
  412. // some browsers do not have a platform token
  413. $result['device_os_token'] = $result['compatibility_flag'];
  414. }
  415. if ($match2) {
  416. $i = 0;
  417. $max = count($match2[0]);
  418. for ($i = 0; $i < $max; $i++) {
  419. if (!empty( $match2[0][$i] )) {
  420. $result['others']['detail'][] = array(
  421. $match2[0][$i],
  422. $match2[2][$i],
  423. $match2[4][$i],
  424. );
  425. }
  426. }
  427. }
  428. /** Security level */
  429. $security = array(
  430. 'N' => 'no security',
  431. 'U' => 'strong security',
  432. 'I' => 'weak security',
  433. );
  434. if (!empty( $result['browser_token'] )) {
  435. if (isset( $security[$result['browser_token']] )) {
  436. $result['security_level'] = $security[$result['browser_token']];
  437. unset( $result['browser_token'] );
  438. }
  439. }
  440. $product = strtolower($result['browser_name']);
  441. // Mozilla : true && false
  442. $compatibleOrIe = false;
  443. if (isset( $result['compatibility_flag'] ) && isset( $result['comment'] )) {
  444. $compatibleOrIe = ( $result['compatibility_flag'] == 'compatible' || strpos($result['comment']['full'], "MSIE") !== false );
  445. }
  446. if ($product == 'mozilla' && $compatibleOrIe) {
  447. if (!empty( $result['browser_token'] )) {
  448. // Classic Mozilla chain
  449. preg_match_all('/([^\/\s].*)(\/|\s)(.*)/i', $result['browser_token'], $real);
  450. } else {
  451. // MSIE specific chain with 'Windows' compatibility flag
  452. foreach ($result['comment']['detail'] as $v) {
  453. if (strpos($v, 'MSIE') !== false) {
  454. $real[0][1] = trim($v);
  455. $result['browser_engine'] = "MSIE";
  456. $real[1][0] = "Internet Explorer";
  457. $temp = explode(' ', trim($v));
  458. $real[3][0] = $temp[1];
  459. }
  460. if (strpos($v, 'Win') !== false) {
  461. $result['device_os_token'] = trim($v);
  462. }
  463. }
  464. }
  465. if (!empty( $real[0] )) {
  466. $result['browser_name'] = $real[1][0];
  467. $result['browser_version'] = $real[3][0];
  468. } else {
  469. if (isset( $result['browser_token'] )) {
  470. $result['browser_name'] = $result['browser_token'];
  471. }
  472. $result['browser_version'] = '??';
  473. }
  474. } elseif ($product == 'mozilla' && $result['browser_version'] < 5.0) {
  475. // handles the real Mozilla (or old Netscape if version < 5.0)
  476. $result['browser_name'] = 'Netscape';
  477. }
  478. /** windows */
  479. if ($result['browser_name'] == 'MSIE') {
  480. $result['browser_engine'] = 'MSIE';
  481. $result['browser_name'] = 'Internet Explorer';
  482. }
  483. if (isset( $result['device_os_token'] )) {
  484. if (strpos($result['device_os_token'], 'Win') !== false) {
  485. $windows = array(
  486. 'Windows NT 6.1' => 'Windows 7',
  487. 'Windows NT 6.0' => 'Windows Vista',
  488. 'Windows NT 5.2' => 'Windows Server 2003',
  489. 'Windows NT 5.1' => 'Windows XP',
  490. 'Windows NT 5.01' => 'Windows 2000 SP1',
  491. 'Windows NT 5.0' => 'Windows 2000',
  492. 'Windows NT 4.0' => 'Microsoft Windows NT 4.0',
  493. 'WinNT' => 'Microsoft Windows NT 4.0',
  494. 'Windows 98; Win 9x 4.90' => 'Windows Me',
  495. 'Windows 98' => 'Windows 98',
  496. 'Win98' => 'Windows 98',
  497. 'Windows 95' => 'Windows 95',
  498. 'Win95' => 'Windows 95',
  499. 'Windows CE' => 'Windows CE',
  500. );
  501. if (isset( $windows[$result['device_os_token']] )) {
  502. $result['device_os_name'] = $windows[$result['device_os_token']];
  503. } else {
  504. $result['device_os_name'] = $result['device_os_token'];
  505. }
  506. }
  507. }
  508. // iphone
  509. $apple_device = array(
  510. 'iPhone',
  511. 'iPod',
  512. 'iPad',
  513. );
  514. if (isset( $result['compatibility_flag'] )) {
  515. if (in_array($result['compatibility_flag'], $apple_device)) {
  516. $result['device'] = strtolower($result['compatibility_flag']);
  517. $result['device_os_token'] = 'iPhone OS';
  518. if (isset( $comment[3] )) {
  519. $result['browser_language'] = trim($comment[3]);
  520. }
  521. if (isset( $result['others']['detail'][1] )) {
  522. $result['browser_version'] = $result['others']['detail'][1][2];
  523. } elseif (isset( $result['others']['detail'] ) && count($result['others']['detail'])) {
  524. $result['browser_version'] = $result['others']['detail'][0][2];
  525. }
  526. if (!empty( $result['others']['detail'][2] )) {
  527. $result['firmware'] = $result['others']['detail'][2][2];
  528. }
  529. if (!empty( $result['others']['detail'][3] )) {
  530. $result['browser_name'] = $result['others']['detail'][3][1];
  531. $result['browser_build'] = $result['others']['detail'][3][2];
  532. }
  533. }
  534. }
  535. // Safari
  536. if (isset( $result['others'] )) {
  537. if ($result['others']['detail'][0][1] == 'AppleWebKit') {
  538. $result['browser_engine'] = 'AppleWebKit';
  539. if (isset( $result['others']['detail'][1] ) && $result['others']['detail'][1][1] == 'Version') {
  540. $result['browser_version'] = $result['others']['detail'][1][2];
  541. } else {
  542. $result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][2];
  543. }
  544. if (isset( $comment[3] )) {
  545. $result['browser_language'] = trim($comment[3]);
  546. }
  547. $last = $result['others']['detail'][count($result['others']['detail']) - 1][1];
  548. if (empty( $result['others']['detail'][2][1] ) || $result['others']['detail'][2][1] == 'Safari') {
  549. if (isset( $result['others']['detail'][1] )) {
  550. $result['browser_name'] = ( $result['others']['detail'][1][1] && $result['others']['detail'][1][1] != 'Version' ? $result['others']['detail'][1][1] : 'Safari' );
  551. $result['browser_version'] = ( $result['others']['detail'][1][2] ? $result['others']['detail'][1][2] : $result['others']['detail'][0][2] );
  552. } else {
  553. $result['browser_name'] = ( $result['others']['detail'][0][1] && $result['others']['detail'][0][1] != 'Version' ? $result['others']['detail'][0][1] : 'Safari' );
  554. $result['browser_version'] = $result['others']['detail'][0][2];
  555. }
  556. } else {
  557. $result['browser_name'] = $result['others']['detail'][2][1];
  558. $result['browser_version'] = $result['others']['detail'][2][2];
  559. // mobile version
  560. if ($result['browser_name'] == 'Mobile') {
  561. $result['browser_name'] = 'Safari ' . $result['browser_name'];
  562. if ($result['others']['detail'][1][1] == 'Version') {
  563. $result['browser_version'] = $result['others']['detail'][1][2];
  564. }
  565. }
  566. }
  567. // For Safari < 2.2, AppleWebKit version gives the Safari version
  568. if (strpos($result['browser_version'], '.') > 2 || (int)$result['browser_version'] > 20) {
  569. $temp = explode('.', $result['browser_version']);
  570. $build = (int)$temp[0];
  571. $awkVersion = array(
  572. 48 => '0.8',
  573. 73 => '0.9',
  574. 85 => '1.0',
  575. 103 => '1.1',
  576. 124 => '1.2',
  577. 300 => '1.3',
  578. 400 => '2.0',
  579. );
  580. foreach ($awkVersion as $k => $v) {
  581. if ($build >= $k) {
  582. $result['browser_version'] = $v;
  583. }
  584. }
  585. }
  586. }
  587. // Gecko (Firefox or compatible)
  588. if ($result['others']['detail'][0][1] == 'Gecko') {
  589. $searchRV = true;
  590. if (!empty( $result['others']['detail'][1][1] ) && !empty( $result['others']['detail'][count($result['others']['detail']) - 1][2] ) || strpos(strtolower($result['others']['full']), 'opera') !== false) {
  591. $searchRV = false;
  592. $result['browser_engine'] = $result['others']['detail'][0][1];
  593. // the name of the application is at the end indepenently
  594. // of quantity of information in $result['others']['detail']
  595. $last = count($result['others']['detail']) - 1;
  596. // exception : if the version of the last information is
  597. // empty we take the previous one
  598. if (empty( $result['others']['detail'][$last][2] )) {
  599. $last--;
  600. }
  601. // exception : if the last one is 'Red Hat' or 'Debian' =>
  602. // use rv: to find browser_version */
  603. if (in_array($result['others']['detail'][$last][1], array(
  604. 'Debian',
  605. 'Hat',
  606. ))
  607. ) {
  608. $searchRV = true;
  609. }
  610. $result['browser_name'] = $result['others']['detail'][$last][1];
  611. $result['browser_version'] = $result['others']['detail'][$last][2];
  612. if (isset( $comment[4] )) {
  613. $result['browser_build'] = trim($comment[4]);
  614. }
  615. if (isset( $comment[3] )) {
  616. $result['browser_language'] = trim($comment[3]);
  617. }
  618. // Netscape
  619. if ($result['browser_name'] == 'Navigator' || $result['browser_name'] == 'Netscape6') {
  620. $result['browser_name'] = 'Netscape';
  621. }
  622. }
  623. if ($searchRV) {
  624. // Mozilla alone : the version is identified by rv:
  625. $result['browser_name'] = 'Mozilla';
  626. if (isset( $result['comment']['detail'] )) {
  627. foreach ($result['comment']['detail'] as $rv) {
  628. if (strpos($rv, 'rv:') !== false) {
  629. $result['browser_version'] = trim(str_replace('rv:', '', $rv));
  630. }
  631. }
  632. }
  633. }
  634. }
  635. // Netscape
  636. if ($result['others']['detail'][0][1] == 'Netscape') {
  637. $result['browser_name'] = 'Netscape';
  638. $result['browser_version'] = $result['others']['detail'][0][2];
  639. }
  640. // Opera
  641. // Opera: engine Presto
  642. if ($result['others']['detail'][0][1] == 'Presto') {
  643. $result['browser_engine'] = 'Presto';
  644. if (!empty( $result['others']['detail'][1][2] )) {
  645. $result['browser_version'] = $result['others']['detail'][1][2];
  646. }
  647. }
  648. // UA ends with 'Opera X.XX' or 'Opera/X.XX'
  649. if ($result['others']['detail'][0][1] == 'Opera') {
  650. $result['browser_name'] = $result['others']['detail'][0][1];
  651. // Opera X.XX
  652. if (isset( $result['others']['detail'][1][1] )) {
  653. $result['browser_version'] = $result['others']['detail'][1][1];
  654. // Opera/X.XX
  655. } elseif (isset( $result['others']['detail'][0][2] )) {
  656. $result['browser_version'] = $result['others']['detail'][0][2];
  657. }
  658. }
  659. // Opera Mini
  660. if (isset( $result["browser_token"] )) {
  661. if (strpos($result["browser_token"], 'Opera Mini') !== false) {
  662. $result['browser_name'] = 'Opera Mini';
  663. }
  664. }
  665. // Symbian
  666. if ($result['others']['detail'][0][1] == 'SymbianOS') {
  667. $result['device_os_token'] = 'SymbianOS';
  668. }
  669. }
  670. // UA ends with 'Opera X.XX'
  671. if (isset( $result['browser_name'] ) && isset( $result['browser_engine'] )) {
  672. if ($result['browser_name'] == 'Opera' && $result['browser_engine'] == 'Gecko' && empty( $result['browser_version'] )) {
  673. $result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][1];
  674. }
  675. }
  676. // cleanup
  677. if (isset( $result['browser_version'] ) && isset( $result['browser_build'] )) {
  678. if ($result['browser_version'] == $result['browser_build']) {
  679. unset( $result['browser_build'] );
  680. }
  681. }
  682. // compatibility
  683. $compatibility['AppleWebKit'] = 'Safari';
  684. $compatibility['Gecko'] = 'Firefox';
  685. $compatibility['MSIE'] = 'Internet Explorer';
  686. $compatibility['Presto'] = 'Opera';
  687. if (!empty( $result['browser_engine'] )) {
  688. if (isset( $compatibility[$result['browser_engine']] )) {
  689. $result['browser_compatibility'] = $compatibility[$result['browser_engine']];
  690. }
  691. }
  692. ksort($result);
  693. return $result;
  694. }
  695. /**
  696. * Loads the Features Adapter if it's defined in the $config array
  697. * Otherwise, nothing is done
  698. *
  699. * @param string $browserType Browser type
  700. *
  701. * @return array
  702. */
  703. protected function _loadFeaturesAdapter ()
  704. {
  705. $config = $this->_config;
  706. $browserType = $this->getType();
  707. if (!isset( $config[$browserType] ) || !isset( $config[$browserType]['features'] )) {
  708. return array();
  709. }
  710. $config = $config[$browserType]['features'];
  711. if (empty( $config['classname'] )) {
  712. require_once 'Zend/Http/UserAgent/Exception.php';
  713. throw new Zend_Http_UserAgent_Exception( 'The ' . $this->getType() . ' features adapter must have a "classname" config parameter defined' );
  714. }
  715. $className = $config['classname'];
  716. if (!class_exists($className)) {
  717. if (isset( $config['path'] )) {
  718. $path = $config['path'];
  719. } else {
  720. require_once 'Zend/Http/UserAgent/Exception.php';
  721. throw new Zend_Http_UserAgent_Exception( 'The ' . $this->getType() . ' features adapter must have a "path" config parameter defined' );
  722. }
  723. if (false === include_once ( $path )) {
  724. require_once 'Zend/Http/UserAgent/Exception.php';
  725. throw new Zend_Http_UserAgent_Exception( 'The ' . $this->getType() . ' features adapter path that does not exist' );
  726. }
  727. }
  728. return call_user_func(array( $className, 'getFromRequest' ), $this->_server, $this->_config);
  729. }
  730. /**
  731. * Retrieve image format support
  732. *
  733. * @return array
  734. */
  735. public function getImageFormatSupport ()
  736. {
  737. return $this->_images;
  738. }
  739. /**
  740. * Get maximum image height supported by this device
  741. *
  742. * @return int
  743. */
  744. public function getMaxImageHeight ()
  745. {
  746. return null;
  747. }
  748. /**
  749. * Get maximum image width supported by this device
  750. *
  751. * @return int
  752. */
  753. public function getMaxImageWidth ()
  754. {
  755. return null;
  756. }
  757. /**
  758. * Get physical screen height of this device
  759. *
  760. * @return int
  761. */
  762. public function getPhysicalScreenHeight ()
  763. {
  764. return null;
  765. }
  766. /**
  767. * Get physical screen width of this device
  768. *
  769. * @return int
  770. */
  771. public function getPhysicalScreenWidth ()
  772. {
  773. return null;
  774. }
  775. /**
  776. * Get preferred markup type
  777. *
  778. * @return string
  779. */
  780. public function getPreferredMarkup ()
  781. {
  782. return 'xhtml';
  783. }
  784. /**
  785. * Get supported X/HTML version
  786. *
  787. * @return int
  788. */
  789. public function getXhtmlSupportLevel ()
  790. {
  791. return 4;
  792. }
  793. /**
  794. * Does the device support Flash?
  795. *
  796. * @return bool
  797. */
  798. public function hasFlashSupport ()
  799. {
  800. return true;
  801. }
  802. /**
  803. * Does the device support PDF?
  804. *
  805. * @return bool
  806. */
  807. public function hasPdfSupport ()
  808. {
  809. return true;
  810. }
  811. /**
  812. * Does the device have a phone number associated with it?
  813. *
  814. * @return bool
  815. */
  816. public function hasPhoneNumber ()
  817. {
  818. return false;
  819. }
  820. /**
  821. * Does the device support HTTPS?
  822. *
  823. * @return bool
  824. */
  825. public function httpsSupport ()
  826. {
  827. return true;
  828. }
  829. /**
  830. * Get the browser type
  831. *
  832. * @return string
  833. */
  834. public function getBrowser ()
  835. {
  836. return $this->_browser;
  837. }
  838. /**
  839. * Get the browser version
  840. *
  841. * @return string
  842. */
  843. public function getBrowserVersion ()
  844. {
  845. return $this->_browserVersion;
  846. }
  847. /**
  848. * Get the user agent string
  849. *
  850. * @return string
  851. */
  852. public function getUserAgent ()
  853. {
  854. return $this->_userAgent;
  855. }
  856. /**
  857. * @return the $_images
  858. */
  859. public function getImages ()
  860. {
  861. return $this->_images;
  862. }
  863. /**
  864. * @param string $browser
  865. */
  866. public function setBrowser ($browser)
  867. {
  868. $this->_browser = $browser;
  869. }
  870. /**
  871. * @param string $browserVersion
  872. */
  873. public function setBrowserVersion ($browserVersion)
  874. {
  875. $this->_browserVersion = $browserVersion;
  876. }
  877. /**
  878. * @param string $userAgent
  879. */
  880. public function setUserAgent ($userAgent)
  881. {
  882. $this->_userAgent = $userAgent;
  883. return $this;
  884. }
  885. /**
  886. * @param array $_images
  887. */
  888. public function setImages ($_images)
  889. {
  890. $this->_images = $_images;
  891. }
  892. /**
  893. * Match a user agent string against a list of signatures
  894. *
  895. * @param string $userAgent
  896. * @param array $signatures
  897. *
  898. * @return bool
  899. */
  900. protected static function _matchAgentAgainstSignatures ($userAgent, $signatures)
  901. {
  902. $userAgent = strtolower($userAgent);
  903. foreach ($signatures as $signature) {
  904. if (!empty( $signature )) {
  905. if (strpos($userAgent, $signature) !== false) {
  906. // Browser signature was found in user agent string
  907. return true;
  908. }
  909. }
  910. }
  911. return false;
  912. }
  913. }