找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 169|回复: 0

[内置扩展] Discuz x3.5 核心文件 function/function_member.php 函数注释

[复制链接]
 楼主| 发表于 2024-3-27 21:35:58 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区

您需要 登录 才可以下载或查看,没有账号?立即注册

×
[PHP] 纯文本查看 复制代码
<?php

/**
 *      [Discuz!] (C)2001-2099 Comsenz Inc.
 *      This is NOT a freeware, use is subject to license terms
 *
 *      $Id: function_member.php 35030 2014-10-23 07:43:23Z laoguozhang $
 */

if(!defined('IN_DISCUZ')) {
        exit('Access Denied');
}
/**
 * 用户登录函数
 *
 * @param string $username 用户名、UID、邮箱或安全手机号
 * @param string $password 用户密码
 * @param int $questionid 安全问题ID(暂未使用)
 * @param string $answer 安全问题答案(暂未使用)
 * @param string $loginfield 登录方式标识,默认为'username',可选'uid'、'email'、'auto'、'secmobile'
 * @param string $ip 用户登录的IP地址,默认为空
 * @return array 返回登录结果,包括状态(status)、用户信息(member)和UC登录结果(ucresult)
 */
function userlogin($username, $password, $questionid, $answer, $loginfield = 'username', $ip = '') {
    $return = array();

    // 根据登录字段确定登录类型
    if($loginfield == 'uid' && getglobal('setting/uidlogin')) {
        $isuid = 1;
    } elseif($loginfield == 'email') {
        $isuid = 2;
    } elseif($loginfield == 'auto') {
        $isuid = 3;
    } elseif($loginfield == 'secmobile' && getglobal('setting/secmobilelogin')) {
        $isuid = 4;
    } else {
        $isuid = 0;
    }

    // 加载UCenter通信函数,如未定义则先加载
    if(!function_exists('uc_user_login')) {
        loaducenter();
    }

    // 处理自动登录逻辑
    if($isuid == 3) {
        // 根据用户名尝试登录,支持UID、邮箱和安全手机号
        if(!strcmp(dintval($username), $username) && getglobal('setting/uidlogin')) {
            $return['ucresult'] = uc_user_login($username, $password, 1, 1, $questionid, $answer, $ip, 1);
        } elseif(isemail($username)) {
            $return['ucresult'] = uc_user_login($username, $password, 2, 1, $questionid, $answer, $ip, 1);
        } elseif(preg_match('/^(\d{1,12}|\d{1,3}-\d{1,12})$/', $username) && getglobal('setting/secmobilelogin')) {
            $username = strpos($username, '-') === false ? (getglobal('setting/smsdefaultcc') . '-' . $username) : $username;
            $return['ucresult'] = uc_user_login($username, $password, 4, 1, $questionid, $answer, $ip, 1);
        }
        // 如果登录失败且不是因为账户不存在,则尝试使用用户名密码登录
        if($return['ucresult'][0] <= 0 && $return['ucresult'][0] != -3) {
            $return['ucresult'] = uc_user_login(addslashes($username), $password, 0, 1, $questionid, $answer, $ip);
        }
    } else {
        // 处理非自动登录类型
        if($isuid == 4) {
            $username = strpos($username, '-') === false ? (getglobal('setting/smsdefaultcc') . '-' . $username) : $username;
        }
        $return['ucresult'] = uc_user_login(addslashes($username), $password, $isuid, 1, $questionid, $answer, $ip);
    }

    // 解析UC登录结果
    $tmp = array();
    $duplicate = '';
    list($tmp['uid'], $tmp['username'], $tmp['password'], $tmp['email'], $duplicate) = $return['ucresult'];
    $return['ucresult'] = $tmp;

    // 检查登录结果,登录失败或用户数据重复则返回
    if($duplicate && $return['ucresult']['uid'] > 0 || $return['ucresult']['uid'] <= 0) {
        $return['status'] = 0;
        return $return;
    }

    // 获取用户详细信息
    $member = getuserbyuid($return['ucresult']['uid'], 1);
    if(!$member || empty($member['uid'])) {
        $return['status'] = -1;
        return $return;
    }
    $return['member'] = $member;

    // 登录成功
    $return['status'] = 1;
    if($member['_inarchive']) {
        // 如果用户是归档用户,则将其移回主表
        C::t('common_member_archive')->move_to_master($member['uid']);
    }
    // 更新用户邮箱,解决可能的邮箱变更问题
    if($member['email'] != $return['ucresult']['email']) {
        C::t('common_member')->update($return['ucresult']['uid'], array('email' => $return['ucresult']['email']));
    }

    return $return;
}
/**
 * 设置登录状态
 *
 * 用于在用户成功登录后,设置用户的登录状态,包括但不限于用户ID、用户名、管理员等级、用户组等信息,
 * 同时更新会话信息、设置登录相关的cookie,以及更新统计信息。
 *
 * @param array $member 包含用户登录信息的数组,至少应包含uid、username、adminid、groupid等字段
 * @param int $cookietime 登录cookie的有效时间,单位为秒
 */
