PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/joomla/session/session.php

https://github.com/J2MTecnologia/joomla-3.x
PHP | 1013 lines | 447 code | 124 blank | 442 comment | 59 complexity | 58dbbd58e9ca5fc626ee13b0959599ec MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage Session
  5. *
  6. * @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. /**
  11. * Class for managing HTTP sessions
  12. *
  13. * Provides access to session-state values as well as session-level
  14. * settings and lifetime management methods.
  15. * Based on the standard PHP session handling mechanism it provides
  16. * more advanced features such as expire timeouts.
  17. *
  18. * @package Joomla.Platform
  19. * @subpackage Session
  20. * @since 11.1
  21. */
  22. class JSession implements IteratorAggregate
  23. {
  24. /**
  25. * Internal state.
  26. * One of 'inactive'|'active'|'expired'|'destroyed'|'error'
  27. *
  28. * @var string
  29. * @see JSession::getState()
  30. * @since 11.1
  31. */
  32. protected $_state = 'inactive';
  33. /**
  34. * Maximum age of unused session in minutes
  35. *
  36. * @var string
  37. * @since 11.1
  38. */
  39. protected $_expire = 15;
  40. /**
  41. * The session store object.
  42. *
  43. * @var JSessionStorage
  44. * @since 11.1
  45. */
  46. protected $_store = null;
  47. /**
  48. * Security policy.
  49. * List of checks that will be done.
  50. *
  51. * Default values:
  52. * - fix_browser
  53. * - fix_adress
  54. *
  55. * @var array
  56. * @since 11.1
  57. */
  58. protected $_security = array('fix_browser');
  59. /**
  60. * Force cookies to be SSL only
  61. * Default false
  62. *
  63. * @var boolean
  64. * @since 11.1
  65. */
  66. protected $_force_ssl = false;
  67. /**
  68. * JSession instances container.
  69. *
  70. * @var JSession
  71. * @since 11.3
  72. */
  73. protected static $instance;
  74. /**
  75. * The type of storage for the session.
  76. *
  77. * @var string
  78. * @since 12.2
  79. */
  80. protected $storeName;
  81. /**
  82. * Holds the JInput object
  83. *
  84. * @var JInput
  85. * @since 12.2
  86. */
  87. private $_input = null;
  88. /**
  89. * Holds the event dispatcher object
  90. *
  91. * @var JEventDispatcher
  92. * @since 12.2
  93. */
  94. private $_dispatcher = null;
  95. /**
  96. * Constructor
  97. *
  98. * @param string $store The type of storage for the session.
  99. * @param array $options Optional parameters
  100. *
  101. * @since 11.1
  102. */
  103. public function __construct($store = 'none', array $options = array())
  104. {
  105. // Need to destroy any existing sessions started with session.auto_start
  106. if (session_id())
  107. {
  108. session_unset();
  109. session_destroy();
  110. }
  111. // Disable transparent sid support
  112. ini_set('session.use_trans_sid', '0');
  113. // Only allow the session ID to come from cookies and nothing else.
  114. ini_set('session.use_only_cookies', '1');
  115. // Create handler
  116. $this->_store = JSessionStorage::getInstance($store, $options);
  117. $this->storeName = $store;
  118. // Set options
  119. $this->_setOptions($options);
  120. $this->_setCookieParams();
  121. $this->_state = 'inactive';
  122. }
  123. /**
  124. * Magic method to get read-only access to properties.
  125. *
  126. * @param string $name Name of property to retrieve
  127. *
  128. * @return mixed The value of the property
  129. *
  130. * @since 12.2
  131. */
  132. public function __get($name)
  133. {
  134. if ($name === 'storeName')
  135. {
  136. return $this->$name;
  137. }
  138. if ($name === 'state' || $name === 'expire')
  139. {
  140. $property = '_' . $name;
  141. return $this->$property;
  142. }
  143. }
  144. /**
  145. * Returns the global Session object, only creating it
  146. * if it doesn't already exist.
  147. *
  148. * @param string $handler The type of session handler.
  149. * @param array $options An array of configuration options.
  150. *
  151. * @return JSession The Session object.
  152. *
  153. * @since 11.1
  154. */
  155. public static function getInstance($handler, $options)
  156. {
  157. if (!is_object(self::$instance))
  158. {
  159. self::$instance = new JSession($handler, $options);
  160. }
  161. return self::$instance;
  162. }
  163. /**
  164. * Get current state of session
  165. *
  166. * @return string The session state
  167. *
  168. * @since 11.1
  169. */
  170. public function getState()
  171. {
  172. return $this->_state;
  173. }
  174. /**
  175. * Get expiration time in minutes
  176. *
  177. * @return integer The session expiration time in minutes
  178. *
  179. * @since 11.1
  180. */
  181. public function getExpire()
  182. {
  183. return $this->_expire;
  184. }
  185. /**
  186. * Get a session token, if a token isn't set yet one will be generated.
  187. *
  188. * Tokens are used to secure forms from spamming attacks. Once a token
  189. * has been generated the system will check the post request to see if
  190. * it is present, if not it will invalidate the session.
  191. *
  192. * @param boolean $forceNew If true, force a new token to be created
  193. *
  194. * @return string The session token
  195. *
  196. * @since 11.1
  197. */
  198. public function getToken($forceNew = false)
  199. {
  200. $token = $this->get('session.token');
  201. // Create a token
  202. if ($token === null || $forceNew)
  203. {
  204. $token = $this->_createToken(12);
  205. $this->set('session.token', $token);
  206. }
  207. return $token;
  208. }
  209. /**
  210. * Method to determine if a token exists in the session. If not the
  211. * session will be set to expired
  212. *
  213. * @param string $tCheck Hashed token to be verified
  214. * @param boolean $forceExpire If true, expires the session
  215. *
  216. * @return boolean
  217. *
  218. * @since 11.1
  219. */
  220. public function hasToken($tCheck, $forceExpire = true)
  221. {
  222. // Check if a token exists in the session
  223. $tStored = $this->get('session.token');
  224. // Check token
  225. if (($tStored !== $tCheck))
  226. {
  227. if ($forceExpire)
  228. {
  229. $this->_state = 'expired';
  230. }
  231. return false;
  232. }
  233. return true;
  234. }
  235. /**
  236. * Method to determine a hash for anti-spoofing variable names
  237. *
  238. * @param boolean $forceNew If true, force a new token to be created
  239. *
  240. * @return string Hashed var name
  241. *
  242. * @since 11.1
  243. */
  244. public static function getFormToken($forceNew = false)
  245. {
  246. $user = JFactory::getUser();
  247. $session = JFactory::getSession();
  248. // TODO: Decouple from legacy JApplication class.
  249. if (is_callable(array('JApplication', 'getHash')))
  250. {
  251. $hash = JApplication::getHash($user->get('id', 0) . $session->getToken($forceNew));
  252. }
  253. else
  254. {
  255. $hash = md5(JFactory::getApplication()->get('secret') . $user->get('id', 0) . $session->getToken($forceNew));
  256. }
  257. return $hash;
  258. }
  259. /**
  260. * Retrieve an external iterator.
  261. *
  262. * @return ArrayIterator Return an ArrayIterator of $_SESSION.
  263. *
  264. * @since 12.2
  265. */
  266. public function getIterator()
  267. {
  268. return new ArrayIterator($_SESSION);
  269. }
  270. /**
  271. * Checks for a form token in the request.
  272. *
  273. * Use in conjunction with JHtml::_('form.token') or JSession::getFormToken.
  274. *
  275. * @param string $method The request method in which to look for the token key.
  276. *
  277. * @return boolean True if found and valid, false otherwise.
  278. *
  279. * @since 12.1
  280. */
  281. public static function checkToken($method = 'post')
  282. {
  283. $token = self::getFormToken();
  284. $app = JFactory::getApplication();
  285. if (!$app->input->$method->get($token, '', 'alnum'))
  286. {
  287. $session = JFactory::getSession();
  288. if ($session->isNew())
  289. {
  290. // Redirect to login screen.
  291. $app->enqueueMessage(JText::_('JLIB_ENVIRONMENT_SESSION_EXPIRED'), 'warning');
  292. $app->redirect(JRoute::_('index.php'));
  293. }
  294. else
  295. {
  296. return false;
  297. }
  298. }
  299. else
  300. {
  301. return true;
  302. }
  303. }
  304. /**
  305. * Get session name
  306. *
  307. * @return string The session name
  308. *
  309. * @since 11.1
  310. */
  311. public function getName()
  312. {
  313. if ($this->_state === 'destroyed')
  314. {
  315. // @TODO : raise error
  316. return null;
  317. }
  318. return session_name();
  319. }
  320. /**
  321. * Get session id
  322. *
  323. * @return string The session name
  324. *
  325. * @since 11.1
  326. */
  327. public function getId()
  328. {
  329. if ($this->_state === 'destroyed')
  330. {
  331. // @TODO : raise error
  332. return null;
  333. }
  334. return session_id();
  335. }
  336. /**
  337. * Get the session handlers
  338. *
  339. * @return array An array of available session handlers
  340. *
  341. * @since 11.1
  342. */
  343. public static function getStores()
  344. {
  345. $connectors = array();
  346. // Get an iterator and loop trough the driver classes.
  347. $iterator = new DirectoryIterator(__DIR__ . '/storage');
  348. /* @type $file DirectoryIterator */
  349. foreach ($iterator as $file)
  350. {
  351. $fileName = $file->getFilename();
  352. // Only load for php files.
  353. if (!$file->isFile() || $file->getExtension() != 'php')
  354. {
  355. continue;
  356. }
  357. // Derive the class name from the type.
  358. $class = str_ireplace('.php', '', 'JSessionStorage' . ucfirst(trim($fileName)));
  359. // If the class doesn't exist we have nothing left to do but look at the next type. We did our best.
  360. if (!class_exists($class))
  361. {
  362. continue;
  363. }
  364. // Sweet! Our class exists, so now we just need to know if it passes its test method.
  365. if ($class::isSupported())
  366. {
  367. // Connector names should not have file extensions.
  368. $connectors[] = str_ireplace('.php', '', $fileName);
  369. }
  370. }
  371. return $connectors;
  372. }
  373. /**
  374. * Shorthand to check if the session is active
  375. *
  376. * @return boolean
  377. *
  378. * @since 12.2
  379. */
  380. public function isActive()
  381. {
  382. return (bool) ($this->_state == 'active');
  383. }
  384. /**
  385. * Check whether this session is currently created
  386. *
  387. * @return boolean True on success.
  388. *
  389. * @since 11.1
  390. */
  391. public function isNew()
  392. {
  393. $counter = $this->get('session.counter');
  394. return (bool) ($counter === 1);
  395. }
  396. /**
  397. * Check whether this session is currently created
  398. *
  399. * @param JInput $input JInput object for the session to use.
  400. * @param JEventDispatcher $dispatcher Dispatcher object for the session to use.
  401. *
  402. * @return void.
  403. *
  404. * @since 12.2
  405. */
  406. public function initialise(JInput $input, JEventDispatcher $dispatcher = null)
  407. {
  408. $this->_input = $input;
  409. $this->_dispatcher = $dispatcher;
  410. }
  411. /**
  412. * Get data from the session store
  413. *
  414. * @param string $name Name of a variable
  415. * @param mixed $default Default value of a variable if not set
  416. * @param string $namespace Namespace to use, default to 'default'
  417. *
  418. * @return mixed Value of a variable
  419. *
  420. * @since 11.1
  421. */
  422. public function get($name, $default = null, $namespace = 'default')
  423. {
  424. // Add prefix to namespace to avoid collisions
  425. $namespace = '__' . $namespace;
  426. if ($this->_state !== 'active' && $this->_state !== 'expired')
  427. {
  428. // @TODO :: generated error here
  429. $error = null;
  430. return $error;
  431. }
  432. if (isset($_SESSION[$namespace][$name]))
  433. {
  434. return $_SESSION[$namespace][$name];
  435. }
  436. return $default;
  437. }
  438. /**
  439. * Set data into the session store.
  440. *
  441. * @param string $name Name of a variable.
  442. * @param mixed $value Value of a variable.
  443. * @param string $namespace Namespace to use, default to 'default'.
  444. *
  445. * @return mixed Old value of a variable.
  446. *
  447. * @since 11.1
  448. */
  449. public function set($name, $value = null, $namespace = 'default')
  450. {
  451. // Add prefix to namespace to avoid collisions
  452. $namespace = '__' . $namespace;
  453. if ($this->_state !== 'active')
  454. {
  455. // @TODO :: generated error here
  456. return null;
  457. }
  458. $old = isset($_SESSION[$namespace][$name]) ? $_SESSION[$namespace][$name] : null;
  459. if (null === $value)
  460. {
  461. unset($_SESSION[$namespace][$name]);
  462. }
  463. else
  464. {
  465. $_SESSION[$namespace][$name] = $value;
  466. }
  467. return $old;
  468. }
  469. /**
  470. * Check whether data exists in the session store
  471. *
  472. * @param string $name Name of variable
  473. * @param string $namespace Namespace to use, default to 'default'
  474. *
  475. * @return boolean True if the variable exists
  476. *
  477. * @since 11.1
  478. */
  479. public function has($name, $namespace = 'default')
  480. {
  481. // Add prefix to namespace to avoid collisions.
  482. $namespace = '__' . $namespace;
  483. if ($this->_state !== 'active')
  484. {
  485. // @TODO :: generated error here
  486. return null;
  487. }
  488. return isset($_SESSION[$namespace][$name]);
  489. }
  490. /**
  491. * Unset data from the session store
  492. *
  493. * @param string $name Name of variable
  494. * @param string $namespace Namespace to use, default to 'default'
  495. *
  496. * @return mixed The value from session or NULL if not set
  497. *
  498. * @since 11.1
  499. */
  500. public function clear($name, $namespace = 'default')
  501. {
  502. // Add prefix to namespace to avoid collisions
  503. $namespace = '__' . $namespace;
  504. if ($this->_state !== 'active')
  505. {
  506. // @TODO :: generated error here
  507. return null;
  508. }
  509. $value = null;
  510. if (isset($_SESSION[$namespace][$name]))
  511. {
  512. $value = $_SESSION[$namespace][$name];
  513. unset($_SESSION[$namespace][$name]);
  514. }
  515. return $value;
  516. }
  517. /**
  518. * Start a session.
  519. *
  520. * @return void
  521. *
  522. * @since 12.2
  523. */
  524. public function start()
  525. {
  526. if ($this->_state === 'active')
  527. {
  528. return;
  529. }
  530. $this->_start();
  531. $this->_state = 'active';
  532. // Initialise the session
  533. $this->_setCounter();
  534. $this->_setTimers();
  535. // Perform security checks
  536. $this->_validate();
  537. if ($this->_dispatcher instanceof JEventDispatcher)
  538. {
  539. $this->_dispatcher->trigger('onAfterSessionStart');
  540. }
  541. }
  542. /**
  543. * Start a session.
  544. *
  545. * Creates a session (or resumes the current one based on the state of the session)
  546. *
  547. * @return boolean true on success
  548. *
  549. * @since 11.1
  550. */
  551. protected function _start()
  552. {
  553. // Start session if not started
  554. if ($this->_state === 'restart')
  555. {
  556. session_regenerate_id(true);
  557. }
  558. else
  559. {
  560. $session_name = session_name();
  561. // Get the JInputCookie object
  562. $cookie = $this->_input->cookie;
  563. if (is_null($cookie->get($session_name)))
  564. {
  565. $session_clean = $this->_input->get($session_name, false, 'string');
  566. if ($session_clean)
  567. {
  568. session_id($session_clean);
  569. $cookie->set($session_name, '', time() - 3600);
  570. }
  571. }
  572. }
  573. /**
  574. * Write and Close handlers are called after destructing objects since PHP 5.0.5.
  575. * Thus destructors can use sessions but session handler can't use objects.
  576. * So we are moving session closure before destructing objects.
  577. *
  578. * Replace with session_register_shutdown() when dropping compatibility with PHP 5.3
  579. */
  580. register_shutdown_function('session_write_close');
  581. session_cache_limiter('none');
  582. session_start();
  583. return true;
  584. }
  585. /**
  586. * Frees all session variables and destroys all data registered to a session
  587. *
  588. * This method resets the $_SESSION variable and destroys all of the data associated
  589. * with the current session in its storage (file or DB). It forces new session to be
  590. * started after this method is called. It does not unset the session cookie.
  591. *
  592. * @return boolean True on success
  593. *
  594. * @see session_destroy()
  595. * @see session_unset()
  596. * @since 11.1
  597. */
  598. public function destroy()
  599. {
  600. // Session was already destroyed
  601. if ($this->_state === 'destroyed')
  602. {
  603. return true;
  604. }
  605. /*
  606. * In order to kill the session altogether, such as to log the user out, the session id
  607. * must also be unset. If a cookie is used to propagate the session id (default behavior),
  608. * then the session cookie must be deleted.
  609. */
  610. if (isset($_COOKIE[session_name()]))
  611. {
  612. $config = JFactory::getConfig();
  613. $cookie_domain = $config->get('cookie_domain', '');
  614. $cookie_path = $config->get('cookie_path', '/');
  615. setcookie(session_name(), '', time() - 42000, $cookie_path, $cookie_domain);
  616. }
  617. session_unset();
  618. session_destroy();
  619. $this->_state = 'destroyed';
  620. return true;
  621. }
  622. /**
  623. * Restart an expired or locked session.
  624. *
  625. * @return boolean True on success
  626. *
  627. * @see JSession::destroy()
  628. * @since 11.1
  629. */
  630. public function restart()
  631. {
  632. $this->destroy();
  633. if ($this->_state !== 'destroyed')
  634. {
  635. // @TODO :: generated error here
  636. return false;
  637. }
  638. // Re-register the session handler after a session has been destroyed, to avoid PHP bug
  639. $this->_store->register();
  640. $this->_state = 'restart';
  641. // Regenerate session id
  642. session_regenerate_id(true);
  643. $this->_start();
  644. $this->_state = 'active';
  645. $this->_validate();
  646. $this->_setCounter();
  647. return true;
  648. }
  649. /**
  650. * Create a new session and copy variables from the old one
  651. *
  652. * @return boolean $result true on success
  653. *
  654. * @since 11.1
  655. */
  656. public function fork()
  657. {
  658. if ($this->_state !== 'active')
  659. {
  660. // @TODO :: generated error here
  661. return false;
  662. }
  663. // Keep session config
  664. $cookie = session_get_cookie_params();
  665. // Kill session
  666. session_destroy();
  667. // Re-register the session store after a session has been destroyed, to avoid PHP bug
  668. $this->_store->register();
  669. // Restore config
  670. session_set_cookie_params($cookie['lifetime'], $cookie['path'], $cookie['domain'], $cookie['secure'], true);
  671. // Restart session with new id
  672. session_regenerate_id(true);
  673. session_start();
  674. return true;
  675. }
  676. /**
  677. * Writes session data and ends session
  678. *
  679. * Session data is usually stored after your script terminated without the need
  680. * to call JSession::close(), but as session data is locked to prevent concurrent
  681. * writes only one script may operate on a session at any time. When using
  682. * framesets together with sessions you will experience the frames loading one
  683. * by one due to this locking. You can reduce the time needed to load all the
  684. * frames by ending the session as soon as all changes to session variables are
  685. * done.
  686. *
  687. * @return void
  688. *
  689. * @see session_write_close()
  690. * @since 11.1
  691. */
  692. public function close()
  693. {
  694. session_write_close();
  695. }
  696. /**
  697. * Set session cookie parameters
  698. *
  699. * @return void
  700. *
  701. * @since 11.1
  702. */
  703. protected function _setCookieParams()
  704. {
  705. $cookie = session_get_cookie_params();
  706. if ($this->_force_ssl)
  707. {
  708. $cookie['secure'] = true;
  709. }
  710. $config = JFactory::getConfig();
  711. if ($config->get('cookie_domain', '') != '')
  712. {
  713. $cookie['domain'] = $config->get('cookie_domain');
  714. }
  715. if ($config->get('cookie_path', '') != '')
  716. {
  717. $cookie['path'] = $config->get('cookie_path');
  718. }
  719. session_set_cookie_params($cookie['lifetime'], $cookie['path'], $cookie['domain'], $cookie['secure'], true);
  720. }
  721. /**
  722. * Create a token-string
  723. *
  724. * @param integer $length Length of string
  725. *
  726. * @return string Generated token
  727. *
  728. * @since 11.1
  729. */
  730. protected function _createToken($length = 32)
  731. {
  732. static $chars = '0123456789abcdef';
  733. $max = strlen($chars) - 1;
  734. $token = '';
  735. $name = session_name();
  736. for ($i = 0; $i < $length; ++$i)
  737. {
  738. $token .= $chars[(rand(0, $max))];
  739. }
  740. return md5($token . $name);
  741. }
  742. /**
  743. * Set counter of session usage
  744. *
  745. * @return boolean True on success
  746. *
  747. * @since 11.1
  748. */
  749. protected function _setCounter()
  750. {
  751. $counter = $this->get('session.counter', 0);
  752. ++$counter;
  753. $this->set('session.counter', $counter);
  754. return true;
  755. }
  756. /**
  757. * Set the session timers
  758. *
  759. * @return boolean True on success
  760. *
  761. * @since 11.1
  762. */
  763. protected function _setTimers()
  764. {
  765. if (!$this->has('session.timer.start'))
  766. {
  767. $start = time();
  768. $this->set('session.timer.start', $start);
  769. $this->set('session.timer.last', $start);
  770. $this->set('session.timer.now', $start);
  771. }
  772. $this->set('session.timer.last', $this->get('session.timer.now'));
  773. $this->set('session.timer.now', time());
  774. return true;
  775. }
  776. /**
  777. * Set additional session options
  778. *
  779. * @param array $options List of parameter
  780. *
  781. * @return boolean True on success
  782. *
  783. * @since 11.1
  784. */
  785. protected function _setOptions(array $options)
  786. {
  787. // Set name
  788. if (isset($options['name']))
  789. {
  790. session_name(md5($options['name']));
  791. }
  792. // Set id
  793. if (isset($options['id']))
  794. {
  795. session_id($options['id']);
  796. }
  797. // Set expire time
  798. if (isset($options['expire']))
  799. {
  800. $this->_expire = $options['expire'];
  801. }
  802. // Get security options
  803. if (isset($options['security']))
  804. {
  805. $this->_security = explode(',', $options['security']);
  806. }
  807. if (isset($options['force_ssl']))
  808. {
  809. $this->_force_ssl = (bool) $options['force_ssl'];
  810. }
  811. // Sync the session maxlifetime
  812. ini_set('session.gc_maxlifetime', $this->_expire);
  813. return true;
  814. }
  815. /**
  816. * Do some checks for security reason
  817. *
  818. * - timeout check (expire)
  819. * - ip-fixiation
  820. * - browser-fixiation
  821. *
  822. * If one check failed, session data has to be cleaned.
  823. *
  824. * @param boolean $restart Reactivate session
  825. *
  826. * @return boolean True on success
  827. *
  828. * @see http://shiflett.org/articles/the-truth-about-sessions
  829. * @since 11.1
  830. */
  831. protected function _validate($restart = false)
  832. {
  833. // Allow to restart a session
  834. if ($restart)
  835. {
  836. $this->_state = 'active';
  837. $this->set('session.client.address', null);
  838. $this->set('session.client.forwarded', null);
  839. $this->set('session.client.browser', null);
  840. $this->set('session.token', null);
  841. }
  842. // Check if session has expired
  843. if ($this->_expire)
  844. {
  845. $curTime = $this->get('session.timer.now', 0);
  846. $maxTime = $this->get('session.timer.last', 0) + $this->_expire;
  847. // Empty session variables
  848. if ($maxTime < $curTime)
  849. {
  850. $this->_state = 'expired';
  851. return false;
  852. }
  853. }
  854. // Record proxy forwarded for in the session in case we need it later
  855. if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
  856. {
  857. $this->set('session.client.forwarded', $_SERVER['HTTP_X_FORWARDED_FOR']);
  858. }
  859. // Check for client address
  860. if (in_array('fix_adress', $this->_security) && isset($_SERVER['REMOTE_ADDR']))
  861. {
  862. $ip = $this->get('session.client.address');
  863. if ($ip === null)
  864. {
  865. $this->set('session.client.address', $_SERVER['REMOTE_ADDR']);
  866. }
  867. elseif ($_SERVER['REMOTE_ADDR'] !== $ip)
  868. {
  869. $this->_state = 'error';
  870. return false;
  871. }
  872. }
  873. // Check for clients browser
  874. if (in_array('fix_browser', $this->_security) && isset($_SERVER['HTTP_USER_AGENT']))
  875. {
  876. $browser = $this->get('session.client.browser');
  877. if ($browser === null)
  878. {
  879. $this->set('session.client.browser', $_SERVER['HTTP_USER_AGENT']);
  880. }
  881. elseif ($_SERVER['HTTP_USER_AGENT'] !== $browser)
  882. {
  883. // @todo remove code: $this->_state = 'error';
  884. // @todo remove code: return false;
  885. }
  886. }
  887. return true;
  888. }
  889. }