Merge branch 'w39_MDL-41437_m26_mia' of https://github.com/skodak/moodle
[moodle.git] / lib / moodlelib.php
index ad1e363..c003719 100644 (file)
@@ -1582,7 +1582,7 @@ function get_users_from_config($value, $capability, $includeadmins = true) {
  * @return void
  */
 function purge_all_caches() {
-    global $CFG;
+    global $CFG, $DB;
 
     reset_text_filters_cache();
     js_reset_all_caches();
@@ -1600,6 +1600,7 @@ function purge_all_caches() {
         // Ignore exception since this function is also called before upgrade script when field course.cacherev does not exist yet.
     }
 
+    $DB->reset_caches();
     cache_helper::purge_all();
 
     // Purge all other caches: rss, simplepie, etc.
@@ -2899,7 +2900,7 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $
     }
 
     // Loginas as redirection if needed.
-    if ($course->id != SITEID and session_is_loggedinas()) {
+    if ($course->id != SITEID and \core\session\manager::is_loggedinas()) {
         if ($USER->loginascontext->contextlevel == CONTEXT_COURSE) {
             if ($USER->loginascontext->instanceid != $course->id) {
                 print_error('loginasonecourse', '', $CFG->wwwroot.'/course/view.php?id='.$USER->loginascontext->instanceid);
@@ -2908,7 +2909,7 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $
     }
 
     // Check whether the user should be changing password (but only if it is REALLY them).
-    if (get_user_preferences('auth_forcepasswordchange') && !session_is_loggedinas()) {
+    if (get_user_preferences('auth_forcepasswordchange') && !\core\session\manager::is_loggedinas()) {
         $userauth = get_auth_plugin($USER->auth);
         if ($userauth->can_change_password() and !$preventredirect) {
             if ($setwantsurltome) {
@@ -3016,9 +3017,9 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $
     if ($course->id == SITEID) {
         // Everybody is enrolled on the frontpage.
     } else {
-        if (session_is_loggedinas()) {
+        if (\core\session\manager::is_loggedinas()) {
             // Make sure the REAL person can access this course first.
-            $realuser = session_get_realuser();
+            $realuser = \core\session\manager::get_realuser();
             if (!is_enrolled($coursecontext, $realuser->id, '', true) and
                 !is_viewing($coursecontext, $realuser->id) and !is_siteadmin($realuser->id)) {
                 if ($preventredirect) {
@@ -3150,26 +3151,39 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $
  * @category   access
  */
 function require_logout() {
-    global $USER;
+    global $USER, $DB;
 
-    if (isloggedin()) {
-        $authsequence = get_enabled_auth_plugins(); // Auths, in sequence.
-        foreach ($authsequence as $authname) {
-            $authplugin = get_auth_plugin($authname);
-            $authplugin->prelogout_hook();
-        }
+    if (!isloggedin()) {
+        // This should not happen often, no need for hooks or events here.
+        \core\session\manager::terminate_current();
+        return;
     }
 
+    // Execute hooks before action.
+    $authsequence = get_enabled_auth_plugins();
+    foreach ($authsequence as $authname) {
+        $authplugin = get_auth_plugin($authname);
+        $authplugin->prelogout_hook();
+    }
+
+    // Store info that gets removed during logout.
+    $sid = session_id();
     $event = \core\event\user_loggedout::create(
-            array(
-                'objectid' => $USER->id,
-                'context' => context_user::instance($USER->id)
-                )
-            );
-    $event->trigger();
+        array(
+            'userid' => $USER->id,
+            'objectid' => $USER->id,
+            'other' => array('sessionid' => $sid),
+        )
+    );
+    if ($session = $DB->get_record('sessions', array('sid'=>$sid))) {
+        $event->add_record_snapshot('sessions', $session);
+    }
 
-    session_get_instance()->terminate_current();
-    unset($GLOBALS['USER']);
+    // Delete session record and drop $_SESSION content.
+    \core\session\manager::terminate_current();
+
+    // Trigger event AFTER action.
+    $event->trigger();
 }
 
 /**
@@ -3274,7 +3288,7 @@ function require_user_key_login($script, $instance=null) {
     }
 
     // Extra safety.
-    @session_write_close();
+    \core\session\manager::write_close();
 
     $keyvalue = required_param('key', PARAM_ALPHANUM);
 
@@ -3299,7 +3313,7 @@ function require_user_key_login($script, $instance=null) {
 
     // Emulate normal session.
     enrol_check_plugins($user);
-    session_set_user($user);
+    \core\session\manager::set_user($user);
 
     // Note we are not using normal login.
     if (!defined('USER_KEY_LOGIN')) {
@@ -4157,7 +4171,7 @@ function delete_user(stdClass $user) {
     $DB->delete_records('user_private_key', array('userid' => $user->id));
 
     // Force logout - may fail if file based sessions used, sorry.
-    session_kill_user($user->id);
+    \core\session\manager::kill_user_sessions($user->id);
 
     // Workaround for bulk deletes of users with the same email address.
     $delname = "$user->email.".time();
@@ -4389,15 +4403,7 @@ function authenticate_user_login($username, $password, $ignorelockout=false, &$f
 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);
+    \core\session\manager::login_user($user);
 
     // Reload preferences from DB.
     unset($USER->preference);
@@ -4409,11 +4415,27 @@ function complete_user_login($user) {
     // Extra session prefs init.
     set_login_session_preferences();
 
+    // Trigger login event.
+    $event = \core\event\user_loggedin::create(
+        array(
+            'userid' => $USER->id,
+            'objectid' => $USER->id,
+            'other' => array('username' => $USER->username),
+        )
+    );
+    $event->add_record_snapshot('user', $user);
+    $event->trigger();
+
     if (isguestuser()) {
         // No need to continue when user is THE guest.
         return $USER;
     }
 
+    if (CLI_SCRIPT) {
+        // We can redirect to password change URL only in browser.
+        return $USER;
+    }
+
     // Select password change url.
     $userauth = get_auth_plugin($USER->auth);
 
@@ -5424,6 +5446,7 @@ function moodle_process_email($modargs, $body) {
 function get_mailer($action='get') {
     global $CFG;
 
+    /** @var moodle_phpmailer $mailer */
     static $mailer  = null;
     static $counter = 0;
 
@@ -5435,7 +5458,7 @@ function get_mailer($action='get') {
         $prevkeepalive = false;
 
         if (isset($mailer) and $mailer->Mailer == 'smtp') {
-            if ($counter < $CFG->smtpmaxbulk and !$mailer->IsError()) {
+            if ($counter < $CFG->smtpmaxbulk and !$mailer->isError()) {
                 $counter++;
                 // Reset the mailer.
                 $mailer->Priority         = 3;
@@ -5450,10 +5473,10 @@ function get_mailer($action='get') {
                 $mailer->AltBody          = "";
                 $mailer->ConfirmReadingTo = "";
 
-                $mailer->ClearAllRecipients();
-                $mailer->ClearReplyTos();
-                $mailer->ClearAttachments();
-                $mailer->ClearCustomHeaders();
+                $mailer->clearAllRecipients();
+                $mailer->clearReplyTos();
+                $mailer->clearAttachments();
+                $mailer->clearCustomHeaders();
                 return $mailer;
             }
 
@@ -5461,35 +5484,22 @@ function get_mailer($action='get') {
             get_mailer('flush');
         }
 
-        include_once($CFG->libdir.'/phpmailer/moodle_phpmailer.php');
+        require_once($CFG->libdir.'/phpmailer/moodle_phpmailer.php');
         $mailer = new moodle_phpmailer();
 
         $counter = 1;
 
-        // Mailer version.
-        $mailer->Version   = 'Moodle '.$CFG->version;
-        // Plugin directory (eg smtp plugin).
-        $mailer->PluginDir = $CFG->libdir.'/phpmailer/';
-        $mailer->CharSet   = 'UTF-8';
-
-        // Some MTAs may do double conversion of LF if CRLF used, CRLF is required line ending in RFC 822bis.
-        if (isset($CFG->mailnewline) and $CFG->mailnewline == 'CRLF') {
-            $mailer->LE = "\r\n";
-        } else {
-            $mailer->LE = "\n";
-        }
-
         if ($CFG->smtphosts == 'qmail') {
             // Use Qmail system.
-            $mailer->IsQmail();
+            $mailer->isQmail();
 
         } else if (empty($CFG->smtphosts)) {
             // Use PHP mail() = sendmail.
-            $mailer->IsMail();
+            $mailer->isMail();
 
         } else {
             // Use SMTP directly.
-            $mailer->IsSMTP();
+            $mailer->isSMTP();
             if (!empty($CFG->debugsmtp)) {
                 $mailer->SMTPDebug = true;
             }
@@ -5695,10 +5705,10 @@ function email_to_user($user, $from, $subject, $messagetext, $messagehtml = '',
         // Add custom headers.
         if (is_array($from->customheaders)) {
             foreach ($from->customheaders as $customheader) {
-                $mail->AddCustomHeader($customheader);
+                $mail->addCustomHeader($customheader);
             }
         } else {
-            $mail->AddCustomHeader($from->customheaders);
+            $mail->addCustomHeader($from->customheaders);
         }
     }
 
@@ -5708,7 +5718,7 @@ function email_to_user($user, $from, $subject, $messagetext, $messagehtml = '',
 
     if ($messagehtml && !empty($user->mailformat) && $user->mailformat == 1) {
         // Don't ever send HTML to users who don't want it.
-        $mail->IsHTML(true);
+        $mail->isHTML(true);
         $mail->Encoding = 'quoted-printable';
         $mail->Body    =  $messagehtml;
         $mail->AltBody =  "\n$messagetext\n";
@@ -5721,11 +5731,11 @@ function email_to_user($user, $from, $subject, $messagetext, $messagehtml = '',
         if (preg_match( "~\\.\\.~" , $attachment )) {
             // Security check for ".." in dir path.
             $temprecipients[] = array($supportuser->email, fullname($supportuser, true));
-            $mail->AddStringAttachment('Error in attachment.  User attempted to attach a filename with a unsafe name.', 'error.txt', '8bit', 'text/plain');
+            $mail->addStringAttachment('Error in attachment.  User attempted to attach a filename with a unsafe name.', 'error.txt', '8bit', 'text/plain');
         } else {
             require_once($CFG->libdir.'/filelib.php');
             $mimetype = mimeinfo('type', $attachname);
-            $mail->AddAttachment($CFG->dataroot .'/'. $attachment, $attachname, 'base64', $mimetype);
+            $mail->addAttachment($CFG->dataroot .'/'. $attachment, $attachname, 'base64', $mimetype);
         }
     }
 
@@ -5760,13 +5770,13 @@ function email_to_user($user, $from, $subject, $messagetext, $messagehtml = '',
     }
 
     foreach ($temprecipients as $values) {
-        $mail->AddAddress($values[0], $values[1]);
+        $mail->addAddress($values[0], $values[1]);
     }
     foreach ($tempreplyto as $values) {
-        $mail->AddReplyTo($values[0], $values[1]);
+        $mail->addReplyTo($values[0], $values[1]);
     }
 
-    if ($mail->Send()) {
+    if ($mail->send()) {
         set_send_count($user);
         if (!empty($mail->SMTPDebug)) {
             echo '</pre>';
@@ -8837,10 +8847,10 @@ function get_performance_info() {
     }
 
     // Display size of session if session started.
-    if (session_id()) {
-        $info['sessionsize'] = display_size(strlen(session_encode()));
-        $info['html'] .= '<span class="sessionsize">Session: ' . $info['sessionsize'] . '</span> ';
-        $info['txt'] .= "Session: {$info['sessionsize']} ";
+    if ($si = \core\session\manager::get_performance_info()) {
+        $info['sessionsize'] = $si['size'];
+        $info['html'] .= $si['html'];
+        $info['txt'] .= $si['txt'];
     }
 
     if ($stats = cache_helper::get_stats()) {