}
if (empty($filter)) {
- if ($mimetype == 'text/html' && !empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) {
+ if ($mimetype == 'text/html' && !empty($CFG->usesid)) {
//cookieless mode - rewrite links
@header('Content-Type: text/html');
$path = $pathisstring ? $path : implode('', file($path));
$text = file_modify_html_header($text);
$output = format_text($text, FORMAT_HTML, $options, $COURSE->id);
- if (!empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) {
+ if (!empty($CFG->usesid)) {
//cookieless mode - rewrite links
$output = sid_ob_rewrite($output);
}
$options->noclean = true;
$text = htmlentities($pathisstring ? $path : implode('', file($path)));
$output = '<pre>'. format_text($text, FORMAT_MOODLE, $options, $COURSE->id) .'</pre>';
- if (!empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) {
+ if (!empty($CFG->usesid)) {
//cookieless mode - rewrite links
$output = sid_ob_rewrite($output);
}
if (empty($filter)) {
$filtered = false;
- if ($mimetype == 'text/html' && !empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) {
+ if ($mimetype == 'text/html' && !empty($CFG->usesid)) {
//cookieless mode - rewrite links
@header('Content-Type: text/html');
$text = $stored_file->get_content();
$text = $stored_file->get_content();
$text = file_modify_html_header($text);
$output = format_text($text, FORMAT_HTML, $options, $COURSE->id);
- if (!empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) {
+ if (!empty($CFG->usesid)) {
//cookieless mode - rewrite links
$output = sid_ob_rewrite($output);
}
$options->noclean = true;
$text = $stored_file->get_content();
$output = '<pre>'. format_text($text, FORMAT_MOODLE, $options, $COURSE->id) .'</pre>';
- if (!empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) {
+ if (!empty($CFG->usesid)) {
//cookieless mode - rewrite links
$output = sid_ob_rewrite($output);
}
* @return moodle_session
*/
function session_get_instance() {
+ global $CFG;
+
static $session = null;
if (is_null($session)) {
- $session = new legacy_session();
- // TODO: add db and custom session class support here
+ if (defined('SESSION_CUSTOM')) {
+ // this is a hook for custom session handling, webservices, etc.
+ if (defined('SESSION_CUSTOM_FILE')) {
+ require_once($CFG->dirroot.SESSION_CUSTOM_FILE);
+ }
+ $session_class = SESSION_CUSTOM;
+ $session = new $session_class();
+
+ } else if (!isset($CFG->dbsessions) or $CFG->dbsessions) {
+ // default recommended session type
+ $session = new database_session();
+
+ } else {
+ // legacy limited file based storage - some features and auth plugins will not work, sorry
+ $session = new legacy_file_session();
+ }
}
return $session;
}
+interface moodle_session {
+ public function terminate();
+}
+
/**
* Class handling all session and cookies related stuff.
*/
-abstract class moodle_session {
+abstract class session_stub implements moodle_session {
public function __construct() {
global $CFG;
- $this->prepare_cookies();
- $this->init_session_storage();
- if (!empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) {
- sid_start_ob();
+ if (!defined('NO_MOODLE_COOKIES')) {
+ if (CLI_SCRIPT) {
+ // CLI scripts can not have session
+ define('NO_MOODLE_COOKIES', true);
+ } else {
+ define('NO_MOODLE_COOKIES', false);
+ }
}
if (NO_MOODLE_COOKIES) {
+ // session not used at all
+ $CFG->usesid = false;
+
$_SESSION = array();
$_SESSION['SESSION'] = new object();
- $_SESSION['USER'] = new object();
+ $_SESSION['USER'] = new object();
} else {
+ $this->prepare_cookies();
+ $this->init_session_storage();
+
+ if (!empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) {
+ sid_start_ob();
+ }
+
session_name('MoodleSession'.$CFG->sessioncookie);
session_set_cookie_params(0, $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $CFG->cookiesecure, $CFG->cookiehttponly);
@session_start();
$user->id = 0; // to enable proper function of $CFG->notloggedinroleid hack
if (isset($CFG->mnet_localhost_id)) {
$user->mnethostid = $CFG->mnet_localhost_id;
+ } else {
+ $user->mnethostid = 1;
}
}
session_set_user($user);
protected function check_security() {
global $CFG;
+ if (NO_MOODLE_COOKIES) {
+ return;
+ }
+
if (!empty($_SESSION['USER']->id) and !empty($CFG->tracksessionip)) {
/// Make sure current IP matches the one for this session
$remoteaddr = getremoteaddr();
* Prepare cookies and varions system settings
*/
protected function prepare_cookies() {
- global $CFG, $nomoodlecookie;
-
- if (!defined('NO_MOODLE_COOKIES')) {
- if (CLI_SCRIPT) {
- // CLI scripts can not have session
- define('NO_MOODLE_COOKIES', true);
- } else if (isset($nomoodlecookie)) {
- // backwards compatibility only
- define('NO_MOODLE_COOKIES', $nomoodlecookie);
- } else {
- define('NO_MOODLE_COOKIES', false);
- }
- }
- unset($nomoodlecookie); // cleanup
+ global $CFG;
if (!isset($CFG->cookiesecure) or (strpos($CFG->wwwroot, 'https://') !== 0 and empty($CFG->sslproxy))) {
$CFG->cookiesecure = 0;
/**
* Legacy moodle sessions stored in files, not recommended any more.
*/
-class legacy_session extends moodle_session {
+class legacy_file_session extends session_stub {
protected function init_session_storage() {
global $CFG;
+ ini_set('session.save_handler', 'files');
+
// Some distros disable GC by setting probability to 0
// overriding the PHP default of 1
// (gc_probability is divided by gc_divisor, which defaults to 1000)
/**
* Recommended moodle session storage.
*/
-class database_session extends moodle_session {
+class database_session extends session_stub {
+ protected $record = null;
+ protected $database = null;
+
protected function init_session_storage() {
global $CFG;
-
+ if (ini_get('session.gc_probability') == 0) {
+ ini_set('session.gc_probability', 1);
+ }
+
+ if (!empty($CFG->sessiontimeout)) {
+ ini_set('session.gc_maxlifetime', $CFG->sessiontimeout);
+ }
+
+ $result = session_set_save_handler(array($this, 'handler_open'),
+ array($this, 'handler_close'),
+ array($this, 'handler_read'),
+ array($this, 'handler_write'),
+ array($this, 'handler_destroy'),
+ array($this, 'handler_gc'));
+ if (!$result) {
+ print_error('dbsessionhandlerproblem'); //TODO: localise
+ }
+ }
+
+ public function handler_open($save_path, $session_name) {
+ global $DB;
+
+ $this->database = $DB;
+ $this->database->used_for_db_sessions();
+
+ return true;
+ }
+
+ public function handler_close() {
+ $this->record = null;
+ return true;
+ }
+
+ public function handler_read($sid) {
+ global $CFG;
+
+ //TODO: implement locking and all the bells and whistles
+
+ if ($this->record and $this->record->sid != $sid) {
+ error_log('Weird error reading session - mismatched sid');
+ return '';
+ }
+
+ try {
+ if (!$record = $this->database->get_record('sessions', array('sid'=>$sid))) {
+ $record = new object();
+ $record->state = 0;
+ $record->sid = $sid;
+ $record->sessdata = null;
+ $record->sessdatahash = sha1('');
+ $record->userid = 0;
+ $record->timecreated = $record->timemodified = time();
+ $record->firstip = $record->lastip = getremoteaddr();
+
+ $record->id = $this->database->insert_record_raw('sessions', $record);
+
+ $this->record = $record;
+
+ return '';
+ }
+ } catch (dml_exception $ex) {
+ if (!empty($CFG->rolesactive)) {
+ error_log('Can not read or insert database sessions');
+ }
+ return '';
+ }
+
+ $data = base64_decode($record->sessdata);
+ unset($record->sessdata); // conserve memory
+ $this->record = $record;
+
+ return $data;
+ }
+
+ public function handler_write($sid, $session_data) {
+ global $USER;
+
+ if (!$this->record) {
+ error_log('Weird error writing session');
+ return true;
+ }
+
+ $this->record->sid = $sid; // it might be regenerated
+ $this->record->sessdata = base64_encode($session_data); // there might be some binary mess :-(
+ $this->record->sessdatahash = sha1($this->record->sessdata);
+ $this->record->userid = empty($USER->realuser) ? $USER->id : $USER->realuser;
+ $this->record->timemodified = time();
+ $this->record->lastip = getremoteaddr();
+
+ try {
+ $this->database->update_record_raw('sessions', $this->record);
+ } catch (dml_exception $ex) {
+ error_log('Can not write session to database.');
+ }
+ return true;
+ }
+
+ public function handler_destroy($sid) {
+ if (!$this->record or $this->record->sid != $sid) {
+ error_log('Weird error destroying session - mismatched sid');
+ return true;
+ }
+
+ try {
+ $this->database->delete_records('sessions', array('sid'=>$this->record->sid));
+ } catch (dml_exception $ex) {
+ error_log('Can not destroy database session.');
+ }
+
+ return true;
+ }
+
+ public function handler_gc($maxlifetime) {
+ $select = "timemodified + :maxlifetime < :now";
+ $params = array('now'=>time(), 'maxlifetime'=>$maxlifetime);
+
+ try {
+ $this->database->delete_records_select('sessions', $select, $params);
+ } catch (dml_exception $ex) {
+ error_log('Can not garbage collect database sessions.');
+ }
+
+ return true;
}
+
}
/**
function set_moodle_cookie($thing) {
global $CFG;
+ if (NO_MOODLE_COOKIES) {
+ return;
+ }
+
if ($thing == 'guest') { // Ignore guest account
return;
}
function get_moodle_cookie() {
global $CFG;
+ if (NO_MOODLE_COOKIES) {
+ return '';
+ }
+
$cookiename = 'MOODLEID_'.$CFG->sessioncookie;
if (empty($_COOKIE[$cookiename])) {