Beispiel #1
0
 public function __fav_user_login($user)
 {
     global $CFG, $USER;
     // regenerate session id and delete old session,
     // this helps prevent session fixation attacks from the same domain
     session_regenerate_id(true);
     // let enrol plugins deal with new enrolments if necessary
     enrol_check_plugins($user);
     // check enrolments, load caps and setup $USER object
     session_set_user($user);
     // reload preferences from DB
     unset($USER->preference);
     check_user_preferences_loaded($USER);
     // update login times
     update_user_login_times();
     // extra session prefs init
     set_login_session_preferences();
     if (isguestuser()) {
         // no need to continue when user is THE guest
         return $USER;
     }
     return $USER;
 }
Beispiel #2
0
/**
 * Require key login. Function terminates with error if key not found or incorrect.
 *
 * @uses NO_MOODLE_COOKIES
 * @uses PARAM_ALPHANUM
 * @param string $script unique script identifier
 * @param int $instance optional instance id
 * @return int Instance ID
 */
function require_user_key_login($script, $instance = null)
{
    global $DB;
    if (!NO_MOODLE_COOKIES) {
        print_error('sessioncookiesdisable');
    }
    // Extra safety.
    \core\session\manager::write_close();
    $keyvalue = required_param('key', PARAM_ALPHANUM);
    $key = validate_user_key($keyvalue, $script, $instance);
    if (!($user = $DB->get_record('user', array('id' => $key->userid)))) {
        print_error('invaliduserid');
    }
    // Emulate normal session.
    enrol_check_plugins($user);
    \core\session\manager::set_user($user);
    // Note we are not using normal login.
    if (!defined('USER_KEY_LOGIN')) {
        define('USER_KEY_LOGIN', true);
    }
    // Return instance id - it might be empty.
    return $key->instance;
}
Beispiel #3
0
/**
 * Require key login. Function terminates with error if key not found or incorrect.
 *
 * @uses NO_MOODLE_COOKIES
 * @uses PARAM_ALPHANUM
 * @param string $script unique script identifier
 * @param int $instance optional instance id
 * @return int Instance ID
 */
function require_user_key_login($script, $instance = null)
{
    global $DB;
    if (!NO_MOODLE_COOKIES) {
        print_error('sessioncookiesdisable');
    }
    // Extra safety.
    \core\session\manager::write_close();
    $keyvalue = required_param('key', PARAM_ALPHANUM);
    if (!($key = $DB->get_record('user_private_key', array('script' => $script, 'value' => $keyvalue, 'instance' => $instance)))) {
        print_error('invalidkey');
    }
    if (!empty($key->validuntil) and $key->validuntil < time()) {
        print_error('expiredkey');
    }
    if ($key->iprestriction) {
        $remoteaddr = getremoteaddr(null);
        if (empty($remoteaddr) or !address_in_subnet($remoteaddr, $key->iprestriction)) {
            print_error('ipmismatch');
        }
    }
    if (!($user = $DB->get_record('user', array('id' => $key->userid)))) {
        print_error('invaliduserid');
    }
    // Emulate normal session.
    enrol_check_plugins($user);
    \core\session\manager::set_user($user);
    // Note we are not using normal login.
    if (!defined('USER_KEY_LOGIN')) {
        define('USER_KEY_LOGIN', true);
    }
    // Return instance id - it might be empty.
    return $key->instance;
}
Beispiel #4
0
    $url->set_slashargument("/{$context->id}/{$guesttoken}/{$componentname}/{$instanceid}/rss.xml");
    //redirect to the 2.0 rss URL
    redirect($url);
} else {
    // Authenticate the user from the token
    $userid = rss_get_userid_from_token($token);
    if (!$userid) {
        rss_error('rsserrorauth');
    }
}
// Check the context actually exists
list($context, $course, $cm) = get_context_info_array($contextid);
$PAGE->set_context($context);
$user = get_complete_user_data('id', $userid);
// let enrol plugins deal with new enrolments if necessary
enrol_check_plugins($user);
\core\session\manager::set_user($user);
//for login and capability checks
try {
    $autologinguest = true;
    $setwantsurltome = true;
    $preventredirect = true;
    require_login($course, $autologinguest, $cm, $setwantsurltome, $preventredirect);
} catch (Exception $e) {
    if (isguestuser()) {
        rss_error('rsserrorguest');
    } else {
        rss_error('rsserrorauth');
    }
}
// Work out which component in Moodle we want (from the frankenstyle name)
Beispiel #5
0
/**
 * Login as another user - no security checks here.
 * @param int $userid
 * @param stdClass $context
 * @return void
 */