function setloginstatus($member, $cookietime) {
    global $_G;
    $_G['uid'] = intval($member['uid']);
    $_G['username'] = $member['username'];
    $_G['adminid'] = $member['adminid'];
    $_G['groupid'] = $member['groupid'];
    $_G['formhash'] = formhash();
    $_G['session']['invisible'] = getuserprofile('invisible');
    $_G['member'] = $member;
    loadcache('usergroup_'.$_G['groupid']);
    C::app()->session->isnew = true;
    C::app()->session->updatesession();

    // 设置登录认证cookie
    dsetcookie('auth', authcode("{$member['password']}\t{$member['uid']}", 'ENCODE'), $cookietime, 1, true);
    dsetcookie('loginuser');
    dsetcookie('activationauth');
    dsetcookie('pmnum');

    // 更新登录统计信息
    include_once libfile('function/stat');
    updatestat('login', 1);
    if(defined('IN_MOBILE')) {
        updatestat('mobilelogin', 1);
    }
    if($_G['setting']['connect']['allow'] && $_G['member']['conisbind']) {
        updatestat('connectlogin', 1);
    }
    // 更新用户积分
    $rule = updatecreditbyaction('daylogin', $_G['uid']);
    if(!$rule['updatecredit']) {
        checkusergroup($_G['uid']);
    }
}

/**
 * 登录检查
 *
 * 用于检查用户登录名是否可用,如果是,则返回可以登录的标志;如果不可用,根据失败次数返回相应的延迟时间。
 *
 * @param string $username 用户输入的用户名
 * @return int 返回值为0表示可以登录,大于0表示需要等待的时间(秒)
 */
function logincheck($username) {
    global $_G;

    $return = 0;
    $username = trim($username);
    loaducenter();
    if(function_exists('uc_user_logincheck')) {
        // 如果存在与UCenter的登录检查函数,则调用UCenter的登录检查
        $return = uc_user_logincheck(addslashes($username), $_G['clientip']);
    } else {
        // 不存在时,进行本地登录检查
        $login = C::t('common_failedlogin')->fetch_ip($_G['clientip']);
        $return = (!$login || (TIMESTAMP - $login['lastupdate'] > 900)) ? 5 : max(0, 5 - $login['count']);

        if(!$login) {
            C::t('common_failedlogin')->insert(array(
                'ip' => $_G['clientip'],
                'count' => 0,
                'lastupdate' => TIMESTAMP
            ), false, true);
        } elseif(TIMESTAMP - $login['lastupdate'] > 900) {
            C::t('common_failedlogin')->insert(array(
                'ip' => $_G['clientip'],
                'count' => 0,
                'lastupdate' => TIMESTAMP
            ), false, true);
            C::t('common_failedlogin')->delete_old(901);
        }
    }
    return $return;
}

/**
 * 登录失败处理
 *
 * 当用户登录失败时,记录登录失败信息,防止恶意登录攻击。
 *
 * @param string $username 用户输入的用户名
 */
function loginfailed($username) {
    global $_G;

    loaducenter();
    if(function_exists('uc_user_logincheck')) {
        // 如果存在与UCenter的登录检查函数,则不进行处理
        return;
    }
    // 记录登录失败信息
    C::t('common_failedlogin')->update_failed($_G['clientip']);
}
/**
 * 检查IP尝试次数是否超过限制。
 *
 * @param $numiptry int 尝试次数限制。
 * @param $timeiptry int 时间限制(秒)。超过此时间限制,尝试次数将被重置。
 * @return bool 如果尝试次数超过限制,返回true;否则,返回false。
 */
