131bc7874SGreg Roach<?php 231bc7874SGreg Roach/** 331bc7874SGreg Roach * webtrees: online genealogy 46bdf7674SGreg Roach * Copyright (C) 2017 webtrees development team 531bc7874SGreg Roach * This program is free software: you can redistribute it and/or modify 631bc7874SGreg Roach * it under the terms of the GNU General Public License as published by 731bc7874SGreg Roach * the Free Software Foundation, either version 3 of the License, or 831bc7874SGreg Roach * (at your option) any later version. 931bc7874SGreg Roach * This program is distributed in the hope that it will be useful, 1031bc7874SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 1131bc7874SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1231bc7874SGreg Roach * GNU General Public License for more details. 1331bc7874SGreg Roach * You should have received a copy of the GNU General Public License 1431bc7874SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 1531bc7874SGreg Roach */ 1676692c8bSGreg Roachnamespace Fisharebest\Webtrees; 1731bc7874SGreg Roach 1831bc7874SGreg Roach/** 1976692c8bSGreg Roach * Temporary class to migrate to Symfony-based sessions, which need PHP 5.4. 2031bc7874SGreg Roach */ 2131bc7874SGreg Roachclass Session { 2231bc7874SGreg Roach /** 2331bc7874SGreg Roach * Start a session 2431bc7874SGreg Roach * 2531bc7874SGreg Roach * @param array $config 2631bc7874SGreg Roach */ 2713abd6f3SGreg Roach public static function start(array $config = []) { 2813abd6f3SGreg Roach $default_config = [ 299c927afbSGreg Roach 'use_cookies' => '1', 3031bc7874SGreg Roach 'name' => 'WT_SESSION', 319c927afbSGreg Roach 'cookie_lifetime' => '0', 329c927afbSGreg Roach 'gc_maxlifetime' => '7200', 339c927afbSGreg Roach 'gc_probability' => '1', 349c927afbSGreg Roach 'gc_divisor' => '100', 3531bc7874SGreg Roach 'cookie_path' => '', 369c927afbSGreg Roach 'cookie_httponly' => '1', 3713abd6f3SGreg Roach ]; 3831bc7874SGreg Roach session_register_shutdown(); 3931bc7874SGreg Roach foreach ($config + $default_config as $key => $value) { 403b8c3a1cSGreg Roach ini_set('session.' . $key, $value); 4131bc7874SGreg Roach } 4231bc7874SGreg Roach session_start(); 4331bc7874SGreg Roach } 4431bc7874SGreg Roach 4531bc7874SGreg Roach /** 4631bc7874SGreg Roach * Read a value from the session 4731bc7874SGreg Roach * 4831bc7874SGreg Roach * @param string $name 4931bc7874SGreg Roach * @param mixed $default 5031bc7874SGreg Roach * 5131bc7874SGreg Roach * @return mixed 5231bc7874SGreg Roach */ 5331bc7874SGreg Roach public static function get($name, $default = null) { 5431bc7874SGreg Roach if (isset($_SESSION[$name])) { 5531bc7874SGreg Roach return $_SESSION[$name]; 5631bc7874SGreg Roach } else { 5731bc7874SGreg Roach return $default; 5831bc7874SGreg Roach } 5931bc7874SGreg Roach } 6031bc7874SGreg Roach 6131bc7874SGreg Roach /** 6231bc7874SGreg Roach * Write a value to the session 6331bc7874SGreg Roach * 6431bc7874SGreg Roach * @param string $name 6531bc7874SGreg Roach * @param mixed $value 6631bc7874SGreg Roach */ 6731bc7874SGreg Roach public static function put($name, $value) { 6831bc7874SGreg Roach $_SESSION[$name] = $value; 6931bc7874SGreg Roach } 7031bc7874SGreg Roach 7131bc7874SGreg Roach /** 7231bc7874SGreg Roach * Remove a value from the session 7331bc7874SGreg Roach * 7431bc7874SGreg Roach * @param string $name 7531bc7874SGreg Roach */ 7631bc7874SGreg Roach public static function forget($name) { 7731bc7874SGreg Roach unset($_SESSION[$name]); 7831bc7874SGreg Roach } 7931bc7874SGreg Roach 8031bc7874SGreg Roach /** 8131bc7874SGreg Roach * Does a session variable exist? 8231bc7874SGreg Roach * 8331bc7874SGreg Roach * @param string $name 8431bc7874SGreg Roach * 85cbc1590aSGreg Roach * @return bool 8631bc7874SGreg Roach */ 8731bc7874SGreg Roach public static function has($name) { 8891fb15f0SGreg Roach return isset($_SESSION[$name]); 8931bc7874SGreg Roach } 9031bc7874SGreg Roach 9131bc7874SGreg Roach /** 92f5004097SGreg Roach * Remove all stored data from the session. 93f5004097SGreg Roach */ 94f5004097SGreg Roach public static function clear() { 9513abd6f3SGreg Roach $_SESSION = []; 96f5004097SGreg Roach } 97f5004097SGreg Roach 98f5004097SGreg Roach /** 9931bc7874SGreg Roach * After any change in authentication level, we should use a new session ID. 10031bc7874SGreg Roach * 10131bc7874SGreg Roach * @param bool $destroy 10231bc7874SGreg Roach */ 10331bc7874SGreg Roach public static function regenerate($destroy = false) { 104f5004097SGreg Roach if ($destroy) { 105f5004097SGreg Roach self::clear(); 106f5004097SGreg Roach } 10731bc7874SGreg Roach session_regenerate_id($destroy); 10831bc7874SGreg Roach } 10931bc7874SGreg Roach 11031bc7874SGreg Roach /** 11131bc7874SGreg Roach * Set an explicit session ID. Typically used for search robots. 11231bc7874SGreg Roach * 11331bc7874SGreg Roach * @param string $id 11431bc7874SGreg Roach */ 11531bc7874SGreg Roach public static function setId($id) { 11631bc7874SGreg Roach session_id($id); 11731bc7874SGreg Roach } 118*57514a4fSGreg Roach 119*57514a4fSGreg Roach /** 120*57514a4fSGreg Roach * Initialise our session save handler 121*57514a4fSGreg Roach */ 122*57514a4fSGreg Roach public static function setSaveHandler() { 123*57514a4fSGreg Roach session_set_save_handler( 124*57514a4fSGreg Roach function (): bool { 125*57514a4fSGreg Roach return Session::open(); 126*57514a4fSGreg Roach }, 127*57514a4fSGreg Roach function ():bool { 128*57514a4fSGreg Roach return Session::close(); 129*57514a4fSGreg Roach }, 130*57514a4fSGreg Roach function (string $id): string { 131*57514a4fSGreg Roach return Session::read($id); 132*57514a4fSGreg Roach }, 133*57514a4fSGreg Roach function (string $id, string $data): bool { 134*57514a4fSGreg Roach return Session::write($id, $data); 135*57514a4fSGreg Roach }, 136*57514a4fSGreg Roach function (string $id): bool { 137*57514a4fSGreg Roach return Session::destroy($id); 138*57514a4fSGreg Roach }, 139*57514a4fSGreg Roach function (int $maxlifetime):bool { 140*57514a4fSGreg Roach return Session::gc($maxlifetime); 141*57514a4fSGreg Roach } 142*57514a4fSGreg Roach ); 143*57514a4fSGreg Roach } 144*57514a4fSGreg Roach 145*57514a4fSGreg Roach /** 146*57514a4fSGreg Roach * For session_set_save_handler() 147*57514a4fSGreg Roach * 148*57514a4fSGreg Roach * @return bool 149*57514a4fSGreg Roach */ 150*57514a4fSGreg Roach private static function close() { 151*57514a4fSGreg Roach return true; 152*57514a4fSGreg Roach } 153*57514a4fSGreg Roach 154*57514a4fSGreg Roach /** 155*57514a4fSGreg Roach * For session_set_save_handler() 156*57514a4fSGreg Roach * 157*57514a4fSGreg Roach * @param string $id 158*57514a4fSGreg Roach * 159*57514a4fSGreg Roach * @return bool 160*57514a4fSGreg Roach */ 161*57514a4fSGreg Roach private static function destroy(string $id) { 162*57514a4fSGreg Roach Database::prepare( 163*57514a4fSGreg Roach "DELETE FROM `##session` WHERE session_id = :session_id" 164*57514a4fSGreg Roach )->execute([ 165*57514a4fSGreg Roach 'session_id' => $id 166*57514a4fSGreg Roach ]); 167*57514a4fSGreg Roach 168*57514a4fSGreg Roach return true; 169*57514a4fSGreg Roach } 170*57514a4fSGreg Roach 171*57514a4fSGreg Roach /** 172*57514a4fSGreg Roach * For session_set_save_handler() 173*57514a4fSGreg Roach * 174*57514a4fSGreg Roach * @param int $maxlifetime 175*57514a4fSGreg Roach * 176*57514a4fSGreg Roach * @return bool 177*57514a4fSGreg Roach */ 178*57514a4fSGreg Roach private static function gc(int $maxlifetime) { 179*57514a4fSGreg Roach Database::prepare( 180*57514a4fSGreg Roach "DELETE FROM `##session` WHERE session_time < DATE_SUB(NOW(), INTERVAL :maxlifetime SECOND)" 181*57514a4fSGreg Roach )->execute([ 182*57514a4fSGreg Roach 'maxlifetime' => $maxlifetime 183*57514a4fSGreg Roach ]); 184*57514a4fSGreg Roach 185*57514a4fSGreg Roach return true; 186*57514a4fSGreg Roach } 187*57514a4fSGreg Roach 188*57514a4fSGreg Roach /** 189*57514a4fSGreg Roach * For session_set_save_handler() 190*57514a4fSGreg Roach * 191*57514a4fSGreg Roach * @return bool 192*57514a4fSGreg Roach */ 193*57514a4fSGreg Roach private static function open() { 194*57514a4fSGreg Roach return true; 195*57514a4fSGreg Roach } 196*57514a4fSGreg Roach 197*57514a4fSGreg Roach /** 198*57514a4fSGreg Roach * For session_set_save_handler() 199*57514a4fSGreg Roach * 200*57514a4fSGreg Roach * @param string $id 201*57514a4fSGreg Roach * 202*57514a4fSGreg Roach * @return string 203*57514a4fSGreg Roach */ 204*57514a4fSGreg Roach private static function read(string $id): string { 205*57514a4fSGreg Roach return (string) Database::prepare( 206*57514a4fSGreg Roach "SELECT session_data FROM `##session` WHERE session_id = :session_id" 207*57514a4fSGreg Roach )->execute([ 208*57514a4fSGreg Roach 'session_id' => $id 209*57514a4fSGreg Roach ])->fetchOne(); 210*57514a4fSGreg Roach } 211*57514a4fSGreg Roach 212*57514a4fSGreg Roach /** 213*57514a4fSGreg Roach * For session_set_save_handler() 214*57514a4fSGreg Roach * 215*57514a4fSGreg Roach * @param string $id 216*57514a4fSGreg Roach * @param string $data 217*57514a4fSGreg Roach * 218*57514a4fSGreg Roach * @return bool 219*57514a4fSGreg Roach */ 220*57514a4fSGreg Roach private static function write(string $id, string $data): bool { 221*57514a4fSGreg Roach // Only update the session table once per minute, unless the session data has actually changed. 222*57514a4fSGreg Roach Database::prepare( 223*57514a4fSGreg Roach "INSERT INTO `##session` (session_id, user_id, ip_address, session_data, session_time)" . 224*57514a4fSGreg Roach " VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP - SECOND(CURRENT_TIMESTAMP))" . 225*57514a4fSGreg Roach " ON DUPLICATE KEY UPDATE" . 226*57514a4fSGreg Roach " user_id = VALUES(user_id)," . 227*57514a4fSGreg Roach " ip_address = VALUES(ip_address)," . 228*57514a4fSGreg Roach " session_data = VALUES(session_data)," . 229*57514a4fSGreg Roach " session_time = CURRENT_TIMESTAMP - SECOND(CURRENT_TIMESTAMP)" 230*57514a4fSGreg Roach )->execute([ 231*57514a4fSGreg Roach $id, 232*57514a4fSGreg Roach (int) Auth::id(), 233*57514a4fSGreg Roach WT_CLIENT_IP, 234*57514a4fSGreg Roach $data] 235*57514a4fSGreg Roach ); 236*57514a4fSGreg Roach 237*57514a4fSGreg Roach return true; 238*57514a4fSGreg Roach } 23931bc7874SGreg Roach} 240