Teknik is a suite of services with attractive and functional interfaces. https://www.teknik.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Session.php 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <?php
  2. /**
  3. * Piwik - free/libre analytics platform
  4. *
  5. * @link http://piwik.org
  6. * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  7. *
  8. */
  9. namespace Piwik;
  10. use Exception;
  11. use Piwik\Session\SaveHandler\DbTable;
  12. use Zend_Session;
  13. /**
  14. * Session initialization.
  15. */
  16. class Session extends Zend_Session
  17. {
  18. const SESSION_NAME = 'PIWIK_SESSID';
  19. protected static $sessionStarted = false;
  20. /**
  21. * Are we using file-based session store?
  22. *
  23. * @return bool True if file-based; false otherwise
  24. */
  25. public static function isFileBasedSessions()
  26. {
  27. $config = Config::getInstance();
  28. return !isset($config->General['session_save_handler'])
  29. || $config->General['session_save_handler'] === 'files';
  30. }
  31. /**
  32. * Start the session
  33. *
  34. * @param array|bool $options An array of configuration options; the auto-start (bool) setting is ignored
  35. * @return void
  36. */
  37. public static function start($options = false)
  38. {
  39. if (headers_sent()
  40. || self::$sessionStarted
  41. || (defined('PIWIK_ENABLE_SESSION_START') && !PIWIK_ENABLE_SESSION_START)
  42. ) {
  43. return;
  44. }
  45. self::$sessionStarted = true;
  46. // use cookies to store session id on the client side
  47. @ini_set('session.use_cookies', '1');
  48. // prevent attacks involving session ids passed in URLs
  49. @ini_set('session.use_only_cookies', '1');
  50. // advise browser that session cookie should only be sent over secure connection
  51. if (ProxyHttp::isHttps()) {
  52. @ini_set('session.cookie_secure', '1');
  53. }
  54. // advise browser that session cookie should only be accessible through the HTTP protocol (i.e., not JavaScript)
  55. @ini_set('session.cookie_httponly', '1');
  56. // don't use the default: PHPSESSID
  57. @ini_set('session.name', self::SESSION_NAME);
  58. // proxies may cause the referer check to fail and
  59. // incorrectly invalidate the session
  60. @ini_set('session.referer_check', '');
  61. $currentSaveHandler = ini_get('session.save_handler');
  62. $config = Config::getInstance();
  63. if (self::isFileBasedSessions()) {
  64. // Note: this handler doesn't work well in load-balanced environments and may have a concurrency issue with locked session files
  65. // for "files", use our own folder to prevent local session file hijacking
  66. $sessionPath = self::getSessionsDirectory();
  67. // We always call mkdir since it also chmods the directory which might help when permissions were reverted for some reasons
  68. Filesystem::mkdir($sessionPath);
  69. @ini_set('session.save_handler', 'files');
  70. @ini_set('session.save_path', $sessionPath);
  71. } else if ($config->General['session_save_handler'] === 'dbtable'
  72. || in_array($currentSaveHandler, array('user', 'mm'))
  73. ) {
  74. // We consider these to be misconfigurations, in that:
  75. // - user - we can't verify that user-defined session handler functions have already been set via session_set_save_handler()
  76. // - mm - this handler is not recommended, unsupported, not available for Windows, and has a potential concurrency issue
  77. $config = array(
  78. 'name' => Common::prefixTable('session'),
  79. 'primary' => 'id',
  80. 'modifiedColumn' => 'modified',
  81. 'dataColumn' => 'data',
  82. 'lifetimeColumn' => 'lifetime',
  83. );
  84. $saveHandler = new DbTable($config);
  85. if ($saveHandler) {
  86. self::setSaveHandler($saveHandler);
  87. }
  88. }
  89. // garbage collection may disabled by default (e.g., Debian)
  90. if (ini_get('session.gc_probability') == 0) {
  91. @ini_set('session.gc_probability', 1);
  92. }
  93. try {
  94. parent::start();
  95. register_shutdown_function(array('Zend_Session', 'writeClose'), true);
  96. } catch (Exception $e) {
  97. Log::warning('Unable to start session: ' . $e->getMessage());
  98. $enableDbSessions = '';
  99. if (DbHelper::isInstalled()) {
  100. $enableDbSessions = "<br/>If you still experience issues after trying these changes,
  101. we recommend that you <a href='http://piwik.org/faq/how-to-install/#faq_133' target='_blank'>enable database session storage</a>.";
  102. }
  103. $pathToSessions = Filechecks::getErrorMessageMissingPermissions(Filesystem::getPathToPiwikRoot() . '/tmp/sessions/');
  104. $pathToSessions = SettingsPiwik::rewriteTmpPathWithInstanceId($pathToSessions);
  105. $message = sprintf("Error: %s %s %s\n<pre>Debug: the original error was \n%s</pre>",
  106. Piwik::translate('General_ExceptionUnableToStartSession'),
  107. $pathToSessions,
  108. $enableDbSessions,
  109. $e->getMessage()
  110. );
  111. Piwik_ExitWithMessage($message, $e->getTraceAsString());
  112. }
  113. }
  114. /**
  115. * Returns the directory session files are stored in.
  116. *
  117. * @return string
  118. */
  119. public static function getSessionsDirectory()
  120. {
  121. $path = PIWIK_USER_PATH . '/tmp/sessions';
  122. return SettingsPiwik::rewriteTmpPathWithInstanceId($path);
  123. }
  124. public static function close()
  125. {
  126. parent::writeClose();
  127. }
  128. }