function failedipcheck($numiptry, $timeiptry) {
        global $_G;
        if(!$numiptry) {
                return false;
        }
        // 检查当前IP在指定时间内尝试的次数是否已达到或超过限制
        return $numiptry <= C::t('common_failedip')->get_ip_count($_G['clientip'], TIMESTAMP - $timeiptry);
}

/**
 * 记录一个失败的IP尝试。
 */
function failedip() {
        global $_G;
        // 插入当前IP到失败尝试表中
        C::t('common_failedip')->insert_ip($_G['clientip']);
}

/**
 * 获取邀请码信息。
 *
 * @return array 包含邀请码相关用户信息的数组,如果不存在有效邀请码则返回空数组。
 */
function getinvite() {
        global $_G;

        // 如果注册功能关闭,则直接返回空数组
        if($_G['setting']['regstatus'] == 1) return array();
        $result = array();
        $cookies = empty($_G['cookie']['invite_auth']) ? array() : explode(',', $_G['cookie']['invite_auth']);
        $cookiecount = count($cookies);

        // 处理通过URL传入的邀请码
        $_GET['invitecode'] = trim($_GET['invitecode']);
        if($cookiecount == 2 || $_GET['invitecode']) {
                $id = intval($cookies[0]);
                $code = trim($cookies[1]);
                if($_GET['invitecode']) {
                        // 通过邀请码查询邀请信息
                        $invite = C::t('common_invite')->fetch_by_code($_GET['invitecode']);
                        $code = trim($_GET['invitecode']);
                } else {
                        // 通过ID查询邀请信息
                        $invite = C::t('common_invite')->fetch($id);
                }
                // 验证邀请信息的有效性
                if(!empty($invite)) {
                        if($invite['code'] == $code && empty($invite['fuid']) && (empty($invite['endtime']) || $_G['timestamp'] < $invite['endtime'])) {
                                $result['uid'] = $invite['uid'];
                                $result['id'] = $invite['id'];
                        }
                }
        } elseif($cookiecount == 3) { // 处理通过cookie传入的邀请码
                $uid = intval($cookies[0]);
                $code = trim($cookies[1]);

                $invite_code = helper_invite::generate_key($uid);
                if($code === $invite_code) {
                        $member = getuserbyuid($uid);
                        if($member) {
                                $usergroup = C::t('common_usergroup')->fetch($member['groupid']);
                                // 如果用户组不允许邀请或邀请需要付费,则返回空数组
                                if(!$usergroup['allowinvite'] || $usergroup['inviteprice'] > 0) return array();
                        } else {
                                return array();
                        }
                        $result['uid'] = $uid;
                }
        }

        // 如果获取到有效的邀请信息,填充邀请者用户名
        if($result['uid']) {
                $member = getuserbyuid($result['uid']);
                $result['username'] = $member['username'];
        } else {
                // 如果没有有效的邀请信息,清除邀请cookie
                dsetcookie('invite_auth', '');
        }

        return $result;
}
/**
 * 替换字符串中的站点变量
 *
 * @param string $string 需要替换的字符串
 * @param array $replaces 用户自定义的替换数组,默认为空数组
 * @return string 替换后的字符串
 */
function replacesitevar($string, $replaces = array()) {
        global $_G;
        // 定义站点变量
        $sitevars = array(
                '{sitename}' => $_G['setting']['sitename'],
                '{bbname}' => $_G['setting']['bbname'],
                '{time}' => dgmdate(TIMESTAMP, 'Y-n-j H:i'),
                '{adminemail}' => $_G['setting']['adminemail'],
                '{username}' => $_G['member']['username'],
                '{myname}' => $_G['member']['username']
        );
        // 合并用户自定义替换数组和站点变量
        $replaces = array_merge($sitevars, $replaces);
        // 替换字符串并返回
        return str_replace(array_keys($replaces), array_values($replaces), $string);
}

/**
 * 清除用户cookie
 */
function clearcookies() {
        global $_G;
        // 遍历cookie,除去特定的键值,其余全部清除
        foreach($_G['cookie'] as $k => $v) {
                if($k != 'widthauto') {
                        dsetcookie($k);
                }
        }
        // 重置用户登录状态
        $_G['uid'] = $_G['adminid'] = 0;
        $_G['username'] = $_G['member']['password'] = '';
}

/**
 * 处理犯罪记录相关操作
 *
 * @param string $fun 要执行的操作
 * @return mixed 操作结果,失败返回false
 */
