码迷,mamicode.com
首页 > Web开发 > 详细

Discuz X3核心文件解析

时间:2016-10-22 07:55:44      阅读:299      评论:0      收藏:0      [点我收藏+]

标签:tsp   网页   ring   username   request   contents   方法   存在   strlen   

<?php

 

/**

 *      [Discuz!] (C)2001-2099 Comsenz Inc.

 *      This is NOT a freeware, use is subject to license terms

 *

 *      $Id: discuz_application.php 34170 2013-10-28 02:58:29Z nemohou $

 */

 

if(!defined(‘IN_DISCUZ‘)) {

    exit(‘Access Denied‘);

}

 

class discuz_application extends discuz_base{

 

 

    var $mem = null;

 

    var $session = null;

 

    var $config = array();

 

    var $var = array();

 

    var $cachelist = array();

 

    var $init_db = true;

    var $init_setting = true;

    var $init_user = true;

    var $init_session = true;

    var $init_cron = true;

    var $init_misc = true;

    var $init_mobile = true;

 

    var $initated = false;//初始化工作未完成标志

 

    var $superglobal = array(//超全局变量

        ‘GLOBALS‘ => 1,

        ‘_GET‘ => 1,

        ‘_POST‘ => 1,

        ‘_REQUEST‘ => 1,

        ‘_COOKIE‘ => 1,

        ‘_SERVER‘ => 1,

        ‘_ENV‘ => 1,

        ‘_FILES‘ => 1,

    );

 

    static function &instance() {//实例化

        static $object;

        if(empty($object)) {

            $object = new self();

        }

        return $object;

    }

 

    public function __construct() {

        $this->_init_env();//初始化环境变量

        $this->_init_config();//初始化配置变量

        $this->_init_input();//初始化输入

        $this->_init_output(); //初始化输出

    }

 

    public function init() {

        if(!$this->initated) {

            $this->_init_db();//初始化数据库

            $this->_init_setting(); //系统设置初始化

            $this->_init_user();//用户信息初始化

            $this->_init_session();//session操作初始化

            $this->_init_mobile(); //手机功能初始化

            $this->_init_cron(); //计划任务初始化

            $this->_init_misc();//其他功能初始化

        }

        $this->initated = true;//设置完成标志

    }

   

    //环境变量初始化方法

