diff --git a/src/Core/Session.php b/src/Core/Session.php new file mode 100644 index 0000000000..b5c09f745b --- /dev/null +++ b/src/Core/Session.php @@ -0,0 +1,57 @@ + + */ +class Session +{ + public static $exists = false; + public static $expire = 180000; + + public static function init() + { + ini_set('session.gc_probability', 50); + ini_set('session.use_only_cookies', 1); + ini_set('session.cookie_httponly', 1); + + if (Config::get('system', 'ssl_policy') == SSL_POLICY_FULL) { + ini_set('session.cookie_secure', 1); + } + + if (!Config::get('system', 'disable_database_session')) { + $memcache = Cache::memcache(); + if (is_object($memcache)) { + $SessionHandler = new MemcacheSessionHandler($memcache); + } else { + $SessionHandler = new DatabaseSessionHandler(); + } + + session_set_save_handler($SessionHandler); + } + } + + public static function exists($name) + { + return isset($_SESSION[$name]); + } + + public static function get($name) + { + return defaults($_SESSION, $name, null); + } + + public static function set($name, $value) + { + $_SESSION[$name] = $value; + } +} diff --git a/src/Core/Session/DatabaseSessionHandler.php b/src/Core/Session/DatabaseSessionHandler.php new file mode 100644 index 0000000000..d017e2edd2 --- /dev/null +++ b/src/Core/Session/DatabaseSessionHandler.php @@ -0,0 +1,95 @@ + + */ +class DatabaseSessionHandler extends BaseObject implements SessionHandlerInterface +{ + public function open($save_path, $session_name) + { + return true; + } + + public function read($session_id) + { + if (!x($session_id)) { + return ''; + } + + $session = dba::selectFirst('session', ['data'], ['sid' => $session_id]); + if (DBM::is_result($session)) { + Session::$exists = true; + return $session['data']; + } + logger("no data for session $session_id", LOGGER_TRACE); + + return ''; + } + + /** + * @brief Standard PHP session write callback + * + * This callback updates the DB-stored session data and/or the expiration depending + * on the case. Uses the Session::expire global for existing session, 5 minutes + * for newly created session. + * + * @param string $session_id Session ID with format: [a-z0-9]{26} + * @param string $session_data Serialized session data + * @return boolean Returns false if parameters are missing, true otherwise + */ + public function write($session_id, $session_data) + { + if (!$session_id) { + return false; + } + + if (!$session_data) { + return true; + } + + $expire = time() + Session::$expire; + $default_expire = time() + 300; + + if (Session::$exists) { + $fields = ['data' => $session_data, 'expire' => $expire]; + $condition = ["`sid` = ? AND (`data` != ? OR `expire` != ?)", $session_id, $session_data, $expire]; + dba::update('session', $fields, $condition); + } else { + $fields = ['sid' => $session_id, 'expire' => $default_expire, 'data' => $session_data]; + dba::insert('session', $fields); + } + + return true; + } + + public function close() + { + return true; + } + + public function destroy($id) + { + dba::delete('session', ['sid' => $id]); + return true; + } + + public function gc($maxlifetime) + { + dba::delete('session', ["`expire` < ?", time()]); + return true; + } +} diff --git a/src/Core/Session/MemcacheSessionHandler.php b/src/Core/Session/MemcacheSessionHandler.php new file mode 100644 index 0000000000..dce206e64c --- /dev/null +++ b/src/Core/Session/MemcacheSessionHandler.php @@ -0,0 +1,102 @@ + + */ +class MemcacheSessionHandler extends BaseObject implements SessionHandlerInterface +{ + /** + * @var Memcache + */ + private $memcache = null; + + /** + * + * @param Memcache $memcache + */ + public function __construct(Memcache $memcache) + { + $this->memcache = $memcache; + } + + public function open($save_path, $session_name) + { + return true; + } + + public function read($session_id) + { + if (!x($session_id)) { + return ''; + } + + $data = $this->memcache->get(self::getApp()->get_hostname() . ":session:" . $session_id); + if (!is_bool($data)) { + Session::$exists = true; + return $data; + } + logger("no data for session $session_id", LOGGER_TRACE); + return ''; + } + + /** + * @brief Standard PHP session write callback + * + * This callback updates the stored session data and/or the expiration depending + * on the case. Uses the Session::expire for existing session, 5 minutes + * for newly created session. + * + * @param string $session_id Session ID with format: [a-z0-9]{26} + * @param string $session_data Serialized session data + * @return boolean Returns false if parameters are missing, true otherwise + */ + public function write($session_id, $session_data) + { + if (!$session_id) { + return false; + } + + if (!$session_data) { + return true; + } + + $expire = time() + Session::$expire; + + $this->memcache->set( + self::getApp()->get_hostname() . ":session:" . $session_id, + $session_data, + MEMCACHE_COMPRESSED, + $expire + ); + + return true; + } + + public function close() + { + return true; + } + + public function destroy($id) + { + $this->memcache->delete(self::getApp()->get_hostname() . ":session:" . $id); + return true; + } + + public function gc($maxlifetime) + { + return true; + } +}