function crime($fun) {
        if(!$fun) {
                return false;
        }
        include_once libfile('class/member');
        $crimerecord = & crime_action_ctl::instance();
        $arg_list = func_get_args();
        // 根据传入的函数名执行不同的操作
        if($fun == 'recordaction') {
                list(, $uid, $action, $reason) = $arg_list;
                return $crimerecord->$fun($uid, $action, $reason);
        } elseif($fun == 'getactionlist') {
                list(, $uid) = $arg_list;
                return $crimerecord->$fun($uid);
        } elseif($fun == 'getcount') {
                list(, $uid, $action) = $arg_list;
                return $crimerecord->$fun($uid, $action);
        } elseif($fun == 'search') {
                list(, $action, $username, $operator, $starttime, $endtime, $reason, $start, $limit) = $arg_list;
                return $crimerecord->$fun($action, $username, $operator, $starttime, $endtime, $reason, $start, $limit);
        } elseif($fun == 'actions') {
                return crime_action_ctl::$actions;
        }
        return false;
}

/**
 * 检查并更新关注的动态
 */
function checkfollowfeed() {
        global $_G;

        if($_G['uid']) {
                $lastcheckfeed = 0;
                if(!empty($_G['cookie']['lastcheckfeed'])) {
                        $time = explode('|', $_G['cookie']['lastcheckfeed']);
                        if($time[0] == $_G['uid']) {
                                $lastcheckfeed = $time[1];
                        }
                }
                if(!$lastcheckfeed) {
                        $lastcheckfeed = getuserprofile('lastactivity');
                }
                // 设置最后一次检查动态的时间
                dsetcookie('lastcheckfeed', $_G['uid'].'|'.TIMESTAMP, 31536000);
                // 获取关注的用户
                $followuser = C::t('home_follow')->fetch_all_following_by_uid($_G['uid']);
                $uids = array_keys($followuser);
                if(!empty($uids)) {
                        // 检查是否有新的动态
                        $count = C::t('home_follow_feed')->count_by_uid_dateline($uids, $lastcheckfeed);
                        if($count) {
                                // 有新动态,添加通知
                                notification_add($_G['uid'], 'follow', 'member_follow', array('count' => $count, 'from_id'=>$_G['uid'], 'from_idtype' => 'follow'), 1);
                        }
                }
        }
        // 更新检查动态的cookie
        dsetcookie('checkfollow', 1, 30);
}

/**
 * 验证邮箱格式及合法性
 *
 * @param string $email 需要验证的邮箱地址
 */
function checkemail($email) {
        global $_G;

        $email = strtolower(trim($email));
        if(strlen($email) > 255) {
                // 邮箱地址过长
                showmessage('profile_email_illegal', '', array(), array('handle' => false));
        }
        if($_G['setting']['regmaildomain']) {
                // 检查邮箱域名是否合法
                $maildomainexp = '/('.str_replace("\r\n", '|', preg_quote(trim($_G['setting']['maildomainlist']), '/')).')$/i';
                if($_G['setting']['regmaildomain'] == 1 && !preg_match($maildomainexp, $email)) {
                        showmessage('profile_email_domain_illegal', '', array(), array('handle' => false));
                } elseif($_G['setting']['regmaildomain'] == 2 && preg_match($maildomainexp, $email)) {
                        showmessage('profile_email_domain_illegal', '', array(), array('handle' => false));
                }
        }

        // 调用ucenter接口验证邮箱
        loaducenter();
        $ucresult = uc_user_checkemail($email);

        // 处理ucenter返回的结果
        if($ucresult == -4) {
                showmessage('profile_email_illegal', '', array(), array('handle' => false));
        } elseif($ucresult == -5) {
                showmessage('profile_email_domain_illegal', '', array(), array('handle' => false));
        } elseif($ucresult == -6) {
                showmessage('profile_email_duplicate', '', array(), array('handle' => false));
        }
}

/**
 * 生成获取密码的签名链接
 *
 * @param int $uid 用户ID
 * @param string $idstring 用户注册ID字符串
 * @return string 签名链接
 */
function make_getpws_sign($uid, $idstring) {
        global $_G;
        $link = "member.php?mod=getpasswd&uid={$uid}&id={$idstring}";
        return dsign($link);
}

?>

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|新秀网络验证系统API ( 豫ICP备2021033257号-1 )

GMT+8, 2024-4-24 01:15 , Processed in 0.210249 second(s), 63 queries , Redis On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表