global $CFG;
if (!defined('NO_MOODLE_COOKIES')) {
- if (CLI_SCRIPT) {
+ if (empty($CFG->version) or $CFG->version < 2009011600) {
+ // no session before sessions table gets greated
+ define('NO_MOODLE_COOKIES', true);
+ } else if (CLI_SCRIPT) {
// CLI scripts can not have session
define('NO_MOODLE_COOKIES', true);
} else {
session_name('MoodleSession'.$CFG->sessioncookie);
session_set_cookie_params(0, $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $CFG->cookiesecure, $CFG->cookiehttponly);
- @session_start();
+ session_start();
if (!isset($_SESSION['SESSION'])) {
$_SESSION['SESSION'] = new object();
- if (!$newsession and !empty($CFG->rolesactive)) {
+ if (!$newsession) {
$_SESSION['SESSION']->has_timed_out = true;
}
}
return;
}
+ // Initialize variable to pass-by-reference to headers_sent(&$file, &$line)
$_SESSION = array();
$_SESSION['SESSION'] = new object();
$_SESSION['USER'] = new object();
if (isset($CFG->mnet_localhost_id)) {
$_SESSION['USER']->mnethostid = $CFG->mnet_localhost_id;
}
-
$SESSION = $_SESSION['SESSION']; // this may not work properly
$USER = $_SESSION['USER']; // this may not work properly
- // Initialize variable to pass-by-reference to headers_sent(&$file, &$line)
$file = null;
$line = null;
if (headers_sent($file, $line)) {
error_log('Can not terminate session properly - headers were already sent in file: '.$file.' on line '.$line);
}
- // now let's try to get a new session id
- session_regenerate_id();
+ $oldid = session_id();
- // close the session
+ // now let's try to get a new session id and delete the old one
+ session_regenerate_id();
+ // write the new session
session_write_close();
+
+ // make sure the old session gets killed,
+ // the optional param in session_regenerate_id() does not seem to work consistently
+ session_kill($oldid);
}
/**
* Inits session storage.
*/
protected abstract function init_session_storage();
-
}
/**
$this->database->get_session_lock($record->id);
}
} catch (dml_exception $ex) {
- if (!empty($CFG->rolesactive)) {
- error_log('Can not read or insert database sessions');
- }
+ error_log('Can not read or insert database sessions');
return '';
}
}
public function handler_gc($ignored_maxlifetime) {
- $this->gc();
+ session_gc();
return true;
}
}
+/**
+ * returns true if legacy session used.
+ * @return bool true if legacy(==file) based session used
+ */
+function session_is_legacy() {
+ global $CFG, $DB;
+ return ((isset($CFG->dbsessions) and !$CFG->dbsessions) or !$DB->session_lock_supported());
+}
+
/**
* Terminates all sessions, auth hooks are not executed.
* Useful in ugrade scripts.
function session_kill_all() {
global $CFG, $DB;
+ // always check db table - custom session classes use sessions table
try {
- // do not show any warnings - might be during upgrade/installation
$DB->delete_records('sessions');
} catch (dml_exception $ignored) {
+ // do not show any warnings - might be during upgrade/installation
}
- $sessiondir = "$CFG->dataroot/sessions/";
- if (is_dir($sessiondir)) {
- // TODO: delete all files, watch out some might be locked
+ if (session_is_legacy()) {
+ $sessiondir = "$CFG->dataroot/sessions";
+ if (is_dir($sessiondir)) {
+ foreach (glob("$sessiondir/sess_*") as $filename) {
+ @unlink($filename);
+ }
+ }
+ }
+}
+
+/**
+ * Mark session as accessed, prevents timeouts.
+ * @param string $sid
+ */
+function session_touch($sid) {
+ global $CFG, $DB;
+
+ // always check db table - custom session classes use sessions table
+ try {
+ $sql = "UPDATE {sessions} SET timemodified=? WHERE sid=?";
+ $params = array(time(), $sid);
+ $DB->execute($sql, $params);
+ } catch (dml_exception $ignored) {
+ // do not show any warnings - might be during upgrade/installation
+ }
+
+ if (session_is_legacy()) {
+ $sid = clean_param($sid, PARAM_FILE);
+ $sessionfile = clean_param("$CFG->dataroot/sessions/sess_$sid", PARAM_FILE);
+ if (file_exists($sessionfile)) {
+ // if the file is locked it means that it will be updated anyway
+ @touch($sessionfile);
+ }
}
}
function session_kill($sid) {
global $CFG, $DB;
+ // always check db table - custom session classes use sessions table
try {
- // do not show any warnings - might be during upgrade/installation
- $$DB->delete_records('sessions', array('sid'=>$sid));
+ $DB->delete_records('sessions', array('sid'=>$sid));
} catch (dml_exception $ignored) {
+ // do not show any warnings - might be during upgrade/installation
}
- $sessionfile = clean_param("$CFG->dataroot/sessions/$sid", PARAM_FILE);
- if (file_exists($sessionfile)) {
- // TODO: delete file, watch out might be locked
+ if (session_is_legacy()) {
+ $sid = clean_param($sid, PARAM_FILE);
+ $sessionfile = "$CFG->dataroot/sessions/sess_$sid";
+ if (file_exists($sessionfile)) {
+ @unlink($sessionfile);
+ }
}
}
function session_kill_user($userid) {
global $CFG, $DB;
+ // always check db table - custom session classes use sessions table
try {
- // do not show any warnings - might be during upgrade/installation
- $$DB->delete_records('sessions', array('userid'=>$userid));
+ $DB->delete_records('sessions', array('userid'=>$userid));
} catch (dml_exception $ignored) {
+ // do not show any warnings - might be during upgrade/installation
+ }
+
+ if (session_is_legacy()) {
+ // log error?
}
}
$maxlifetime = $CFG->sessiontimeout;
- if (empty($CFG->rolesactive)) {
- return;
- }
-
try {
/// kill all sessions of deleted users
$DB->delete_records_select('sessions', "userid IN (SELECT id FROM {user} WHERE deleted <> 0)");