Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
/lib/ -> sessionlib.php (source)

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * @package    core
  19   * @subpackage session
  20   * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  21   * @copyright  2008, 2009 Petr Skoda  {@link http://skodak.org}
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  
  28  /**
  29   * Makes sure that $USER->sesskey exists, if $USER itself exists. It sets a new sesskey
  30   * if one does not already exist, but does not overwrite existing sesskeys. Returns the
  31   * sesskey string if $USER exists, or boolean false if not.
  32   *
  33   * @uses $USER
  34   * @return string
  35   */
  36  function sesskey() {
  37      // note: do not use $USER because it may not be initialised yet
  38      if (empty($_SESSION['USER']->sesskey)) {
  39          if (!isset($_SESSION['USER'])) {
  40              // This should never happen,
  41              // do not mess with session and globals here,
  42              // let any checks fail instead!
  43              return false;
  44          }
  45          $_SESSION['USER']->sesskey = random_string(10);
  46      }
  47  
  48      return $_SESSION['USER']->sesskey;
  49  }
  50  
  51  
  52  /**
  53   * Check the sesskey and return true of false for whether it is valid.
  54   * (You might like to imagine this function is called sesskey_is_valid().)
  55   *
  56   * Every script that lets the user perform a significant action (that is,
  57   * changes data in the database) should check the sesskey before doing the action.
  58   * Depending on your code flow, you may want to use the {@link require_sesskey()}
  59   * helper function.
  60   *
  61   * @param string $sesskey The sesskey value to check (optional). Normally leave this blank
  62   *      and this function will do required_param('sesskey', ...).
  63   * @return bool whether the sesskey sent in the request matches the one stored in the session.
  64   */
  65  function confirm_sesskey($sesskey=NULL) {
  66      global $USER;
  67  
  68      if (!empty($USER->ignoresesskey)) {
  69          return true;
  70      }
  71  
  72      if (empty($sesskey)) {
  73          $sesskey = required_param('sesskey', PARAM_RAW);  // Check script parameters
  74      }
  75  
  76      return (sesskey() === $sesskey);
  77  }
  78  
  79  /**
  80   * Check the session key using {@link confirm_sesskey()},
  81   * and cause a fatal error if it does not match.
  82   */
  83  function require_sesskey() {
  84      if (!confirm_sesskey()) {
  85          print_error('invalidsesskey');
  86      }
  87  }
  88  
  89  /**
  90   * Determine wether the secure flag should be set on cookies
  91   * @return bool
  92   */
  93  function is_moodle_cookie_secure() {
  94      global $CFG;
  95  
  96      if (!isset($CFG->cookiesecure)) {
  97          return false;
  98      }
  99      if (!is_https() and empty($CFG->sslproxy)) {
 100          return false;
 101      }
 102      return !empty($CFG->cookiesecure);
 103  }
 104  
 105  /**
 106   * Sets a moodle cookie with a weakly encrypted username
 107   *
 108   * @param string $username to encrypt and place in a cookie, '' means delete current cookie
 109   * @return void
 110   */
 111  function set_moodle_cookie($username) {
 112      global $CFG;
 113  
 114      if (NO_MOODLE_COOKIES) {
 115          return;
 116      }
 117  
 118      if (empty($CFG->rememberusername)) {
 119          // erase current and do not store permanent cookies
 120          $username = '';
 121      }
 122  
 123      if ($username === 'guest') {
 124          // keep previous cookie in case of guest account login
 125          return;
 126      }
 127  
 128      $cookiename = 'MOODLEID1_'.$CFG->sessioncookie;
 129  
 130      $cookiesecure = is_moodle_cookie_secure();
 131  
 132      // Delete old cookie.
 133      setcookie($cookiename, '', time() - HOURSECS, $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $cookiesecure, $CFG->cookiehttponly);
 134  
 135      if ($username !== '') {
 136          // Set username cookie for 60 days.
 137          setcookie($cookiename, rc4encrypt($username), time() + (DAYSECS * 60), $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $cookiesecure, $CFG->cookiehttponly);
 138      }
 139  }
 140  
 141  /**
 142   * Gets a moodle cookie with a weakly encrypted username
 143   *
 144   * @return string username
 145   */
 146  function get_moodle_cookie() {
 147      global $CFG;
 148  
 149      if (NO_MOODLE_COOKIES) {
 150          return '';
 151      }
 152  
 153      if (empty($CFG->rememberusername)) {
 154          return '';
 155      }
 156  
 157      $cookiename = 'MOODLEID1_'.$CFG->sessioncookie;
 158  
 159      if (empty($_COOKIE[$cookiename])) {
 160          return '';
 161      } else {
 162          $username = rc4decrypt($_COOKIE[$cookiename]);
 163          if ($username === 'guest' or $username === 'nobody') {
 164              // backwards compatibility - we do not set these cookies any more
 165              $username = '';
 166          }
 167          return $username;
 168      }
 169  }
 170  
 171  /**
 172   * Sets up current user and course environment (lang, etc.) in cron.
 173   * Do not use outside of cron script!
 174   *
 175   * @param stdClass $user full user object, null means default cron user (admin),
 176   *                 value 'reset' means reset internal static caches.
 177   * @param stdClass $course full course record, null means $SITE
 178   * @param bool $leavepagealone If specified, stops it messing with global page object
 179   * @return void
 180   */
 181  function cron_setup_user($user = null, $course = null, $leavepagealone = false) {
 182      global $CFG, $SITE, $PAGE;
 183  
 184      if (!CLI_SCRIPT && !$leavepagealone) {
 185          throw new coding_exception('Function cron_setup_user() cannot be used in normal requests!');
 186      }
 187  
 188      static $cronuser    = NULL;
 189      static $cronsession = NULL;
 190  
 191      if ($user === 'reset') {
 192          $cronuser = null;
 193          $cronsession = null;
 194          \core\session\manager::init_empty_session();
 195          return;
 196      }
 197  
 198      if (empty($cronuser)) {
 199          /// ignore admins timezone, language and locale - use site default instead!
 200          $cronuser = get_admin();
 201          $cronuser->timezone = $CFG->timezone;
 202          $cronuser->lang     = '';
 203          $cronuser->theme    = '';
 204          unset($cronuser->description);
 205  
 206          $cronsession = new stdClass();
 207      }
 208  
 209      if (!$user) {
 210          // Cached default cron user (==modified admin for now).
 211          \core\session\manager::init_empty_session();
 212          \core\session\manager::set_user($cronuser);
 213          $GLOBALS['SESSION'] = $cronsession;
 214  
 215      } else {
 216          // Emulate real user session - needed for caps in cron.
 217          if ($GLOBALS['USER']->id != $user->id) {
 218              \core\session\manager::init_empty_session();
 219              \core\session\manager::set_user($user);
 220          }
 221      }
 222  
 223      // TODO MDL-19774 relying on global $PAGE in cron is a bad idea.
 224      // Temporary hack so that cron does not give fatal errors.
 225      if (!$leavepagealone) {
 226          $PAGE = new moodle_page();
 227          if ($course) {
 228              $PAGE->set_course($course);
 229          } else {
 230              $PAGE->set_course($SITE);
 231          }
 232      }
 233  
 234      // TODO: it should be possible to improve perf by caching some limited number of users here ;-)
 235  
 236  }