/** * Starts and initializes session data. * @throws XApp_InvalidStateException * @return void */ public function start() { if (self::$started) { return; } $this->configure($this->options); $id =& $_COOKIE[session_name()]; if (!is_string($id) || !preg_match('#^[0-9a-zA-Z,-]{22,128}\\z#i', $id)) { unset($_COOKIE[session_name()]); } set_error_handler(function ($severity, $message) use(&$error) { // session_start returns FALSE on failure only sometimes if (($severity & error_reporting()) === $severity) { $error = $message; restore_error_handler(); } }); session_start(); if (!$error) { restore_error_handler(); } $this->response->removeDuplicateCookies(); if ($error) { @session_write_close(); // this is needed throw new Exception("session_start(): {$error}"); } self::$started = TRUE; /* structure: __NF: BrowserKey, Data, Meta, Time DATA: section->variable = data META: section->variable = Timestamp, Browser, Version */ $nf =& $_SESSION['__NF']; // regenerate empty session if (empty($nf['Time'])) { $nf['Time'] = time(); $this->regenerated = TRUE; } // browser closing detection $browserKey = $this->request->getCookie('nette-browser'); if (!$browserKey) { $browserKey = XApp_Utils_Strings::random(); } $browserClosed = !isset($nf['B']) || $nf['B'] !== $browserKey; $nf['B'] = $browserKey; // resend cookie $this->sendCookie(); // process meta metadata if (isset($nf['META'])) { $now = time(); // expire section variables foreach ($nf['META'] as $section => $metadata) { if (is_array($metadata)) { foreach ($metadata as $variable => $value) { if (!empty($value['B']) && $browserClosed || !empty($value['T']) && $now > $value['T'] || isset($nf['DATA'][$section][$variable]) && is_object($nf['DATA'][$section][$variable]) && (isset($value['V']) ? $value['V'] : NULL) != XApp_Reflection_ClassType::from($nf['DATA'][$section][$variable])->getAnnotation('serializationVersion')) { if ($variable === '') { // expire whole section unset($nf['META'][$section], $nf['DATA'][$section]); continue 2; } unset($nf['META'][$section][$variable], $nf['DATA'][$section][$variable]); } } } } } if ($this->regenerated) { $this->regenerated = FALSE; $this->regenerateId(); } register_shutdown_function(array($this, 'clean')); }
/** * Computes salted password hash. * @param string * @return string */ protected static function hashPassword($password, $options = NULL) { if ($password === XApp_Utils_Strings::upper($password)) { // perhaps caps lock is on $password = XApp_Utils_Strings::lower($password); } $password = substr($password, 0, self::PASSWORD_MAX_LENGTH); $options = $options ?: implode('$', array('algo' => '$2a', 'cost' => '07', 'salt' => XApp_Utils_Strings::random(22))); return crypt($password, $options); }