diff options
| author | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
|---|---|---|
| committer | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
| commit | 4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch) | |
| tree | 5c07151ae61276d334e88f6309c30d439a85c12e /lib/phplib/Seminar_Session.php | |
| parent | da0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff) | |
| parent | 97a188592c679890a25c37ab78463add76a52ff7 (diff) | |
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/phplib/Seminar_Session.php')
| -rw-r--r-- | lib/phplib/Seminar_Session.php | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/lib/phplib/Seminar_Session.php b/lib/phplib/Seminar_Session.php new file mode 100644 index 0000000..8324062 --- /dev/null +++ b/lib/phplib/Seminar_Session.php @@ -0,0 +1,436 @@ +<?php + +/** + * PHPLib Sessions using PHP 4 build-in sessions and PHPLib storage container + * + * @copyright (c) 1998,1999 NetUSE GmbH Boris Erdmann, Kristian Koehntopp, + * 2000 Maxim Derkachev <kot@books.ru>, + * 2000 Teodor Cimpoesu <teo@digiro.net> + * @author André Noack <noack@data-quest.de> Maxim Derkachev <kot@books.ru>, + * Teodor Cimpoesu <teo@digiro.net>,Ulf Wendel <uw@netuse.de> + */ +class Seminar_Session +{ + /** + * Current session id. + * + * @var string + * @see id(), Session() + */ + private $id; + + + /** + * Current session name also cookie name + * + * @var string + * @see name(), Session() + */ + private $name; + + /** + * + * @var string + */ + private $cookie_path; + + /** + * If set, the domain for which the session cookie is set. + * + * @var string + */ + private $cookie_domain; + + /** + * If set, the domain for which the session cookie is set. + * + * @var bool + */ + private $cookie_secure = false; + + /** + * If set, the domain for which the session cookie is set. + * + * @var bool + */ + private $cookie_httponly = true; + + /** + * session storage module - user, files or mm + * + * @var string + */ + private $module = 'user'; + + + /** + * where to save session files if module == files + * + * @var string + */ + private $save_path; + + + /** + * Name of data storage container + * + * var string + */ + private $that_class = 'CT_Sql'; + + /** + * + * @var object CT_* + */ + private $that; + + /** + * Purge all session data older than this. + * + * @var int + */ + private $gc_time; + + + /** + * @var + */ + private static $studipticket; + /** + * @var + */ + private static $current_session_state; + + /** + * Returns true, if the current session is valid and belongs to an + * authenticated user. Does not start a session. + * + * @static + * @return bool + */ + public static function is_current_session_authenticated() + { + return self::get_current_session_state() == 'authenticated'; + } + + /** + * Returns the state of the current session. Does not start a session. + * possible return values: + * 'authenticated' - session is valid and user is authenticated + * 'nobody' - session is valid, but user is not authenticated + * false - no valid session + * + * @static + * @return string|false + */ + public static function get_current_session_state() + { + + if (!is_null(self::$current_session_state)) { + return self::$current_session_state; + } + $state = false; + if (isset($GLOBALS['user']) && is_object($GLOBALS['user'])) { + $state = in_array($GLOBALS['user']->id, ['nobody', 'form']) ? 'nobody' : 'authenticated'; + } else { + $sid = $_COOKIE[__CLASS__]; + if ($sid) { + $session_vars = self::get_session_vars($sid); + $session_auth = $session_vars['auth']->auth; + if ($session_auth['uid'] && !in_array($session_auth['uid'], ['nobody', 'form'])) { + $state = 'authenticated'; + } else { + $state = in_array($session_auth['uid'], ['nobody', 'form']) ? 'nobody' : false; + } + } + } + return (self::$current_session_state = $state); + } + + /** + * returns a SessionDecoder object containing the session variables + * for the given session id + * + * @static + * @param string $sid a session id + * @return SessionDecoder + */ + public static function get_session_vars($sid) + { + $sess = $GLOBALS['sess'] ?? null; + if (!is_object($sess)) { + $sess = new self(); + } + $storage_class = $sess->that_class; + $storage = new $storage_class(); + $storage->ac_start(); + return new SessionDecoder($storage->ac_get_value($sid)); + } + + /** + * returns a random string token for XSRF prevention + * the string is stored in the session + * + * @static + * @return string + */ + public static function get_ticket() + { + if (!self::$studipticket) { + self::$studipticket = $_SESSION['last_ticket'] = md5(uniqid('studipticket', 1)); + } + return self::$studipticket; + } + + /** + * checks the given string token against the one stored + * in the session + * + * @static + * @param string $studipticket + * @return bool + */ + public static function check_ticket($studipticket) + { + $check = (isset($_SESSION['last_ticket']) && $_SESSION['last_ticket'] == $studipticket); + $_SESSION['last_ticket'] = null; + return $check; + } + + + /** + * + */ + function __construct() + { + if (Config::get()->CACHING_ENABLE && $GLOBALS['CACHE_IS_SESSION_STORAGE']) { + $this->that_class = 'CT_Cache'; + } + $this->cookie_path = $this->cookie_path ?: $GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP']; + $this->cookie_secure = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on'; + $this->name(get_class($this)); + } + + /** + * Start a new session or recovers from an existing session + * + * @return boolean session_start() return value + * @access public + */ + function start() + { + $this->set_container(); + + session_set_cookie_params( + 0, + implode('/', array_map('rawurlencode', explode('/', $this->cookie_path))), + $this->cookie_domain, + $this->cookie_secure, + $this->cookie_httponly + ); + session_cache_limiter("nocache"); + //check for illegal cookiename + if ( + !isset($_COOKIE[$this->name]) + || mb_strlen($_COOKIE[$this->name]) !== 32 + || preg_match('/[^0-9a-f]+/', $_COOKIE[$this->name]) + ) { + do { + $new_id = md5(bin2hex(random_bytes(128))); + } while (!$this->that->ac_newid($new_id)); + + session_id($new_id); + } + + $ok = session_start(); + $this->id = session_id(); + return $ok; + } + + /** + * Sets or returns the name of the current session + * + * @param string If given, sets the session name + * @return string session_name() return value + * @access public + */ + function name($name = '') + { + if ($name) { + $this->name = $name; + $ok = session_name($name); + } else { + $ok = session_name(); + } + return $ok; + } + + /** + * ? + * + */ + function set_container() + { + + switch ($this->module) { + case "user" : + $name = $this->that_class; + $this->that = new $name; + $this->that->ac_start(); + // set custom session handlers + session_set_save_handler([$this, 'open'], + [$this, 'close'], + [$this, 'thaw'], + [$this, 'freeze'], + [$this, 'del'], + [$this, 'gc'] + ); + break; + + case "mm": + session_module_name('mm'); + break; + + case "files": + default: + if ($this->save_path) { + session_save_path($this->save_path); + } + session_module_name('files'); + break; + } + } + + /** + * @param array $keep_session_vars + */ + function regenerate_session_id($keep_session_vars = []) + { + $keep = []; + if (is_array($_SESSION)) { + foreach (array_keys($_SESSION) as $k) { + if (in_array($k, $keep_session_vars)) { + $keep[$k] = $_SESSION[$k]; + } + } + $_SESSION = []; + } + $this->delete(); + $this->start(); + foreach ($keep_session_vars as $k) { + $_SESSION[$k] = $keep[$k] ?? null; + } + } + + /** + * Delete the current session destroying all registered data. + * + * Note that it does more but the PHP 4 session_destroy it also + * throws away a cookie is there's one. + * + * @return boolean session_destroy return value + * @access public + */ + function delete() + { + $cookie_params = session_get_cookie_params(); + setCookie( + $this->name, + '', + 0, + implode('/', array_map('rawurlencode', explode('/', $cookie_params['path']))), + $cookie_params['domain'], + $cookie_params['secure'], + $cookie_params['httponly'] + ); + $_COOKIE[$this->name] = ""; + $_SESSION = []; + return session_destroy(); + } + + // the following functions used in session_set_save_handler + + /** + * Open callback + * + */ + function open() + { + return true; + } + + + /** + * Close callback + * + */ + function close() + { + return true; + } + + + /** + * Delete callback + */ + function del() + { + if ($this->module == 'user') { + $this->that->ac_delete($this->id, $this->name); + } + return true; + } + + + /** + * Write callback. + * + */ + function freeze($id = null, $sess_data = null) + { + if ($this->module == 'user') { + if (!isset($sess_data)) { + $sess_data = session_encode(); + } + $r = $this->that->ac_store($this->id, $this->name, $sess_data); + if (!$r) { + $this->that->ac_halt("Session: freeze() failed."); + } + } + return true; + } + + /** + * Read callback. + */ + function thaw() + { + if ($this->module == 'user') { + return $this->that->ac_get_value(session_id(), $this->name) ?: ''; + } + return ''; + } + + /** + * @return bool + */ + function gc() + { + if ($this->module === 'user') { + //bail out if cronjob activated and not called in cli context + if ( + Config::getInstance()->getValue('CRONJOBS_ENABLE') + && ($task = CronjobTask::findOneByClass(SessionGcJob::class)) + && count($task->schedules->findBy('active', 1)) + && PHP_SAPI !== 'cli' + ) { + return false; + } + if (empty($this->gc_time)) { + $this->gc_time = ini_get("session.gc_maxlifetime"); + } + return (bool)$this->that->ac_gc($this->gc_time, $this->name); + } + return true; + } +} |