    private function _init_env() {

 

        error_reporting(E_ERROR);//定义错误报告等级

        if(PHP_VERSION < ‘5.3.0‘) {

            set_magic_quotes_runtime(0);//设置set_magic_quotes_runtime

        }

 

        define(‘MAGIC_QUOTES_GPC‘, function_exists(‘get_magic_quotes_gpc‘) && get_magic_quotes_gpc()); //定义MAGIC_QUOTES_GPC

        define(‘ICONV_ENABLE‘, function_exists(‘iconv‘));//定义转码函数常量,如果 iconv函数支持,则为TRUE

        define(‘MB_ENABLE‘, function_exists(‘mb_convert_encoding‘));//转码函数是否支持

        define(‘EXT_OBGZIP‘, function_exists(‘ob_gzhandler‘));//缓存输出句柄函数

 

        define(‘TIMESTAMP‘, time());//定义当前时间戳常量

        $this->timezone_set();

       

        /*如果系统核心函数库文件未include,则include,

        * 如果核心函数库文件缺失,则退出,

        *因为function_core.php是系统本身的函数库,必须加载

        */

        if(!defined(‘DISCUZ_CORE_FUNCTION‘) && !@include(DISCUZ_ROOT.‘./source/function/function_core.php‘)) {

            exit(‘function_core.php is missing‘);

        }

        /*

         * 以下6行代码的作用是设置内存使用限制,

         * 如果小于32M,则增加为128M,

         * 因为memory_limit小于32M,可能会不够用,

         * 毕竟X系统比较大,可能内存会使用的多点,

         * 如果不支持ini_set函数,就得去php.ini中修改了。

         */

       

        if(function_exists(‘ini_get‘)) {

            $memorylimit = @ini_get(‘memory_limit‘);

           if($memorylimit && return_bytes($memorylimit) < 33554432 && function_exists(‘ini_set‘)) {

                ini_set(‘memory_limit‘, ‘128m‘);

            }

        }

 

        define(‘IS_ROBOT‘, checkrobot());//检测机器人

       

        foreach ($GLOBALS as $key => $value) {//注销所有的超级变量。

            if (!isset($this->superglobal[$key])) {

                $GLOBALS[$key] = null; unset($GLOBALS[$key]);

            }

        }

 

        global $_G;//$_G大数组是Discuz中自定义的超级变量

        $_G = array(

            ‘uid‘ => 0,//uid

            ‘username‘ => ‘‘,//用户名

            ‘adminid‘ => 0,//adminid标识

            ‘groupid‘ => 1, //用户组ID

            ‘sid‘ => ‘‘, // sessionID

            ‘formhash‘ => ‘‘,//表单验证认证

            ‘connectguest‘ => 0,

            ‘timestamp‘ => TIMESTAMP,//时间戳

            ‘starttime‘ => microtime(true),//开始时间

            ‘clientip‘ => $this->_get_client_ip(), //客户端IP

            ‘remoteport‘ => $_SERVER[‘REMOTE_PORT‘],//远程端口号

            ‘referer‘ => ‘‘,//referer地址

            ‘charset‘ => ‘‘, //字符串编码

            ‘gzipcompress‘ => ‘‘,//gzip

            ‘authkey‘ => ‘‘, //authkey  认证码

            ‘timenow‘ => array(),//当前时间

            ‘widthauto‘ => 0,

            ‘disabledwidthauto‘ => 0,

 

            ‘PHP_SELF‘ => ‘‘,//PHP_SELF

            ‘siteurl‘ => ‘‘,//网站地址

            ‘siteroot‘ => ‘‘, //网站根目录

            ‘siteport‘ => ‘‘,//网站端口号

 

            ‘pluginrunlist‘ => !defined(‘PLUGINRUNLIST‘) ? array() : explode(‘,‘, PLUGINRUNLIST),

 

            ‘config‘ => array(),//配置变量数组

            ‘setting‘ => array(),//设置变量数组

            ‘member‘ => array(),//用户信息数组

            ‘group‘ => array(),//用户组数组

            ‘cookie‘ => array(),//cookie数组

            ‘style‘ => array(),//风格数组

            ‘cache‘ => array(),//缓存列表数组

            ‘session‘ => array(), //session变量数组

            ‘lang‘ => array(),//语言包数组

            ‘my_app‘ => array(),//我的应用数组

            ‘my_userapp‘ => array(),//用户应用数组

 

            ‘fid‘ => 0,

            ‘tid‘ => 0,

            ‘forum‘ => array(),//论坛板块数组

            ‘thread‘ => array(),//论坛相关帖子数组

            ‘rssauth‘ => ‘‘,//RSS订阅认证

 

            ‘home‘ => array(), //home功能相关数组

            ‘space‘ => array(),//space功能相关数组

 

            ‘block‘ => array(),//块信息数组

            ‘article‘ => array(),

 

            ‘action‘ => array(

                ‘action‘ => APPTYPEID,

                ‘fid‘ => 0,

                ‘tid‘ => 0,

            ),

 

            ‘mobile‘ => ‘‘,//手机信息

            ‘notice_structure‘ => array(

                ‘mypost‘ => array(‘post‘,‘pcomment‘,‘activity‘,‘reward‘,‘goods‘,‘at‘),

                ‘interactive‘ => array(‘poke‘,‘friend‘,‘wall‘,‘comment‘,‘click‘,‘sharenotice‘),

                ‘system‘ => array(‘system‘,‘myapp‘,‘credit‘,‘group‘,‘verify‘,‘magic‘,‘task‘,‘show‘,‘group‘,‘pusearticle‘,‘mod_member‘,‘blog‘,‘article‘),

                ‘manage‘ => array(‘mod_member‘,‘report‘,‘pmreport‘),

                ‘app‘ => array(),

            ),

            ‘mobiletpl‘ => array(‘1‘ => ‘mobile‘, ‘2‘ => ‘touch‘, ‘3‘ => ‘wml‘,‘yes‘ => ‘mobile‘),

        );

        $_G[‘PHP_SELF‘] = dhtmlspecialchars($this->_get_script_url());//网站地址

        $_G[‘basescript‘] = CURSCRIPT;//当前脚本

        $_G[‘basefilename‘] = basename($_G[‘PHP_SELF‘]);//当前脚本名称

        $sitepath = substr($_G[‘PHP_SELF‘], 0, strrpos($_G[‘PHP_SELF‘], ‘/‘));//网站根地址

        if(defined(‘IN_API‘)) {

            $sitepath = preg_replace("/\/api\/?.*?$/i", ‘‘, $sitepath);

        } elseif(defined(‘IN_ARCHIVER‘)) {

            $sitepath = preg_replace("/\/archiver/i", ‘‘, $sitepath);

        }

        $_G[‘isHTTPS‘] = ($_SERVER[‘HTTPS‘] && strtolower($_SERVER[‘HTTPS‘]) != ‘off‘) ? true : false;

        $_G[‘siteurl‘] = dhtmlspecialchars(‘http‘.($_G[‘isHTTPS‘] ? ‘s‘ : ‘‘).‘://‘.$_SERVER[‘HTTP_HOST‘].$sitepath.‘/‘);

 

        $url = parse_url($_G[‘siteurl‘]);

        $_G[‘siteroot‘] = isset($url[‘path‘]) ? $url[‘path‘] : ‘‘;

        $_G[‘siteport‘] = empty($_SERVER[‘SERVER_PORT‘]) || $_SERVER[‘SERVER_PORT‘] == ‘80‘ || $_SERVER[‘SERVER_PORT‘] == ‘443‘ ? ‘‘ : ‘:‘.$_SERVER[‘SERVER_PORT‘];

 

        if(defined(‘SUB_DIR‘)) {//二级目录设置

            $_G[‘siteurl‘] = str_replace(SUB_DIR, ‘/‘, $_G[‘siteurl‘]);

            $_G[‘siteroot‘] = str_replace(SUB_DIR, ‘/‘, $_G[‘siteroot‘]);

        }

 

        $this->var = & $_G;

 

    }

 

    private function _get_script_url() {

        if(!isset($this->var[‘PHP_SELF‘])){

            $scriptName = basename($_SERVER[‘SCRIPT_FILENAME‘]);

            if(basename($_SERVER[‘SCRIPT_NAME‘]) === $scriptName) {

                $this->var[‘PHP_SELF‘] = $_SERVER[‘SCRIPT_NAME‘];

            } else if(basename($_SERVER[‘PHP_SELF‘]) === $scriptName) {

                $this->var[‘PHP_SELF‘] = $_SERVER[‘PHP_SELF‘];

            } else if(isset($_SERVER[‘ORIG_SCRIPT_NAME‘]) && basename($_SERVER[‘ORIG_SCRIPT_NAME‘]) === $scriptName) {

                $this->var[‘PHP_SELF‘] = $_SERVER[‘ORIG_SCRIPT_NAME‘];

            } else if(($pos = strpos($_SERVER[‘PHP_SELF‘],‘/‘.$scriptName)) !== false) {

                $this->var[‘PHP_SELF‘] = substr($_SERVER[‘SCRIPT_NAME‘],0,$pos).‘/‘.$scriptName;

            } else if(isset($_SERVER[‘DOCUMENT_ROOT‘]) && strpos($_SERVER[‘SCRIPT_FILENAME‘],$_SERVER[‘DOCUMENT_ROOT‘]) === 0) {

                $this->var[‘PHP_SELF‘] = str_replace(‘\\‘,‘/‘,str_replace($_SERVER[‘DOCUMENT_ROOT‘],‘‘,$_SERVER[‘SCRIPT_FILENAME‘]));

                $this->var[‘PHP_SELF‘][0] != ‘/‘ && $this->var[‘PHP_SELF‘] = ‘/‘.$this->var[‘PHP_SELF‘];

            } else {

                system_error(‘request_tainting‘);

            }

        }

        return $this->var[‘PHP_SELF‘];

    }

 

    private function _init_input() { //输入初始化方法

        /*

         * 以下代码未GPC安全机制,进行转义

         */

        if (isset($_GET[‘GLOBALS‘]) ||isset($_POST[‘GLOBALS‘]) ||  isset($_COOKIE[‘GLOBALS‘]) || isset($_FILES[‘GLOBALS‘])) {

            system_error(‘request_tainting‘);

        }

        /*

         * 以下代码意思是,如果cookie的键值等于定义的键值,那么截取cookiepre

         */

        if(MAGIC_QUOTES_GPC) {

            $_GET = dstripslashes($_GET);

            $_POST = dstripslashes($_POST);

            $_COOKIE = dstripslashes($_COOKIE);

        }

 

        $prelength = strlen($this->config[‘cookie‘][‘cookiepre‘]);

        foreach($_COOKIE as $key => $val) {

            if(substr($key, 0, $prelength) == $this->config[‘cookie‘][‘cookiepre‘]) {

                $this->var[‘cookie‘][substr($key, $prelength)] = $val;

            }

        }

 

        //合并$_POST和$_GET

        if($_SERVER[‘REQUEST_METHOD‘] == ‘POST‘ && !empty($_POST)) {

            $_GET = array_merge($_GET, $_POST);

        }

 

        if(isset($_GET[‘page‘])) {

            $_GET[‘page‘] = rawurlencode($_GET[‘page‘]);

        }

 

        if(!(!empty($_GET[‘handlekey‘]) && preg_match(‘/^\w+$/‘, $_GET[‘handlekey‘]))) {

            unset($_GET[‘handlekey‘]);

        }

        //然后把$_POST和$_GET的值都赋予gp变量中,方便使用

        if(!empty($this->var[‘config‘][‘input‘][‘compatible‘])) {

            foreach($_GET as $k => $v) {

                $this->var[‘gp_‘.$k] = daddslashes($v);

            }

        }

        //获得$mod变量 ?mod=xxx,则$this->var[‘mod‘]为xxx

        $this->var[‘mod‘] = empty($_GET[‘mod‘]) ? ‘‘ : dhtmlspecialchars($_GET[‘mod‘]);

        //是否需要ajax方式

        $this->var[‘inajax‘] = empty($_GET[‘inajax‘]) ? 0 : (empty($this->var[‘config‘][‘output‘][‘ajaxvalidate‘]) ? 1 : ($_SERVER[‘REQUEST_METHOD‘] == ‘GET‘ && $_SERVER[‘HTTP_X_REQUESTED_WITH‘] == ‘XMLHttpRequest‘ || $_SERVER[‘REQUEST_METHOD‘] == ‘POST‘ ? 1 : 0));

        //页面获取,最小为1

        $this->var[‘page‘] = empty($_GET[‘page‘]) ? 1 : max(1, intval($_GET[‘page‘]));

        //sid获取

        $this->var[‘sid‘] = $this->var[‘cookie‘][‘sid‘] = isset($this->var[‘cookie‘][‘sid‘]) ? dhtmlspecialchars($this->var[‘cookie‘][‘sid‘]) : ‘‘;

 

        if(empty($this->var[‘cookie‘][‘saltkey‘])) {

            $this->var[‘cookie‘][‘saltkey‘] = random(8);

            dsetcookie(‘saltkey‘, $this->var[‘cookie‘][‘saltkey‘], 86400 * 30, 1, 1);

        }

        $this->var[‘authkey‘] = md5($this->var[‘config‘][‘security‘][‘authkey‘].$this->var[‘cookie‘][‘saltkey‘]);

 

    }

 

    private function _init_config() {//获得配置文件

 

        $_config = array();

       

        //加载全局配置文件

        @include DISCUZ_ROOT.‘./config/config_global.php‘;

        //以下代码为:如果config不存在,要么没安装,要么文件不存在,系统报错

        if(empty($_config)) {

            if(!file_exists(DISCUZ_ROOT.‘./data/install.lock‘)) {

                header(‘location: install‘);

                exit;

            } else {

                system_error(‘config_notfound‘);

            }

        }

        //设置安全验证的authkey

        if(empty($_config[‘security‘][‘authkey‘])) {

            $_config[‘security‘][‘authkey‘] = md5($_config[‘cookie‘][‘cookiepre‘].$_config[‘db‘][1][‘dbname‘]);

        }

        //以下代码为是否调试模式,

        if(empty($_config[‘debug‘]) || !file_exists(libfile(‘function/debug‘))) {

            define(‘DISCUZ_DEBUG‘, false);

            error_reporting(0);

        } elseif($_config[‘debug‘] === 1 || $_config[‘debug‘] === 2 || !empty($_REQUEST[‘debug‘]) && $_REQUEST[‘debug‘] === $_config[‘debug‘]) {

            define(‘DISCUZ_DEBUG‘, true);

            error_reporting(E_ERROR);

            if($_config[‘debug‘] === 2) {

                error_reporting(E_ALL);

            }

        } else {

            define(‘DISCUZ_DEBUG‘, false);

            error_reporting(0);

        }

        //定义静态文件常量,如:css,img等,如果$_config[‘output‘][‘staticurl‘]为空,

        //则是默认的static目录,就是默认目录

        define(‘STATICURL‘, !empty($_config[‘output‘][‘staticurl‘]) ? $_config[‘output‘][‘staticurl‘] : ‘static/‘);

        $this->var[‘staticurl‘] = STATICURL;

 

        //引用$_config变量,改变$this->config,则$_config改变,保持统一

        $this->config = & $_config;

        $this->var[‘config‘] = & $_config;

 

        //设置cookie域,一般是设置目录域。/不存在则加上/,安全性更高

        if(substr($_config[‘cookie‘][‘cookiepath‘], 0, 1) != ‘/‘) {

            $this->var[‘config‘][‘cookie‘][‘cookiepath‘] = ‘/‘.$this->var[‘config‘][‘cookie‘][‘cookiepath‘];

        }

        $this->var[‘config‘][‘cookie‘][‘cookiepre‘] = $this->var[‘config‘][‘cookie‘][‘cookiepre‘].substr(md5($this->var[‘config‘][‘cookie‘][‘cookiepath‘].‘|‘.$this->var[‘config‘][‘cookie‘][‘cookiedomain‘]), 0, 4).‘_‘;

 

 

    }

 

    private function _init_output() {//输出初始化方法

 

        //验证码设置,加载include/misc/misc_security.php文件,验证功能;

        if($this->config[‘security‘][‘attackevasive‘] && (!defined(‘CURSCRIPT‘) || !in_array($this->var[‘mod‘], array(‘seccode‘, ‘secqaa‘, ‘swfupload‘)) && !defined(‘DISABLEDEFENSE‘))) {

            require_once libfile(‘misc/security‘, ‘include‘);

        }

 

        //是否开启gzip,如果不支持gzip,则定义为false

        if(!empty($_SERVER[‘HTTP_ACCEPT_ENCODING‘]) && strpos($_SERVER[‘HTTP_ACCEPT_ENCODING‘], ‘gzip‘) === false) {

            $this->config[‘output‘][‘gzip‘] = false;

        }

 

        //把$allowgzip写入全局变量中

        $allowgzip = $this->config[‘output‘][‘gzip‘] && empty($this->var[‘inajax‘]) && $this->var[‘mod‘] != ‘attachment‘ && EXT_OBGZIP;

        setglobal(‘gzipcompress‘, $allowgzip);

 

        //定义输出缓存

        if(!ob_start($allowgzip ? ‘ob_gzhandler‘ : null)) {

            ob_start();

        }

 

        //把配置文件中的字符集赋予全局变量中

        setglobal(‘charset‘, $this->config[‘output‘][‘charset‘]);

        define(‘CHARSET‘, $this->config[‘output‘][‘charset‘]);

        if($this->config[‘output‘][‘forceheader‘]) {

            //设置网页编码,强制输出

            @header(‘Content-Type: text/html; charset=‘.CHARSET);

        }

 

    }

 

    public function reject_robot() { //拒绝机器人访问,设置为403错误

        if(IS_ROBOT) {

            exit(header("HTTP/1.1 403 Forbidden"));

        }

    }

 

    private function _xss_check() { //检测xss漏洞,UBB

 

        static $check = array(‘"‘, ‘>‘, ‘<‘, ‘\‘‘, ‘(‘, ‘)‘, ‘CONTENT-TRANSFER-ENCODING‘);

 

        if(isset($_GET[‘formhash‘]) && $_GET[‘formhash‘] !== formhash()) {

            system_error(‘request_tainting‘);

        }

 

        if($_SERVER[‘REQUEST_METHOD‘] == ‘GET‘ ) {

            $temp = $_SERVER[‘REQUEST_URI‘];

        } elseif(empty ($_GET[‘formhash‘])) {

            $temp = $_SERVER[‘REQUEST_URI‘].file_get_contents(‘php://input‘);

        } else {

            $temp = ‘‘;

        }

 

        if(!empty($temp)) {

            $temp = strtoupper(urldecode(urldecode($temp)));

            foreach ($check as $str) {

                if(strpos($temp, $str) !== false) {

                    system_error(‘request_tainting‘);

                }

            }

        }

 

        return true;

    }

 

    private function _get_client_ip() { //得到客户端IP

        $ip = $_SERVER[‘REMOTE_ADDR‘];

        if (isset($_SERVER[‘HTTP_CLIENT_IP‘]) && preg_match(‘/^([0-9]{1,3}\.){3}[0-9]{1,3}$/‘, $_SERVER[‘HTTP_CLIENT_IP‘])) {

            $ip = $_SERVER[‘HTTP_CLIENT_IP‘];

        } elseif(isset($_SERVER[‘HTTP_X_FORWARDED_FOR‘]) AND preg_match_all(‘#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s‘, $_SERVER[‘HTTP_X_FORWARDED_FOR‘], $matches)) {

            foreach ($matches[0] AS $xip) {

                if (!preg_match(‘#^(10|172\.16|192\.168)\.#‘, $xip)) {

                    $ip = $xip;

                    break;

                }

            }

        }

        return $ip;

    }

 

    private function _init_db() {//初始化数据库

        if($this->init_db) {

            $driver = function_exists(‘mysql_connect‘) ? ‘db_driver_mysql‘ : ‘db_driver_mysqli‘;

            if(getglobal(‘config/db/slave‘)) {//是否存在从数据连接,存在则初始化

                $driver = function_exists(‘mysql_connect‘) ? ‘db_driver_mysql_slave‘ : ‘db_driver_mysqli_slave‘;

            }

            DB::init($driver, $this->config[‘db‘]);

        }

    }

 

    private function _init_session() { //session初始化方法

 

        $sessionclose = !empty($this->var[‘setting‘][‘sessionclose‘]);

        $this->session = $sessionclose ? new discuz_session_close() : new discuz_session();

 

        if($this->init_session)  {

            $this->session->init($this->var[‘cookie‘][‘sid‘], $this->var[‘clientip‘], $this->var[‘uid‘]);

            $this->var[‘sid‘] = $this->session->sid; //设置sid

            $this->var[‘session‘] = $this->session->var;//设置session

 

            //如果sid不为cookie中的sid,则重写sid到cookie

            if(!empty($this->var[‘sid‘]) && $this->var[‘sid‘] != $this->var[‘cookie‘][‘sid‘]) {

                dsetcookie(‘sid‘, $this->var[‘sid‘], 86400);

            }

 

            if($this->session->isnew) {

                //如果发现IP在禁止范围里,则设置该客户端用户组为6,则:禁止IP用户组

                if(ipbanned($this->var[‘clientip‘])) {

                    $this->session->set(‘groupid‘, 6);

                }

            }

 

            if($this->session->get(‘groupid‘) == 6) {

                $this->var[‘member‘][‘groupid‘] = 6;

                if(!defined(‘IN_MOBILE_API‘)) {

                    sysmessage(‘user_banned‘);//提示IP禁止

                } else {

                    mobile_core::result(array(‘error‘ => ‘user_banned‘));

                }

            }

 

            //最近活动检测,600秒,如果用户在600秒里不活动,则设置最后访问时间点

            if($this->var[‘uid‘] && !$sessionclose && ($this->session->isnew || ($this->session->get(‘lastactivity‘) + 600) < TIMESTAMP)) {

                $this->session->set(‘lastactivity‘, TIMESTAMP);

                if($this->session->isnew) {

                    if($this->var[‘member‘][‘lastip‘] && $this->var[‘member‘][‘lastvisit‘]) {

                        dsetcookie(‘lip‘, $this->var[‘member‘][‘lastip‘].‘,‘.$this->var[‘member‘][‘lastvisit‘]);

                    }

                    C::t(‘common_member_status‘)->update($this->var[‘uid‘], array(‘lastip‘ => $this->var[‘clientip‘], ‘port‘ => $this->var[‘remoteport‘], ‘lastvisit‘ => TIMESTAMP));

                }

            }

 

        }

    }

 

    private function _init_user() {//用户初始化方法

        if($this->init_user) {

            //得到auth,username\tuid的加密信息

            if($auth = getglobal(‘auth‘, ‘cookie‘)) {

                //进行解密

                $auth = daddslashes(explode("\t", authcode($auth, ‘DECODE‘)));

            }

            //得到用户名和用户密码,如果auth为空,或者缺失uid和username中的一个,则为空

            list($discuz_pw, $discuz_uid) = empty($auth) || count($auth) < 2 ? array(‘‘, ‘‘) : $auth;

 

            //如果uid存在,则得到该用户信息

            if($discuz_uid) {

                $user = getuserbyuid($discuz_uid, 1);

            }

 

            //如果用户存在,且密码正确,则用户信息写进全局变量中

            if(!empty($user) && $user[‘password‘] == $discuz_pw) {

                if(isset($user[‘_inarchive‘])) {

                    C::t(‘common_member_archive‘)->move_to_master($discuz_uid);

                }

                $this->var[‘member‘] = $user;

            } else {

                $user = array();//user定义为空数组

                $this->_init_guest();//否则为游客,游客初始化方法

            }

 

            //用户组过期检测

            if($user && $user[‘groupexpiry‘] > 0 && $user[‘groupexpiry‘] < TIMESTAMP) {

                $memberfieldforum = C::t(‘common_member_field_forum‘)->fetch($discuz_uid);

                $groupterms = dunserialize($memberfieldforum[‘groupterms‘]);

                if(!empty($groupterms[‘main‘])) {

                    C::t("common_member")->update($user[‘uid‘], array(‘groupexpiry‘=> 0, ‘groupid‘ => $groupterms[‘main‘][‘groupid‘], ‘adminid‘ => $groupterms[‘main‘][‘adminid‘]));

                    $user[‘groupid‘] = $groupterms[‘main‘][‘groupid‘];

                    $user[‘adminid‘] = $groupterms[‘main‘][‘adminid‘];

                    unset($groupterms[‘main‘], $groupterms[‘ext‘][$this->var[‘member‘][‘groupid‘]]);

                    $this->var[‘member‘] = $user;

                    C::t(‘common_member_field_forum‘)->update($discuz_uid, array(‘groupterms‘ => serialize($groupterms)));

               } elseif((getgpc(‘mod‘) != ‘spacecp‘ || CURSCRIPT != ‘home‘) && CURSCRIPT != ‘member‘) {

                    dheader(‘location: home.php?mod=spacecp&ac=usergroup&do=expiry‘);

                }

            }

 

            if($user && $user[‘freeze‘] && (getgpc(‘mod‘) != ‘spacecp‘ && getgpc(‘mod‘) != ‘misc‘  || CURSCRIPT != ‘home‘) && CURSCRIPT != ‘member‘ && CURSCRIPT != ‘misc‘) {

                dheader(‘location: home.php?mod=spacecp&ac=profile&op=password‘);

            }

 

            //用户组数据缓存

            $this->cachelist[] = ‘usergroup_‘.$this->var[‘member‘][‘groupid‘];

            if($user && $user[‘adminid‘] > 0 && $user[‘groupid‘] != $user[‘adminid‘]) {

                $this->cachelist[] = ‘admingroup_‘.$this->var[‘member‘][‘adminid‘];//管理员用户组缓存

            }

 

        } else {

            $this->_init_guest(); //游客

        }

        setglobal(‘groupid‘, getglobal(‘groupid‘, ‘member‘));

        !empty($this->cachelist) && loadcache($this->cachelist);

 

        if($this->var[‘member‘] && $this->var[‘group‘][‘radminid‘] == 0 && $this->var[‘member‘][‘adminid‘] > 0 && $this->var[‘member‘][‘groupid‘] != $this->var[‘member‘][‘adminid‘] && !empty($this->var[‘cache‘][‘admingroup_‘.$this->var[‘member‘][‘adminid‘]])) {

            $this->var[‘group‘] = array_merge($this->var[‘group‘], $this->var[‘cache‘][‘admingroup_‘.$this->var[‘member‘][‘adminid‘]]);

        }

 

        if($this->var[‘group‘][‘allowmakehtml‘] && isset($_GET[‘_makehtml‘])) {

            $this->var[‘makehtml‘] = 1;

            $this->_init_guest();

            loadcache(array(‘usergroup_7‘));

            $this->var[‘group‘] = $this->var[‘cache‘][‘usergroup_7‘];

            unset($this->var[‘inajax‘]);

        }

 

        if(empty($this->var[‘cookie‘][‘lastvisit‘])) {

            $this->var[‘member‘][‘lastvisit‘] = TIMESTAMP - 3600;

            dsetcookie(‘lastvisit‘, TIMESTAMP - 3600, 86400 * 30);//cookie中如果为记录最后访问时间,则写入

        } else {

            $this->var[‘member‘][‘lastvisit‘] = $this->var[‘cookie‘][‘lastvisit‘];//否则,写入全局变量

        }

        //以下四行是把用户的uid,用户名,管理组id,用户组写入全局变量中

        setglobal(‘uid‘, getglobal(‘uid‘, ‘member‘));

        setglobal(‘username‘, getglobal(‘username‘, ‘member‘));

        setglobal(‘adminid‘, getglobal(‘adminid‘, ‘member‘));

        setglobal(‘groupid‘, getglobal(‘groupid‘, ‘member‘));

        if($this->var[‘member‘][‘newprompt‘]) {

            $this->var[‘member‘][‘newprompt_num‘] = C::t(‘common_member_newprompt‘)->fetch($this->var[‘member‘][‘uid‘]);

            $this->var[‘member‘][‘newprompt_num‘] = unserialize($this->var[‘member‘][‘newprompt_num‘][‘data‘]);

            $this->var[‘member‘][‘category_num‘] = helper_notification::get_categorynum($this->var[‘member‘][‘newprompt_num‘]);

        }

 

    }

 

    private function _init_guest() {//游客初始化方法

        $username = ‘‘;

        $groupid = 7;

        if(!empty($this->var[‘cookie‘][‘con_auth_hash‘]) && ($openid = authcode($this->var[‘cookie‘][‘con_auth_hash‘]))) {

            $this->var[‘connectguest‘] = 1;

            $username = ‘QQ_‘.substr($openid, -6);

            $this->var[‘setting‘][‘cacheindexlife‘] = 0;

            $this->var[‘setting‘][‘cachethreadlife‘] = 0;

            $groupid = $this->var[‘setting‘][‘connect‘][‘guest_groupid‘] ? $this->var[‘setting‘][‘connect‘][‘guest_groupid‘] : $this->var[‘setting‘][‘newusergroupid‘];

        }

        setglobal(‘member‘, array( ‘uid‘ => 0, ‘username‘ => $username, ‘adminid‘ => 0, ‘groupid‘ => $groupid, ‘credits‘ => 0, ‘timeoffset‘ => 9999));

    }

 

    private function _init_cron() { //计划任务初始化

        $ext = empty($this->config[‘remote‘][‘on‘]) || empty($this->config[‘remote‘][‘cron‘]) || APPTYPEID == 200;

        if($this->init_cron && $this->init_setting && $ext) {

            if($this->var[‘cache‘][‘cronnextrun‘] <= TIMESTAMP) {

                discuz_cron::run();//运行

            }

        }

    }

 

    private function _init_misc() {

 

        if($this->config[‘security‘][‘urlxssdefend‘] && !defined(‘DISABLEXSSCHECK‘)) {

            $this->_xss_check();

        }

 

        if(!$this->init_misc) {

            return false;

        }

        lang(‘core‘);//加载core语言包

 

        //设置用户时区timeoffset

        if($this->init_setting && $this->init_user) {

            if(!isset($this->var[‘member‘][‘timeoffset‘]) || $this->var[‘member‘][‘timeoffset‘] == 9999 || $this->var[‘member‘][‘timeoffset‘] === ‘‘) {

                $this->var[‘member‘][‘timeoffset‘] = $this->var[‘setting‘][‘timeoffset‘];

            }

        }

 

        $timeoffset = $this->init_setting ? $this->var[‘member‘][‘timeoffset‘] : $this->var[‘setting‘][‘timeoffset‘];

        $this->var[‘timenow‘] = array(

            ‘time‘ => dgmdate(TIMESTAMP),

            ‘offset‘ => $timeoffset >= 0 ? ($timeoffset == 0 ? ‘‘ : ‘+‘.$timeoffset) : $timeoffset

        );

        $this->timezone_set($timeoffset);

 

        $this->var[‘formhash‘] = formhash();//得到FORMHASH

        define(‘FORMHASH‘, $this->var[‘formhash‘]);//定义为常量

 

        if($this->init_user) {

            $allowvisitflag = in_array(CURSCRIPT, array(‘member‘)) || defined(‘ALLOWGUEST‘) && ALLOWGUEST;

            if($this->var[‘group‘] && isset($this->var[‘group‘][‘allowvisit‘]) && !$this->var[‘group‘][‘allowvisit‘]) {

                if($this->var[‘uid‘] && !$allowvisitflag) {

                    if(!defined(‘IN_MOBILE_API‘)) {

                        showmessage(‘user_banned‘);//检测是否为禁止访问

                    } else {

                        mobile_core::result(array(‘error‘ => ‘user_banned‘));

                    }

                } elseif((!defined(‘ALLOWGUEST‘) || !ALLOWGUEST) && !in_array(CURSCRIPT, array(‘member‘, ‘api‘)) && !$this->var[‘inajax‘]) {

                    if(!defined(‘IN_MOBILE_API‘)) {

                        dheader(‘location: member.php?mod=logging&action=login&referer=‘.rawurlencode($this->var[‘siteurl‘].$this->var[‘basefilename‘].($_SERVER[‘QUERY_STRING‘] ? ‘?‘.$_SERVER[‘QUERY_STRING‘] : ‘‘)));

                    } else {

                        mobile_core::result(array(‘error‘ => ‘to_login‘));

                    }

                }

            }

            //如果用户状态为-1,则提示禁止访问

            if(isset($this->var[‘member‘][‘status‘]) && $this->var[‘member‘][‘status‘] == -1 && !$allowvisitflag) {

                if(!defined(‘IN_MOBILE_API‘)) {

                    showmessage(‘user_banned‘);

                } else {

                    mobile_core::result(array(‘error‘ => ‘user_banned‘));

                }

            }

        }

 

        //ip权限检测

        if($this->var[‘setting‘][‘ipaccess‘] && !ipaccess($this->var[‘clientip‘], $this->var[‘setting‘][‘ipaccess‘])) {

            if(!defined(‘IN_MOBILE_API‘)) {

                showmessage(‘user_banned‘);

            } else {

                mobile_core::result(array(‘error‘ => ‘user_banned‘));

            }

        }

   

        //论坛如果为关闭,只有管理员可以访问,其他则提示关闭原因

        if($this->var[‘setting‘][‘bbclosed‘]) {

            if($this->var[‘uid‘] && ($this->var[‘group‘][‘allowvisit‘] == 2 || $this->var[‘groupid‘] == 1)) {

            } elseif(in_array(CURSCRIPT, array(‘admin‘, ‘member‘, ‘api‘)) || defined(‘ALLOWGUEST‘) && ALLOWGUEST) {

            } else {

                $closedreason = C::t(‘common_setting‘)->fetch(‘closedreason‘);

                $closedreason = str_replace(‘:‘, ‘&#58;‘, $closedreason);

                if(!defined(‘IN_MOBILE_API‘)) {

                    showmessage($closedreason ? $closedreason : ‘board_closed‘, NULL, array(‘adminemail‘ => $this->var[‘setting‘][‘adminemail‘]), array(‘login‘ => 1));

                } else {

                    mobile_core::result(array(‘error‘ => $closedreason ? $closedreason : ‘board_closed‘));

                }

            }

        }

 

        //私密板块访问设置

        if(CURSCRIPT != ‘admin‘ && !(in_array($this->var[‘mod‘], array(‘logging‘, ‘seccode‘)))) {

            periodscheck(‘visitbanperiods‘);

        }

 

        //wap访问设置

        if(defined(‘IN_MOBILE‘)) {

            $this->var[‘tpp‘] = $this->var[‘setting‘][‘mobile‘][‘mobiletopicperpage‘] ? intval($this->var[‘setting‘][‘mobile‘][‘mobiletopicperpage‘]) : 20;

            $this->var[‘ppp‘] = $this->var[‘setting‘][‘mobile‘][‘mobilepostperpage‘] ? intval($this->var[‘setting‘][‘mobile‘][‘mobilepostperpage‘]) : 5;

        } else {

            $this->var[‘tpp‘] = $this->var[‘setting‘][‘topicperpage‘] ? intval($this->var[‘setting‘][‘topicperpage‘]) : 20;

            $this->var[‘ppp‘] = $this->var[‘setting‘][‘postperpage‘] ? intval($this->var[‘setting‘][‘postperpage‘]) : 10;

        }

       

        //以下五行作用是header cache状态设置

        if($this->var[‘setting‘][‘nocacheheaders‘]) {

            @header("Expires: -1");

            @header("Cache-Control: no-store, private, post-check=0, pre-check=0, max-age=0", FALSE);

            @header("Pragma: no-cache");

        }

   

        if($this->session->isnew && $this->var[‘uid‘]) {

            updatecreditbyaction(‘daylogin‘, $this->var[‘uid‘]);//每日登陆增加积分设置

 

            include_once libfile(‘function/stat‘);

            updatestat(‘login‘, 1);

            if(defined(‘IN_MOBILE‘)) {

                updatestat(‘mobilelogin‘, 1);

            }

            if($this->var[‘setting‘][‘connect‘][‘allow‘] && $this->var[‘member‘][‘conisbind‘]) {

                updatestat(‘connectlogin‘, 1);

            }

        }

        if(isset($this->var[‘member‘][‘conisbind‘]) && $this->var[‘member‘][‘conisbind‘] && $this->var[‘setting‘] && $this->var[‘setting‘][‘connect‘][‘newbiespan‘] !== ‘‘) {

            $this->var[‘setting‘][‘newbiespan‘] = $this->var[‘setting‘][‘connect‘][‘newbiespan‘];

        }

 

        $lastact = TIMESTAMP."\t".dhtmlspecialchars(basename($this->var[‘PHP_SELF‘]))."\t".dhtmlspecialchars($this->var[‘mod‘]);

        dsetcookie(‘lastact‘, $lastact, 86400);

        setglobal(‘currenturl_encode‘, base64_encode(‘http://‘.$_SERVER[‘HTTP_HOST‘].$_SERVER[‘REQUEST_URI‘]));

 

        if((!empty($_GET[‘fromuid‘]) || !empty($_GET[‘fromuser‘])) && ($this->var[‘setting‘][‘creditspolicy‘][‘promotion_visit‘] || $this->var[‘setting‘][‘creditspolicy‘][‘promotion_register‘])) {

            require_once libfile(‘misc/promotion‘, ‘include‘);

        }

 

        //SEO keywords

        $this->var[‘seokeywords‘] = !empty($this->var[‘setting‘][‘seokeywords‘][CURSCRIPT]) ? $this->var[‘setting‘][‘seokeywords‘][CURSCRIPT] : ‘‘;

        //SEO 网站描述

        $this->var[‘seodescription‘] = !empty($this->var[‘setting‘][‘seodescription‘][CURSCRIPT]) ? $this->var[‘setting‘][‘seodescription‘][CURSCRIPT] : ‘‘;

 

    }

 

    private function _init_setting() {

        if($this->init_setting) {

            if(empty($this->var[‘setting‘])) {

                $this->cachelist[] = ‘setting‘;//缓存设置文件

            }

 

            if(empty($this->var[‘style‘])) {

                $this->cachelist[] = ‘style_default‘;//风格缓存设置

            }

 

            if(!isset($this->var[‘cache‘][‘cronnextrun‘])) {

                $this->cachelist[] = ‘cronnextrun‘;//缓存计划任务

            }

        }

 

        !empty($this->cachelist) && loadcache($this->cachelist);

 

        if(!is_array($this->var[‘setting‘])) {

            $this->var[‘setting‘] = array();

        }

 

    }

 

    public function _init_style() { //模板初始化方法

        if(defined(‘IN_MOBILE‘)) {

            $mobile = max(1, intval(IN_MOBILE));

            if($mobile && $this->var[‘setting‘][‘styleid‘.$mobile]) {

                $styleid = $this->var[‘setting‘][‘styleid‘.$mobile];

            }

        } else {

           $styleid = !empty($this->var[‘cookie‘][‘styleid‘]) ? $this->var[‘cookie‘][‘styleid‘] : 0;

        }

        if(intval(!empty($this->var[‘forum‘][‘styleid‘]))) {

            $this->var[‘cache‘][‘style_default‘][‘styleid‘] = $styleid = $this->var[‘forum‘][‘styleid‘];

        } elseif(intval(!empty($this->var[‘category‘][‘styleid‘]))) {

            $this->var[‘cache‘][‘style_default‘][‘styleid‘] = $styleid = $this->var[‘category‘][‘styleid‘];

        }

 

        $styleid = intval($styleid);

 

        if($styleid && $styleid != $this->var[‘setting‘][‘styleid‘]) {

            loadcache(‘style_‘.$styleid);

            if($this->var[‘cache‘][‘style_‘.$styleid]) {

                $this->var[‘style‘] = $this->var[‘cache‘][‘style_‘.$styleid];

            }

        }

 

        define(‘IMGDIR‘, $this->var[‘style‘][‘imgdir‘]);

        define(‘STYLEID‘, $this->var[‘style‘][‘styleid‘]);

        define(‘VERHASH‘, $this->var[‘style‘][‘verhash‘]);

        define(‘TPLDIR‘, $this->var[‘style‘][‘tpldir‘]);

        define(‘TEMPLATEID‘, $this->var[‘style‘][‘templateid‘]);

    }

 

    private function _init_mobile() {  //手机访问设置

        if(!$this->init_mobile) {

            return false;

        }

 

        //允许手机访问

        if(!$this->var[‘setting‘] || !$this->var[‘setting‘][‘mobile‘][‘allowmobile‘] || !is_array($this->var[‘setting‘][‘mobile‘]) || IS_ROBOT) {

            $nomobile = true;

            $unallowmobile = true;

        }

 

 

        $mobile = getgpc(‘mobile‘);

        $mobileflag = isset($this->var[‘mobiletpl‘][$mobile]);

        if($mobile === ‘no‘) {

            dsetcookie(‘mobile‘, ‘no‘, 3600);

            $nomobile = true;

        } elseif($this->var[‘cookie‘][‘mobile‘] == ‘no‘ && $mobileflag) {

            checkmobile();//检测是否为手机访问

            dsetcookie(‘mobile‘, ‘‘);

        } elseif($this->var[‘cookie‘][‘mobile‘] == ‘no‘) {

            $nomobile = true;

        } elseif(!($mobile_ = checkmobile())) {

            $nomobile = true;

        } elseif(!$mobile) {

            $mobile = isset($mobile_) ? $mobile_ : 1;

        }

 

        if(!$this->var[‘mobile‘] && !$unallowmobile) {

            if($mobileflag) {

                dheader("Location:misc.php?mod=mobile");

            }

        }

 

        if($nomobile || (!$this->var[‘setting‘][‘mobile‘][‘mobileforward‘] && !$mobileflag)) {

            if($_SERVER[‘HTTP_HOST‘] == $this->var[‘setting‘][‘domain‘][‘app‘][‘mobile‘] && $this->var[‘setting‘][‘domain‘][‘app‘][‘default‘]) {

            dheader("Location:http://".$this->var[‘setting‘][‘domain‘][‘app‘][‘default‘].$_SERVER[‘REQUEST_URI‘]);

                return false;

            } else {

                return false;

            }

        }

 

        if(strpos($this->var[‘setting‘][‘domain‘][‘defaultindex‘], CURSCRIPT) !== false && CURSCRIPT != ‘forum‘ && !$_GET[‘mod‘]) {

            if($this->var[‘setting‘][‘domain‘][‘app‘][‘mobile‘]) {

                $mobileurl = ‘http://‘.$this->var[‘setting‘][‘domain‘][‘app‘][‘mobile‘];

            } else {

                if($this->var[‘setting‘][‘domain‘][‘app‘][‘forum‘]) {

                    $mobileurl = ‘http://‘.$this->var[‘setting‘][‘domain‘][‘app‘][‘forum‘].‘?mobile=yes‘;

                } else {

                    $mobileurl = $this->var[‘siteurl‘].‘forum.php?mobile=yes‘;

                }

            }

            dheader("location:$mobileurl");

        }

        if($mobile === ‘3‘ && empty($this->var[‘setting‘][‘mobile‘][‘wml‘])) {

            return false;

        }

        define(‘IN_MOBILE‘, isset($this->var[‘mobiletpl‘][$mobile]) ? $mobile : ‘2‘);

        setglobal(‘gzipcompress‘, 0);

 

        $arr = array();

        foreach(array_keys($this->var[‘mobiletpl‘]) as $mobiletype) {

            $arr[] = ‘&mobile=‘.$mobiletype;

            $arr[] = ‘mobile=‘.$mobiletype;

        }

        $arr = array_merge(array(strstr($_SERVER[‘QUERY_STRING‘], ‘&simpletype‘), strstr($_SERVER[‘QUERY_STRING‘], ‘simpletype‘)), $arr);

        $query_sting_tmp = str_replace($arr, ‘‘, $_SERVER[‘QUERY_STRING‘]);

        $this->var[‘setting‘][‘mobile‘][‘nomobileurl‘] = ($this->var[‘setting‘][‘domain‘][‘app‘][‘forum‘] ? ‘http://‘.$this->var[‘setting‘][‘domain‘][‘app‘][‘forum‘].‘/‘ : $this->var[‘siteurl‘]).$this->var[‘basefilename‘].($query_sting_tmp ? ‘?‘.$query_sting_tmp.‘&‘ : ‘?‘).‘mobile=no‘;

 

        $this->var[‘setting‘][‘lazyload‘] = 0;

 

        if(‘utf-8‘ != CHARSET) {

            if(strtolower($_SERVER[‘REQUEST_METHOD‘]) === ‘post‘) {

                foreach($_POST AS $pk => $pv) {

                    if(!is_numeric($pv)) {

                        $_GET[$pk] = $_POST[$pk] = $this->mobile_iconv_recurrence($pv);

                        if(!empty($this->var[‘config‘][‘input‘][‘compatible‘])) {

                            $this->var[‘gp_‘.$pk] = daddslashes($_GET[$pk]);

                        }

                    }

                }

            }

        }

 

 

        if(!$this->var[‘setting‘][‘mobile‘][‘mobilesimpletype‘]) {

            $this->var[‘setting‘][‘imagemaxwidth‘] = 224;

        }

 

        $this->var[‘setting‘][‘regstatus‘] = $this->var[‘setting‘][‘mobile‘][‘mobileregister‘] ? $this->var[‘setting‘][‘regstatus‘] : 0 ;

 

        $this->var[‘setting‘][‘thumbquality‘] = 50;

        $this->var[‘setting‘][‘avatarmethod‘] = 0;

 

        $this->var[‘setting‘][‘mobile‘][‘simpletypeurl‘] = array();

        $this->var[‘setting‘][‘mobile‘][‘simpletypeurl‘][0] = $this->var[‘siteurl‘].$this->var[‘basefilename‘].($query_sting_tmp ? ‘?‘.$query_sting_tmp.‘&‘ : ‘?‘).‘mobile=1&simpletype=no‘;

        $this->var[‘setting‘][‘mobile‘][‘simpletypeurl‘][1] =  $this->var[‘siteurl‘].$this->var[‘basefilename‘].($query_sting_tmp ? ‘?‘.$query_sting_tmp.‘&‘ : ‘?‘).‘mobile=1&simpletype=yes‘;

        $this->var[‘setting‘][‘mobile‘][‘simpletypeurl‘][2] =  $this->var[‘siteurl‘].$this->var[‘basefilename‘].($query_sting_tmp ? ‘?‘.$query_sting_tmp.‘&‘ : ‘?‘).‘mobile=2‘;

        unset($query_sting_tmp);

        ob_start();

    }

 

    public function timezone_set($timeoffset = 0) {//时区设置

        if(function_exists(‘date_default_timezone_set‘)) {

            @date_default_timezone_set(‘Etc/GMT‘.($timeoffset > 0 ? ‘-‘ : ‘+‘).(abs($timeoffset)));

        }

    }

 

       public function mobile_iconv_recurrence($value) {//手机访问再次转码

        if(is_array($value)) {

            foreach($value AS $key => $val) {

                $value[$key] = $this->mobile_iconv_recurrence($val);

            }

        } else {

            $value = diconv($value, ‘utf-8‘, CHARSET);

        }

        return $value;

    }

}

 

?>

Discuz X3核心文件解析

标签:tsp   网页   ring   username   request   contents   方法   存在   strlen   

原文地址:http://www.cnblogs.com/lyg0126/p/5986637.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!