function session_loginas($userid, $context)
{
    if (session_is_loggedinas()) {
        return;
    }
    // switch to fresh new $SESSION
    $_SESSION['REALSESSION'] = $_SESSION['SESSION'];
    $_SESSION['SESSION'] = new stdClass();
    /// Create the new $USER object with all details and reload needed capabilities
    $_SESSION['REALUSER'] = $_SESSION['USER'];
    $user = get_complete_user_data('id', $userid);
    $user->realuser = $_SESSION['REALUSER']->id;
    $user->loginascontext = $context;
    // let enrol plugins deal with new enrolments if necessary
    enrol_check_plugins($user);
    // set up global $USER
    session_set_user($user);
}
Beispiel #6
0
        } else {
            if (isset($SESSION->wantsurl) and strpos($SESSION->wantsurl, $CFG->wwwroot) === 0) {
                $urltogo = $SESSION->wantsurl;
                /// Because it's an address in this site
                unset($SESSION->wantsurl);
            } else {
                $urltogo = $CFG->wwwroot . '/';
                /// Go to the standard home page
                unset($SESSION->wantsurl);
                /// Just in case
            }
        }
        /// Go to my-moodle page instead of homepage if defaulthomepage enabled
        if (!has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)) and !empty($CFG->defaulthomepage) && $CFG->defaulthomepage == HOMEPAGE_MY and !isguestuser()) {
            if ($urltogo == $CFG->wwwroot or $urltogo == $CFG->wwwroot . '/' or $urltogo == $CFG->wwwroot . '/index.php') {
                $urltogo = $CFG->wwwroot . '/my/';
            }
        }
        enrol_check_plugins($USER);
        load_all_capabilities();
        /// This is what lets the user do anything on the site  :-)
        redirect($urltogo);
        exit;
    } else {
        // For some weird reason the Shibboleth user couldn't be authenticated
    }
} elseif (!empty($_SERVER['HTTP_SHIB_APPLICATION_ID']) || !empty($_SERVER['Shib-Application-ID'])) {
    print_error('shib_no_attributes_error', 'auth', '', '\'' . $pluginconfig->user_attribute . '\', \'' . $pluginconfig->field_map_firstname . '\', \'' . $pluginconfig->field_map_lastname . '\' and \'' . $pluginconfig->field_map_email . '\'');
} else {
    print_error('shib_not_set_up_error', 'auth');
}
Beispiel #7
0
 /**
  * Authenticate user using username+password or token.
  * This function sets up $USER global.
  * It is safe to use has_capability() after this.
  * This method also verifies user is allowed to use this
  * server.
  */
 protected function authenticate_user()
 {
     global $CFG, $DB;
     if (!NO_MOODLE_COOKIES) {
         throw new coding_exception('Cookies must be disabled in WS servers!');
     }
     $loginfaileddefaultparams = array('context' => context_system::instance(), 'other' => array('method' => $this->authmethod, 'reason' => null));
     if ($this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME) {
         //we check that authentication plugin is enabled
         //it is only required by simple authentication
         if (!is_enabled_auth('webservice')) {
             throw new webservice_access_exception('The web service authentication plugin is disabled.');
         }
         if (!($auth = get_auth_plugin('webservice'))) {
             throw new webservice_access_exception('The web service authentication plugin is missing.');
         }
         $this->restricted_context = context_system::instance();
         if (!$this->username) {
             throw new moodle_exception('missingusername', 'webservice');
         }
         if (!$this->password) {
             throw new moodle_exception('missingpassword', 'webservice');
         }
         if (!$auth->user_login_webservice($this->username, $this->password)) {
             // Log failed login attempts.
             $params = $loginfaileddefaultparams;
             $params['other']['reason'] = 'password';
             $params['other']['username'] = $this->username;
             $event = \core\event\webservice_login_failed::create($params);
             $event->set_legacy_logdata(array(SITEID, 'webservice', get_string('simpleauthlog', 'webservice'), '', get_string('failedtolog', 'webservice') . ": " . $this->username . "/" . $this->password . " - " . getremoteaddr(), 0));
             $event->trigger();
             throw new moodle_exception('wrongusernamepassword', 'webservice');
         }
         $user = $DB->get_record('user', array('username' => $this->username, 'mnethostid' => $CFG->mnet_localhost_id), '*', MUST_EXIST);
     } else {
         if ($this->authmethod == WEBSERVICE_AUTHMETHOD_PERMANENT_TOKEN) {
             $user = $this->authenticate_by_token(EXTERNAL_TOKEN_PERMANENT);
         } else {
             $user = $this->authenticate_by_token(EXTERNAL_TOKEN_EMBEDDED);
         }
     }
     //Non admin can not authenticate if maintenance mode
     $hassiteconfig = has_capability('moodle/site:config', context_system::instance(), $user);
     if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) {
         throw new moodle_exception('sitemaintenance', 'admin');
     }
     //only confirmed user should be able to call web service
     if (!empty($user->deleted)) {
         $params = $loginfaileddefaultparams;
         $params['other']['reason'] = 'user_deleted';
         $params['other']['username'] = $user->username;
         $event = \core\event\webservice_login_failed::create($params);
         $event->set_legacy_logdata(array(SITEID, '', '', '', get_string('wsaccessuserdeleted', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id));
         $event->trigger();
         throw new webservice_access_exception('Refused web service access for deleted username: '******'other']['reason'] = 'user_unconfirmed';
         $params['other']['username'] = $user->username;
         $event = \core\event\webservice_login_failed::create($params);
         $event->set_legacy_logdata(array(SITEID, '', '', '', get_string('wsaccessuserunconfirmed', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id));
         $event->trigger();
         throw new moodle_exception('wsaccessuserunconfirmed', 'webservice', '', $user->username);
     }
     //check the user is suspended
     if (!empty($user->suspended)) {
         $params = $loginfaileddefaultparams;
         $params['other']['reason'] = 'user_unconfirmed';
         $params['other']['username'] = $user->username;
         $event = \core\event\webservice_login_failed::create($params);
         $event->set_legacy_logdata(array(SITEID, '', '', '', get_string('wsaccessusersuspended', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id));
         $event->trigger();
         throw new webservice_access_exception('Refused web service access for suspended username: '******'other']['reason'] = 'password_expired';
             $params['other']['username'] = $user->username;
             $event = \core\event\webservice_login_failed::create($params);
             $event->set_legacy_logdata(array(SITEID, '', '', '', get_string('wsaccessuserexpired', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id));
             $event->trigger();
             throw new webservice_access_exception('Refused web service access for password expired username: '******'nologin') {
         $params = $loginfaileddefaultparams;
         $params['other']['reason'] = 'login';
         $params['other']['username'] = $user->username;
         $event = \core\event\webservice_login_failed::create($params);
         $event->set_legacy_logdata(array(SITEID, '', '', '', get_string('wsaccessusernologin', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id));
         $event->trigger();
         throw new webservice_access_exception('Refused web service access for nologin authentication username: '******'You are not allowed to use the {$a} protocol (missing capability: webservice/' . $this->wsname . ':use)');
     }
     external_api::set_context_restriction($this->restricted_context);
 }
Beispiel #8
0
/**
 * Call to complete the user login process after authenticate_user_login()
 * has succeeded. It will setup the $USER variable and other required bits
 * and pieces.
 *
 * NOTE:
 * - It will NOT log anything -- up to the caller to decide what to log.
 * - this function does not set any cookies any more!
 *
 * @param object $user
 * @return object A {@link $USER} object - BC only, do not use
 */
function complete_user_login($user)
{
    global $CFG, $USER;
    // regenerate session id and delete old session,
    // this helps prevent session fixation attacks from the same domain
    session_regenerate_id(true);
    // let enrol plugins deal with new enrolments if necessary
    enrol_check_plugins($user);
    // check enrolments, load caps and setup $USER object
    session_set_user($user);
    // reload preferences from DB
    unset($USER->preference);
    check_user_preferences_loaded($USER);
    // update login times
    update_user_login_times();
    // extra session prefs init
    set_login_session_preferences();
    if (isguestuser()) {
        // no need to continue when user is THE guest
        return $USER;
    }
    /// Select password change url
    $userauth = get_auth_plugin($USER->auth);
    /// check whether the user should be changing password
    if (get_user_preferences('auth_forcepasswordchange', false)) {
        if ($userauth->can_change_password()) {
            if ($changeurl = $userauth->change_password_url()) {
                redirect($changeurl);
            } else {
                redirect($CFG->httpswwwroot . '/login/change_password.php');
            }
        } else {
            print_error('nopasswordchangeforced', 'auth');
        }
    }
    return $USER;
}
Beispiel #9
0
 /**
  * Login as another user - no security checks here.
  * @param int $userid
  * @param \context $context
  * @return void
  */
 public static function loginas($userid, \context $context)
 {
     global $USER;
     if (self::is_loggedinas()) {
         return;
     }
     // Switch to fresh new $_SESSION.
     $_SESSION = array();
     $_SESSION['REALSESSION'] = clone $GLOBALS['SESSION'];
     $GLOBALS['SESSION'] = new \stdClass();
     $_SESSION['SESSION'] =& $GLOBALS['SESSION'];
     // Create the new $USER object with all details and reload needed capabilities.
     $_SESSION['REALUSER'] = clone $GLOBALS['USER'];
     $user = get_complete_user_data('id', $userid);
     $user->realuser = $_SESSION['REALUSER']->id;
     $user->loginascontext = $context;
     // Let enrol plugins deal with new enrolments if necessary.
     enrol_check_plugins($user);
     // Create event before $USER is updated.
     $event = \core\event\user_loggedinas::create(array('objectid' => $USER->id, 'context' => $context, 'relateduserid' => $userid, 'other' => array('originalusername' => fullname($USER, true), 'loggedinasusername' => fullname($user, true))));
     // Set up global $USER.
     \core\session\manager::set_user($user);
     $event->trigger();
 }
Beispiel #10
0
 /**
  * Authenticate user using username+password or token.
  * This function sets up $USER global.
  * It is safe to use has_capability() after this.
  * This method also verifies user is allowed to use this
  * server.
  */
 protected function authenticate_user()
 {
     global $CFG, $DB;
     if (!NO_MOODLE_COOKIES) {
         throw new coding_exception('Cookies must be disabled in WS servers!');
     }
     if ($this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME) {
         //we check that authentication plugin is enabled
         //it is only required by simple authentication
         if (!is_enabled_auth('webservice')) {
             throw new webservice_access_exception(get_string('wsauthnotenabled', 'webservice'));
         }
         if (!($auth = get_auth_plugin('webservice'))) {
             throw new webservice_access_exception(get_string('wsauthmissing', 'webservice'));
         }
         $this->restricted_context = get_context_instance(CONTEXT_SYSTEM);
         if (!$this->username) {
             throw new webservice_access_exception(get_string('missingusername', 'webservice'));
         }
         if (!$this->password) {
             throw new webservice_access_exception(get_string('missingpassword', 'webservice'));
         }
         if (!$auth->user_login_webservice($this->username, $this->password)) {
             // log failed login attempts
             add_to_log(SITEID, 'webservice', get_string('simpleauthlog', 'webservice'), '', get_string('failedtolog', 'webservice') . ": " . $this->username . "/" . $this->password . " - " . getremoteaddr(), 0);
             throw new webservice_access_exception(get_string('wrongusernamepassword', 'webservice'));
         }
         $user = $DB->get_record('user', array('username' => $this->username, 'mnethostid' => $CFG->mnet_localhost_id), '*', MUST_EXIST);
     } else {
         if ($this->authmethod == WEBSERVICE_AUTHMETHOD_PERMANENT_TOKEN) {
             $user = $this->authenticate_by_token(EXTERNAL_TOKEN_PERMANENT);
         } else {
             $user = $this->authenticate_by_token(EXTERNAL_TOKEN_EMBEDDED);
         }
     }
     //Non admin can not authenticate if maintenance mode
     $hassiteconfig = has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM), $user);
     if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) {
         throw new webservice_access_exception(get_string('sitemaintenance', 'admin'));
     }
     //only confirmed user should be able to call web service
     if (!empty($user->deleted)) {
         add_to_log(SITEID, '', '', '', get_string('wsaccessuserdeleted', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id);
         throw new webservice_access_exception(get_string('wsaccessuserdeleted', 'webservice', $user->username));
     }
     //only confirmed user should be able to call web service
     if (empty($user->confirmed)) {
         add_to_log(SITEID, '', '', '', get_string('wsaccessuserunconfirmed', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id);
         throw new webservice_access_exception(get_string('wsaccessuserunconfirmed', 'webservice', $user->username));
     }
     //check the user is suspended
     if (!empty($user->suspended)) {
         add_to_log(SITEID, '', '', '', get_string('wsaccessusersuspended', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id);
         throw new webservice_access_exception(get_string('wsaccessusersuspended', 'webservice', $user->username));
     }
     //retrieve the authentication plugin if no previously done
     if (empty($auth)) {
         $auth = get_auth_plugin($user->auth);
     }
     // check if credentials have expired
     if (!empty($auth->config->expiration) and $auth->config->expiration == 1) {
         $days2expire = $auth->password_expire($user->username);
         if (intval($days2expire) < 0) {
             add_to_log(SITEID, '', '', '', get_string('wsaccessuserexpired', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id);
             throw new webservice_access_exception(get_string('wsaccessuserexpired', 'webservice', $user->username));
         }
     }
     //check if the auth method is nologin (in this case refuse connection)
     if ($user->auth == 'nologin') {
         add_to_log(SITEID, '', '', '', get_string('wsaccessusernologin', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id);
         throw new webservice_access_exception(get_string('wsaccessusernologin', 'webservice', $user->username));
     }
     // now fake user login, the session is completely empty too
     enrol_check_plugins($user);
     session_set_user($user);
     $this->userid = $user->id;
     if ($this->authmethod != WEBSERVICE_AUTHMETHOD_SESSION_TOKEN && !has_capability("webservice/{$this->wsname}:use", $this->restricted_context)) {
         throw new webservice_access_exception(get_string('protocolnotallowed', 'webservice', $this->wsname));
     }
     external_api::set_context_restriction($this->restricted_context);
 }
Beispiel #11
0
/**
 * Setup $USER object - called during login, loginas, etc.
 * Preloads capabilities and checks enrolment plugins
 *
 * @param stdClass $user full user record object
 * @return void
 */
function session_set_user($user)
{
    $_SESSION['USER'] = $user;
    unset($_SESSION['USER']->description);
    // conserve memory
    if (!isset($_SESSION['USER']->access)) {
        // check enrolments and load caps only once
        enrol_check_plugins($_SESSION['USER']);
        load_all_capabilities();
    }
    sesskey();
    // init session key
}
Beispiel #12
0
 /**
  * Authenticate user using username+password or token.
  * This function sets up $USER global.
  * It is safe to use has_capability() after this.
  * This method also verifies user is allowed to use this
  * server.
  * @return void
  */
 protected function authenticate_user()
 {
     global $CFG, $DB;
     if (!NO_MOODLE_COOKIES) {
         throw new coding_exception('Cookies must be disabled in WS servers!');
     }
     if ($this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME) {
         //we check that authentication plugin is enabled
         //it is only required by simple authentication
         if (!is_enabled_auth('webservice')) {
             throw new webservice_access_exception(get_string('wsauthnotenabled', 'webservice'));
         }
         if (!($auth = get_auth_plugin('webservice'))) {
             throw new webservice_access_exception(get_string('wsauthmissing', 'webservice'));
         }
         $this->restricted_context = get_context_instance(CONTEXT_SYSTEM);
         if (!$this->username) {
             throw new webservice_access_exception(get_string('missingusername', 'webservice'));
         }
         if (!$this->password) {
             throw new webservice_access_exception(get_string('missingpassword', 'webservice'));
         }
         if (!$auth->user_login_webservice($this->username, $this->password)) {
             // log failed login attempts
             add_to_log(SITEID, 'webservice', get_string('simpleauthlog', 'webservice'), '', get_string('failedtolog', 'webservice') . ": " . $this->username . "/" . $this->password . " - " . getremoteaddr(), 0);
             throw new webservice_access_exception(get_string('wrongusernamepassword', 'webservice'));
         }
         $user = $DB->get_record('user', array('username' => $this->username, 'mnethostid' => $CFG->mnet_localhost_id, 'deleted' => 0), '*', MUST_EXIST);
     } else {
         if ($this->authmethod == WEBSERVICE_AUTHMETHOD_PERMANENT_TOKEN) {
             $user = $this->authenticate_by_token(EXTERNAL_TOKEN_PERMANENT);
         } else {
             $user = $this->authenticate_by_token(EXTERNAL_TOKEN_EMBEDDED);
         }
     }
     // now fake user login, the session is completely empty too
     enrol_check_plugins($user);
     session_set_user($user);
     $this->userid = $user->id;
     if ($this->authmethod != WEBSERVICE_AUTHMETHOD_SESSION_TOKEN && !has_capability("webservice/{$this->wsname}:use", $this->restricted_context)) {
         throw new webservice_access_exception(get_string('protocolnotallowed', 'webservice', $this->wsname));
     }
     external_api::set_context_restriction($this->restricted_context);
 }
Beispiel #13
0
 /**
  * See if the request contains a proper username/password for login
  *
  * @param  Zend_Controller_Request_Http $request The request to check
  * @return boolean
  */
 public function isValid($request)
 {
     // No cookies !
     if (!PHPUNIT_TEST) {
         if (!defined('NO_MOODLE_COOKIES') or !NO_MOODLE_COOKIES) {
             $this->_error(self::LOGIN_COOKIE);
             return false;
         }
     }
     $wsusername = $request->getParam($this->_paramusername, '');
     $wsusername = clean_param($wsusername, PARAM_RAW);
     $wspassword = $request->getParam($this->_parampassword, '');
     $wspassword = clean_param($wspassword, PARAM_RAW);
     // Are they empty ?
     if (empty($wsusername) or empty($wspassword)) {
         $this->_error(self::LOGIN_MISSING);
         return false;
     }
     // Can we login ?
     if (!($user = authenticate_user_login($wsusername, $wspassword))) {
         $this->_error(self::LOGIN_FAIL);
         return false;
     }
     // Set the user to the session
     enrol_check_plugins($user);
     \core\session\manager::set_user($user);
     return true;
 }
 /**
  * Get recent activity for course(s)
  *
  * The passed course(s) will get populated with recent activity
  * and returned.  EG: $course->recentactivity = array(...of activity...);
  *
  * @param int $timestart Look for activity after this time
  * @param array|stdClass $courses An array of course objects or a single course object
  * @param mixed $otheruser The user who will view the list of activity.  If NULL, then currently logged in user is used.
  * @throws Exception
  * @return array
  */
 public function direct($timestart, $courses, $otheruser = NULL)
 {
     global $DB, $CFG, $USER;
     $recentactivity = array();
     // Param checks
     if (is_null($timestart) or empty($courses)) {
         return $recentactivity;
     }
     if (!is_array($courses)) {
         $courses = array($courses->id => $courses);
     }
     if (!is_null($otheruser)) {
         $currentuser = clone $USER;
         enrol_check_plugins($otheruser);
         \core\session\manager::set_user($otheruser);
     } else {
         $currentuser = false;
     }
     $timestart = clean_param($timestart, PARAM_INT);
     if ($allmods = $DB->get_records('modules')) {
         foreach ($allmods as $mod) {
             if ($mod->visible) {
                 $modnames[$mod->name] = get_string('modulename', $mod->name);
             }
         }
     } else {
         throw new Exception('No modules are installed!');
     }
     // Gather recent activity
     foreach ($courses as $course) {
         $modinfo = get_fast_modinfo($course);
         $viewfullnames = has_capability('moodle/site:viewfullnames', context_course::instance($course->id));
         $activities = array();
         $index = 0;
         $recentactivity[$course->id] = $course;
         $recentactivity[$course->id]->recentactivity = array();
         $logs = $DB->get_records_sql("SELECT l.*, u.firstname, u.lastname, u.picture\n                                            FROM {log} l\n                                 LEFT OUTER JOIN {user} u ON l.userid = u.id\n                                           WHERE time > ?\n                                             AND course = ?\n                                             AND module = 'course'\n                                             AND (action = 'add mod' OR action = 'update mod' OR action = 'delete mod')\n                                        ORDER BY id ASC", array($timestart, $course->id));
         if ($logs) {
             $changelist = array();
             $newgones = array();
             // added and later deleted items
             foreach ($logs as $key => $log) {
                 $info = explode(' ', $log->info);
                 // Labels are ignored in recent activity
                 if ($info[0] == 'label') {
                     continue;
                 }
                 // Check for incorrect entry
                 if (count($info) != 2) {
                     continue;
                 }
                 $modname = $info[0];
                 $instanceid = $info[1];
                 $userinfo = new stdClass();
                 $userinfo->id = $log->userid;
                 $userinfo->userid = $log->userid;
                 $userinfo->fullname = '';
                 $userinfo->picture = $log->picture;
                 if (!empty($log->firstname) and !empty($log->lastname)) {
                     $a = new stdClass();
                     $a->fullname = fullname($log, $viewfullnames);
                     $a->modname = get_string('modulename', $modname);
                     $userinfo->fullname = $a->fullname;
                 } else {
                     $a = false;
                 }
                 if ($log->action == 'delete mod') {
                     // unfortunately we do not know if the mod was visible
                     if (!array_key_exists($log->info, $newgones)) {
                         if ($a) {
                             $strdeleted = get_string('deletedactivity', 'local_mr', $a);
                         } else {
                             $strdeleted = get_string('deletedactivity', 'moodle', get_string('modulename', $modname));
                         }
                         $changelist[$log->info] = (object) array('cmid' => $log->cmid, 'type' => $modname, 'name' => '', 'action' => 'delete', 'timestamp' => $log->time, 'description_html' => $strdeleted, 'description_text' => $strdeleted, 'user' => $userinfo);
                     }
                 } else {
                     if (!isset($modinfo->instances[$modname][$instanceid])) {
                         if ($log->action == 'add mod') {
                             // do not display added and later deleted activities
                             $newgones[$log->info] = true;
                         }
                         continue;
                     }
                     $cm = $modinfo->instances[$modname][$instanceid];
                     if (!$cm->uservisible) {
                         continue;
                     }
                     if ($log->action == 'add mod') {
                         if ($a) {
                             $stradded = get_string('addedactivity', 'local_mr', $a);
                         } else {
                             $stradded = get_string('added', 'moodle', get_string('modulename', $modname));
                         }
                         $changelist[$log->info] = (object) array('cmid' => $cm->id, 'type' => $modname, 'name' => $cm->name, 'action' => 'add', 'timestamp' => $log->time, 'description_html' => "{$stradded}:<br /><a href=\"{$CFG->wwwroot}/mod/{$cm->modname}/view.php?id={$cm->id}\">" . format_string($cm->name, true) . '</a>', 'description_text' => "{$stradded}: " . format_string($cm->name, true), 'user' => $userinfo);
                     } else {
                         if ($log->action == 'update mod' and empty($changelist[$log->info])) {
                             if ($a) {
                                 $strupdated = get_string('updatedactivity', 'local_mr', $a);
                             } else {
                                 $strupdated = get_string('updated', 'moodle', get_string('modulename', $modname));
                             }
                             $changelist[$log->info] = (object) array('cmid' => $cm->id, 'type' => $modname, 'name' => $cm->name, 'action' => 'update', 'timestamp' => $log->time, 'description_html' => "{$strupdated}:<br /><a href=\"{$CFG->wwwroot}/mod/{$cm->modname}/view.php?id={$cm->id}\">" . format_string($cm->name, true) . '</a>', 'description_text' => "{$strupdated}: " . format_string($cm->name, true), 'user' => $userinfo);
                         }
                     }
                 }
             }
             // Add to main recentactivity array
             $recentactivity[$course->id]->recentactivity = array_values($changelist);
         }
         foreach ($modinfo->cms as $cm) {
             if (!$cm->uservisible) {
                 continue;
             }
             $lib = "{$CFG->dirroot}/mod/{$cm->modname}/lib.php";
             if (file_exists($lib)) {
                 require_once $lib;
                 $get_recent_mod_activity = "{$cm->modname}_get_recent_mod_activity";
                 if (function_exists($get_recent_mod_activity)) {
                     $get_recent_mod_activity($activities, $index, $timestart, $course->id, $cm->id, 0, 0);
                 }
             }
         }
         foreach ($activities as $activity) {
             $print_recent_mod_activity = "{$activity->type}_print_recent_mod_activity";
             if (function_exists($print_recent_mod_activity)) {
                 ob_start();
                 $print_recent_mod_activity($activity, $course->id, true, $modnames, true);
                 $description = ob_get_contents();
                 ob_end_clean();
                 $activity->description_html = $description;
                 $activity->description_text = trim(strip_tags(str_replace(array('</td>', '</div>'), array(' </td>', ' </div>'), $description)));
                 if (empty($activity->timestamp)) {
                     $activity->timestamp = 0;
                 }
                 $recentactivity[$course->id]->recentactivity[] = $activity;
             }
         }
     }
     // Sort recent activity
     foreach ($recentactivity as $courseid => $course) {
         uasort($course->recentactivity, create_function('$a, $b', 'return ($a->timestamp == $b->timestamp) ? 0 : (($a->timestamp > $b->timestamp) ? -1 : 1);'));
         $recentactivity[$courseid]->recentactivity = array_values($course->recentactivity);
     }
     if ($currentuser !== false) {
         \core\session\manager::set_user($currentuser);
     }
     return $recentactivity;
 }