• php discuz 核心类函数分析


    简介:这是php discuz 核心类函数分析的详细页面,介绍了和php,sql, php php discuz 核心类函数分析有关的知识、技巧、经验,和一些php源码等。

    class='pingjiaF' frameborder='0' src='http://biancheng.dnbcw.info/pingjia.php?id=348684' scrolling='no'>
    <?php
    
    /**
     *      [Discuz!] (C)2001-2099 Comsenz Inc.
     *      This is NOT a freeware, use is subject to license terms
     *
     *      $Id: class_core.php 6914 2010-03-26 12:52:36Z cnteacher $
     */
    
    ///TODO 是将要完成的功能,包括禁止ip和禁止访问
    //TODO 禁止ip
    //TODO 禁止访问
    
    ///和DZ72一样,确保所有文件需要先加载核心文件
    define('IN_DISCUZ', true);
    
    /**
     * Discuz 核心引擎
     * 其他处理代码当中用到的变量不要在本核心 new 之前设置, 否则会自动清空
     *
     */
    class discuz_core {
    
        // 数据库存储引擎
        var $db = null;
    
        // 内存缓冲object
        var $mem = null;
    
        // 会话 object
        var $session = null;
    
        // 程序配置
        var $config = array();
    
        // $_G 数组的映射
        var $var = array();
    
        // 加载缓存的数组
        var $cachelist = array();
    
        // 是否初始化
        var $init_setting = true; //设置
        var $init_user = true;//用户
        var $init_session = true;//会话
        var $init_cron = true;//任务计划
        var $init_misc = true;//其他功能
        var $init_memory = true;//内存
    
        // 是否已经初始化
        var $initated = false;
    
        var $superglobal = array(
            'GLOBALS' => 1,
            '_GET' = 1,
            '_POST' = 1,
            '_REQUEST' = 1,
            '_COOKIE' = 1,
            '_SERVER' = 1,
            '_ENV' = 1,
            '_FILES' = 1,
        );
    
        function &instance() {
            static $object;
            if(empty($object)) {
                $object = new discuz_core();
            }
            return $object;
        }
    
        function discuz_core() {
            $this->_init_env();
            $this->_init_config();
            $this->_init_input();
            $this->_init_output();
        }
    
        function init() {
            if(!$this->initated) {
                $this->_init_db();
                $this->_init_memory();
                $this->_init_user();
                $this->_init_session();
                $this->_init_setting();
                $this->_init_cron();
                $this->_init_misc();
            }
            $this->initated = true;
        }
    
        function _init_env() {
    
            error_reporting(E_ALL ^ E_NOTICE);
    //        error_reporting(E_ALL);
            ///php 5.3前则关闭魔法引号匹配(自动转义)
            if(phpversion() < '5.3.0') {
                set_magic_quotes_runtime(0);
            }
    
            ///程序主目录,根据核心文件确定,原来是-7 代表在include下,现在是12代表在source/class下
            define('DISCUZ_ROOT', substr(dirname(__FILE__), 0, -12));
            ///和dz72一样,设置魔法引用(自动转义,单双引号反斜线)
            define('MAGIC_QUOTES_GPC', function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc());
            ///判断字符编码转换函数是否存在
            define('ICONV_ENABLE', function_exists('iconv'));
            ///亚洲字符转码函数是否存在, 因为mb_开头字符处理亚洲字符会比较高效,初步判断用于转码时先用mb_来处理:
            define('MB_ENABLE', function_exists('mb_convert_encoding'));
            ///是否存在输出缓存压缩函数,这个函数的目的,是在确认浏览器支持页面压缩后,才用该函数来压缩所有输出内容,否则直接传输
            define('EXT_OBGZIP', function_exists('ob_gzhandler'));
    
            ///和DZ72一样,不过当前时间戳被定义为一个常量,效率更高吧,也不用global了。
            define('TIMESTAMP', time());
            ///获取默认时区
            discuz_core::timezone_set();
    
            ///加载function_core.php,作用推测类似global.func.php
            if(!defined('DISCUZ_CORE_FUNCTION') && !@include(DISCUZ_ROOT.'./source/function/function_core.php')) {
                $this->error('function_core.php is missing');
            }
    
            //判断浏览器是否是蜘蛛
            define('IS_ROBOT', checkrobot());
    
            //清理全局变量
            ///全清理了,真是彻底把所有变量都从内存中注销了
            foreach ($GLOBALS as $key = $value) {
                if (!isset($this->superglobal[$key])) {
                    $GLOBALS[$key] = null; unset($GLOBALS[$key]);
                }
            }
    
            // 配置全局变量
            ///和上一步结合,只留下自己需要的变量,并初始化。
            ///这么做够狠,只要稍微小心点,就不会出现因为变量未初始化而出现的安全问题
            global $_G;
            $_G = array(
                //公用全局定义
                'uid' = 0,
                'username' = '',
                'adminid' = 0,
                'groupid' = 1,
                'sid' = '',
                'formhash' = '',
                'timestamp' = TIMESTAMP,
                'starttime' = dmicrotime(),
                'clientip' = $this->_get_client_ip(),
                'referer' = '',
                'charset' = '',
                'gzipcompress' = '',
                'authkey' = '',
                'timenow' = array(),
    
                'PHP_SELF' = '',
                'siteurl' = '',
    
                //公用全局数组定义
                'config' = array(),
                'setting' = array(),
                'member' = array(),
                'group' = array(),
                'cookie' = array(),
                'style' = array(),
                'cache' = array(),
                'session' = array(),
                'lang' = array(),
                'my_app' = array(),//默认应用
                'my_userapp' = array(),//用户自添加应用
    
                //论坛全局定义
                'fid' = 0,
                'tid' = 0,
                'forum' = array(),
                'rssauth' = '',
    
                //uch 全局定义
                'home' = array(),
                'space' = array(),
    
                //portal 全局定义
                'block' = array(),
                'article' = array(),
    
                //Action
                'action' = array(
                    'action' = APPTYPEID,
                    'fid' = 0,
                    'tid' = 0,
                )
            );
            //相对主目录的相对地址及文件名
            $_G['PHP_SELF'] = htmlspecialchars($_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']);
            //基本脚本名,每个功能脚本首页前都会定义
            //比如forum.php,则定义CURSCRIPT为forum,而forum_forumdisplay.php则不定义,因为属于forum
            $_G['basescript'] = CURSCRIPT;
            //站点网址
            $_G['siteurl'] = htmlspecialchars('http://'.$_SERVER['HTTP_HOST'].preg_replace("/\/+(api)?\/*$/i", '', substr($_G['PHP_SELF'], 0, strrpos($_G['PHP_SELF'], '/'))).'/');
    
            ///$_G的映射,也即超级全局变量
            $this->var = & $_G;
    
        }
    
        function _init_input() {
    
            //note 禁止对全局变量注入
            ///和dz72类似,禁止GLOBALS=xxx的方式注入
            if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS'])) {
                error('request_tainting');
            }
    
            if(!empty($_GET['rewrite'])) {
                $query_string = '?mod=';
                $param = explode('-', $_GET['rewrite']);
                $query_string .= $_GET['mod'] = $param[0];
                array_shift($param);
                $paramc = count($param);
                for($i = 0;$i < $paramc;$i+=2) {
                    $_REQUEST[$param[$i]] = $_GET[$param[$i]] = $param[$i + 1];
                    $query_string .= '&'.$param[$i].'='.$param[$i + 1];
                }
                $_SERVER['QUERY_STRING'] = $query_string;
                unset($param, $paramc, $query_string);
            }
    
            // slashes 处理,如果没有魔法引号处理(自动转义),则手动转义GET/POST/COOKIE/FILES中的单双引号、null反斜线\
            if(!MAGIC_QUOTES_GPC) {
                $_GET = daddslashes($_GET);
                $_POST = daddslashes($_POST);
                $_COOKIE = daddslashes($_COOKIE);
                $_FILES = daddslashes($_FILES);
            }
    
            //cookie 处理
            ///验证cookie前缀与config中的设置值是否一致,一致则转为$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;
                }
            }
    
            $_GET['diy'] = empty($_GET['diy']) ? '' : $_GET['diy'];
    
            ///$_GET和$_POST转成与索引同名加"gp_"前缀的变量
            ///如$_GET['username']直接用$gp_username来访问
            foreach(array_merge($_POST, $_GET) as $k = $v) {
                $this->var['gp_'.$k] = $v;
            }
    
            ///根据$_GET['mod']来确定m的值,$this->var为全局数组,gp_为上个语句的附加前缀
            $this->var['mod'] = empty($this->var['gp_mod']) ? '' : htmlspecialchars($this->var['gp_mod']);
            ///如果使用ajax,再判断是post传值或get和xmlhttprequest同时有效
            $this->var['inajax'] = empty($this->var['gp_inajax']) ? 0 : ($_SERVER['REQUEST_METHOD'] == 'GET' && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' || $_SERVER['REQUEST_METHOD'] == 'POST' ? 1 : 0);
            ///当前页码
            $this->var['page'] = empty($this->var['gp_page']) ? 1 : max(1, intval($this->var['gp_page']));
            ///确定cookie中的sid值
            $this->var['sid'] = $this->var['cookie']['sid'] = isset($this->var['cookie']['sid']) ? htmlspecialchars($this->var['cookie']['sid']) : '';
        }
    
        ///初始化设置
        function _init_config() {
            ///加载设置文件
            $_config = array();
            @include DISCUZ_ROOT.'./config/config_global.php';
            if(empty($_config)) {
                error('config_notfound');
            }
            ///确定密钥,如果值为空,则密钥默认为cookie前缀与数据库名拼接的md5值,否则为配置文件中的值
            ///authkey密钥是sid等参数加解密的重要参数
            $_config['security']['authkey'] = empty($config['security']['authkey']) ? md5($_config['cookie']['cookiepre'].$_config['db'][1]['dbname']) : ($config['security']['authkey']);
    
            $this->config = & $_config;
            ///Discuz的调试
            if(empty($this->config['debug']) || !file_exists(libfile('function/debug'))) {
                define('DISCUZ_DEBUG', false);
            } elseif($this->config['debug'] === 1 || $this->config['debug'] === 2 || !empty($_REQUEST['debug']) && $_REQUEST['debug'] === $this->config['debug']) {
                define('DISCUZ_DEBUG', true);
                if($this->config['debug'] == 2) {
                    error_reporting(E_ALL);
                }
            }
    
            $GLOBALS['_G']['config'] = & $this->config;
            ///以浏览器版本为参考,进行密钥的二次md5加密
            $GLOBALS['_G']['authkey'] = md5($this->config['security']['authkey'].$_SERVER['HTTP_USER_AGENT']);
        }
    
        function _init_output() {
            ///如果设置中打开xss跨站脚本的防御模式,且网址中存在"<"和"""等非法字符,则拒绝请求
            if($this->config['security']['urlxssdefend'] && !empty($_SERVER['REQUEST_URI'])) {
                $temp = urldecode($_SERVER['REQUEST_URI']);
                if(strpos($temp, '<') !== false || strpos($temp, '"') !== false) {
                    error('request_tainting');
                }
            }
    
            ///存在ob_gzhandler则启用输出缓存压缩
            if($this->config['output']['gzip'] && EXT_OBGZIP) {
                ob_start('ob_gzhandler');
                setglobal('gzipcompress', true);
            } else {
                ob_start();
                setglobal('gzipcompress', false);
            }
    
            ///确定HTML页面编码,及其他编码
            if($this->config['output']['forceheader']) {
                @header('Content-Type: text/html; charset='.$this->config['output']['charset']);
            }
    
            setglobal('charset', $this->config['output']['charset']);
            define('CHARSET', $this->config['output']['charset']);
        }
    
        ///拒绝机器人访问
        function reject_robot() {
            if(IS_ROBOT) {
                exit(header("HTTP/1.1 403 Forbidden"));
            }
        }
    
        ///获取客户端ip,
        function _get_client_ip() {
            $clientip = '';
            ///环境变量客户端ip有值且字符长度大于unknown,则说明该变量有效,确定为客户端ip
            if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
                $clientip = getenv('HTTP_CLIENT_IP');
            ///否则取当前浏览用户的网关ip地址
            } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
                $clientip = getenv('HTTP_X_FORWARDED_FOR');
            ///用户计算机的ip地址
            } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
                $clientip = getenv('REMOTE_ADDR');
            } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
                $clientip = $_SERVER['REMOTE_ADDR'];
            }
    
            ///判断是否是数字与点组成的7-15位字符
            preg_match("/[\d\.]{7,15}/", $clientip, $clientipmatches);
            $clientip = $clientipmatches[0] ? $clientipmatches[0] : 'unknown';
            return $clientip;
        }
    
        function _init_db() {
            ///生成数据库对象
            $this->db = & DB::object();
            ///加载设置文件并连接数据库
            $this->db->set_config($this->config['db']);
            $this->db->connect();
        }
    
        function _init_session() {
    
            $this->session = new discuz_session();
    
            if($this->init_session)
            {
                ///传入sid,客户端ip与uid作为session判断机制,分新老用户,老用户则查session表,否则创建
                $this->session->init($this->var['cookie']['sid'], $this->var['clientip'], $this->var['uid']);
                $this->var['sid'] = $this->session->sid;
                $this->var['session'] = $this->session->var;
    
                if($this->var['sid'] != $this->var['cookie']['sid']) {
                    dsetcookie('sid', $this->var['sid'], 86400);
                }
    
                // 首次登陆更新最后访问时间,每隔 10 分钟更新用户最后动作时间
                if($this->var['uid'] && ($this->session->isnew || ($this->session->get('lastactivity') + 600) < TIMESTAMP)) {
    
                    $this->session->set('lastactivity', TIMESTAMP);
    
                    $update = array('lastip' = $this->var['clientip'], 'lastactivity' = TIMESTAMP);
                    if($this->session->isnew) {
                        $update['lastvisit'] = TIMESTAMP;
                    }
                    更新会员状态
                    DB::update('common_member_status', $update, "uid='".$this->var['uid']."'");
                }
            }
        }
    
        function _init_user() {
    
            if($this->init_user) {
                if($auth = getglobal('auth', 'cookie')) {
                    $auth = daddslashes(explode("\t", authcode($auth, 'DECODE')));
                }
                list($discuz_pw, $discuz_uid) = empty($auth) || count($auth) < 2 ? array('', '') : $auth;
    
                if($discuz_uid) {
                    $user = getuserbyuid($discuz_uid);
                }
    
                if(!empty($user) && $user['password'] == $discuz_pw) {
                    $this->var['member'] = $user;
                } else {
                    $user = array();
                    $this->_init_guest();
                }
    
                $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();
            }
    
            if(empty($this->var['cookie']['lastvisit'])) {
                $this->var['member']['lastvisit'] = TIMESTAMP - 3600;
                dsetcookie('lastvisit', TIMESTAMP - 3600, 86400 * 30);
            } else {
                $this->var['member']['lastvisit'] = empty($this->var['cookie']['lastvisit']);
            }
    
            setglobal('uid', getglobal('uid', 'member'));
            setglobal('username', addslashes(getglobal('username', 'member')));
            setglobal('adminid', getglobal('adminid', 'member'));
            setglobal('groupid', getglobal('groupid', 'member'));
        }
    
        function _init_guest() {
            setglobal('member', array( 'uid' = 0, 'username' = '', 'groupid' = 7, 'credits' = 0, 'timeoffset' = 9999));
        }
    
        function _init_cron() {
            if($this->init_cron && $this->init_setting) {
                if($this->var['cache']['cronnextrun'] <= TIMESTAMP) {
                    discuz_cron::run();
                }
            }
        }
    
        function _init_misc() {
    
            if(!$this->init_misc) {
                return false;
            }
            // 调入核心语言包
            lang('core');
    
            //处理全局时区设置
            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();
            define('FORMHASH', $this->var['formhash']);
    
            // 定义风格常量
            if(is_array($this->var['style'])) {
                foreach ($this->var['style'] as $key = $val) {
                    $key = strtoupper($key);
                    if(!defined($key) && !is_array($val)) {
                        define($key, $val);
                    }
                }
            }
    
            //论坛开关检查
            if($this->var['setting']['**losed'] && !(in_array($this->var['mod'], array('logging', 'seccode')) || getglobal('adminid', 'member') == 1)) {
                $closedreason = DB::result_first("SELECT svalue FROM ".DB::table('common_setting')." WHERE skey='closedreason'");
                showmessage($closedreason ? $closedreason : 'board_closed', NULL, array(), array('login' = 1));
            }
    
            $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;
    
            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");
            }
    
            $lastact = TIMESTAMP."\t".htmlspecialchars(basename($this->var['PHP_SELF']))."\t".htmlspecialchars($this->var['mod']);
            dsetcookie('lastact', $lastact, 86400);
    
        }
    
        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();
            }
            if($this->var['member'] && $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']]);
            }
        }
    
        function _init_memory() {
            $this->mem = new discuz_memory();
            if($this->init_memory) {
                $this->mem->init($this->config['memory']);
            }
            $this->var['memory'] = $this->mem->type;
        }
    
        function timezone_set($timeoffset = 0) {
            if(function_exists('date_default_timezone_set')) {
                @date_default_timezone_set('Etc/GMT'.($timeoffset  0 ? '-' : '+').(abs($timeoffset)));
            }
        }
    
        function error($msg, $halt = true) {
            $this->error_log($msg);
            echo $msg;
            $halt && exit();
        }
    
        function error_log($message) {
            $time = date("Y-m-d H:i:s", TIMESTAMP);
            $file =  DISCUZ_ROOT.'./data/log/errorlog_'.date("Ym").'.txt';
            $message = "\n#{$time}:\t".str_replace(array("\t", "\r", "\n"), " ", $message);
            error_log($message, 3, $file);
        }
    
    }
    
    /**
     * Discuz MySQL 类的支持
     *
     */
    class db_mysql
    {
        var $tablepre;
        var $version = '';
        var $querynum = 0;
        var $curlink;
        var $link = array();
        var $config = array();
        var $sqldebug = array();
    
        function db_mysql($config = array()) {
            if(!empty($config)) {
                $this->set_config($config);
            }
        }
    
        function set_config($config) {
            $this->config = &$config;
            $this->tablepre = $config['1']['tablepre'];
        }
    
        function connect() {
    
            if(empty($this->config) || empty($this->config[1])) {
                $this->halt('notfound_config');
            }
    
            foreach ($this->config as $id = $config) {
                $this->link[$id] = $this->_dbconnect(
                $config['dbhost'],
                $config['dbuser'],
                $config['dbpw'],
                $config['dbcharset'],
                $config['dbname'],
                $config['pconnect']
                );
            }
            $this->curlink = $this->link[1];
        }
    
        function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname, $pconnect) {
            $link = null;
            $func = empty($pconnect) ? 'mysql_connect' : 'mysql_pconnect';
            if(!$link = @$func($dbhost, $dbuser, $dbpw, 1)) {
                $this->halt('notconnect');
            } else {
                $this->curlink = $link;
                if($this->version()  '4.1') {
                    $serverset = $dbcharset ? 'character_set_connection='.$dbcharset.', character_set_results='.$dbcharset.', character_set_client=binary' : '';
                    $serverset .= $this->version()  '5.0.1' ? ((empty($serverset) ? '' : ',').'sql_mode=\'\'') : '';
                    $serverset && mysql_query("SET $serverset", $link);
                }
                $dbname && @mysql_select_db($dbname, $link);
            }
            return $link;
        }
    
        function table_name($tablename) {
            return $this->tablepre.$tablename;
        }
    
        function select_db($dbname) {
            return mysql_select_db($dbname, $this->curlink);
        }
    
        function fetch_array($query, $result_type = MYSQL_ASSOC) {
            return mysql_fetch_array($query, $result_type);
        }
    
        function fetch_first($sql) {
            return $this->fetch_array($this->query($sql));
        }
    
        function result_first($sql) {
            return $this->result($this->query($sql), 0);
        }
    
        function query($sql, $type = '') {
    
            if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
                $starttime = dmicrotime();
            }
            $func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ?
            'mysql_unbuffered_query' : 'mysql_query';
            if(!($query = $func($sql, $this->curlink))) {
                if(in_array($this->errno(), array(2006, 2013)) && substr($type, 0, 5) != 'RETRY') {
                    $this->connect();
                    return $this->query($sql, 'RETRY'.$type);
                }
                if($type != 'SILENT' && substr($type, 5) != 'SILENT') {
                    $this->halt('query_error', $sql);
                }
            }
    
            if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
                $this->sqldebug[] = array($sql, number_format((dmicrotime() - $starttime), 6), debug_backtrace());
            }
    
            $this->querynum++;
            return $query;
        }
    
        function affected_rows() {
            return mysql_affected_rows($this->curlink);
        }
    
        function error() {
            return (($this->curlink) ? mysql_error($this->curlink) : mysql_error());
        }
    
        function errno() {
            return intval(($this->curlink) ? mysql_errno($this->curlink) : mysql_errno());
        }
    
        function result($query, $row = 0) {
            $query = @mysql_result($query, $row);
            return $query;
        }
    
        function num_rows($query) {
            $query = mysql_num_rows($query);
            return $query;
        }
    
        function num_fields($query) {
            return mysql_num_fields($query);
        }
    
        function free_result($query) {
            return mysql_free_result($query);
        }
    
        function insert_id() {
            return ($id = mysql_insert_id($this->curlink)) = 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
        }
    
        function fetch_row($query) {
            $query = mysql_fetch_row($query);
            return $query;
        }
    
        function fetch_fields($query) {
            return mysql_fetch_field($query);
        }
    
        function version() {
            if(empty($this->version)) {
                $this->version = mysql_get_server_info($this->curlink);
            }
            return $this->version;
        }
    
        function close() {
            return mysql_close($this->curlink);
        }
    
        function halt($message = '', $sql = '') {
            global $_G;
            $dberror = $this->error();
            $dberrno = $this->errno();
            $phperror = '<table style="font-size:11px" cellpadding="0"><tr><td width="270">File</td><td width="80">Line</td><td>Function</td></tr>';
            foreach (debug_backtrace() as $error) {
                $error['file'] = str_replace(DISCUZ_ROOT, '', $error['file']);
                $error['class'] = isset($error['class']) ? $error['class'] : '';
                $error['type'] = isset($error['type']) ? $error['type'] : '';
                $error['function'] = isset($error['function']) ? $error['function'] : '';
                $phperror .= "<tr><td>$error[file]</td><td>$error[line]</td><td>$error[class]$error[type]$error[function]()</td></tr>";
            }
            $phperror .= '</table>';
            $helplink = "http://faq.comsenz.com/?type=mysql&dberrno=".rawurlencode($dberrno)."&dberror=".rawurlencode($dberror);
            @header('Content-Type: text/html; charset='.$_G['config']['output']['charset']);
            echo '<div style="position:absolute;font-size:11px;font-family:verdana,arial;background:#EBEBEB;padding:0.5em;line-height:1.5em">'.
            error('db_error', array(
                '$message' = error('db_'.$message, array(), true),
                '$info' = $dberror ? error('db_error_message', array('$dberror' = $dberror), true) : '',
                '$sql' = $sql ? error('db_error_sql', array('$sql' = $sql), true) : '',
                '$errorno' = $dberrno ? error('db_error_no', array('$dberrno' = $dberrno), true) : '',
                '$helplink' = $helplink,
                ), true);
            echo "<b>PHP Backtrace</b><br />$phperror<br /></div>";
            exit();
        }
    
    }
    
    /**
     * 对Discuz CORE 中 DB Object中的主要方法进行二次封装,方便程序调用
     *
     */
    class DB
    {
    
        /**
         * 返回表名(pre_$table)
         *
         * @param 原始表名 $table
         * @return 增加pre之后的名字
         */
        function table($table) {
            $a = & DB::object();
            return $a->table_name($table);
        }
    
        /**
         * 删除一条或者多条记录
         *
         * @param string $table 原始表名
         * @param string $condition 条件语句,不需要写WHERE
         * @param int $limit 删除条目数
         * @param boolean $unbuffered 立即返回?
         */
        function delete($table, $condition, $limit = 0, $unbuffered = true) {
            if(empty($condition)) {
                $where = '1';
            } elseif(is_array($condition)) {
                $where = DB::implode_field_value($condition, ' AND ');
            } else {
                $where = $condition;
            }
            $sql = "DELETE FROM ".DB::table($table)." WHERE $where ".($limit ? "LIMIT $limit" : '');
            return DB::query($sql, ($unbuffered ? 'UNBUFFERED' : ''));
        }
    
        /**
         * 插入一条记录
         *
         * @param string $table 原始表名
         * @param array $data 数组field->vlaue 对
         * @param boolen $return_insert_id 返回 InsertID?
         * @param boolen $replace 是否是REPLACE模式
         * @param boolen $silent 屏蔽错误?
         * @return InsertID or Result
         */
        function insert($table, $data, $return_insert_id = false, $replace = false, $silent = false) {
    
            $sql = DB::implode_field_value($data);
    
            $cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';
    
            $table = DB::table($table);
            $silent = $silent ? 'SILENT' : '';
    
            $return = DB::query("$cmd $table SET $sql", $silent);
    
            return $return_insert_id ? DB::insert_id() : $return;
    
        }
    
        /**
         * 更新一条或者多条数据记录
         *
         * @param string $table 原始表名
         * @param array $data 数据field-value
         * @param string $condition 条件语句,不需要写WHERE
         * @param boolean $unbuffered 迅速返回?
         * @param boolan $low_priority 延迟更新?
         * @return result
         */
        function update($table, $data, $condition, $unbuffered = false, $low_priority = false) {
            $sql = DB::implode_field_value($data);
            $cmd = "UPDATE ".($low_priority ? 'LOW_PRIORITY' : '');
            $table = DB::table($table);
            $where = $comma = '';
            if(empty($condition)) {
                $where = '1';
            } elseif(is_array($condition)) {
                $where = DB::implode_field_value($condition, ' AND ');
            } else {
                $where = $condition;
            }
            $res = DB::query("$cmd $table SET $sql WHERE $where", $unbuffered ? 'UNBUFFERED' : '');
            return $res;
        }
    
        /**
         * 格式化field字段和value,并组成一个字符串
         *
         * @param array $array 格式为 key=value 数组
         * @param 分割符 $glue
         * @return string
         */
        function implode_field_value($array, $glue = ',') {
            //print_r(debug_backtrace());
            $sql = $comma = '';
            foreach ($array as $k = $v) {
                $sql .= $comma."`$k`='$v'";
                $comma = $glue;
            }
            return $sql;
        }
    
        /**
         * 返回插入的ID
         *
         * @return int
         */
        function insert_id() {
            $db = & DB::object();
            return $db->insert_id();
        }
    
        /**
         * 依据查询结果,返回一行数据
         *
         * @param resourceID $resourceid
         * @return array
         */
        function fetch($resourceid) {
            $db = & DB::object();
            return $db->fetch_array($resourceid);
        }
    
        /**
         * 依据SQL文,返回一条查询结果
         *
         * @param string $query 查询语句
         * @return array
         */
        function fetch_first($sql) {
            $db = & DB::object();
            return $db->fetch_first($sql);
        }
    
        /**
         * 依据查询结果,返回结果数值
         *
         * @param resourceid $resourceid
         * @return string or int
         */
        function result($resourceid, $row = 0) {
            $db = & DB::object();
            return $db->result($resourceid, $row);
        }
    
        /**
         * 依据查询语句,返回结果数值
         *
         * @param string $query SQL查询语句
         * @return unknown
         */
        function result_first($sql) {
            $db = & DB::object();
            return $db->result_first($sql);
        }
    
        /**
         * 执行查询
         *
         * @param string $sql
         * @param 类型定义 $type UNBUFFERED OR SILENT
         * @return Resource OR Result
         */
        function query($sql, $type = '') {
            $db = & DB::object();
            return $db->query($sql, $type);
        }
    
        /**
         * 返回select的结果行数
         *
         * @param resource $resourceid
         * @return int
         */
        function num_rows($resourceid) {
            $db = & DB::object();
            return $db->num_rows($resourceid);
        }
    
        /**
         * 返回sql语句所影响的记录行数
         *
         * @return int
         */
        function affected_rows() {
            $db = & DB::object();
            return $db->affected_rows();
        }
    
        function free_result($query) {
            $db = & DB::object();
            return $db->free_result($query);
        }
    
        function error() {
            $db = & DB::object();
            return $db->error();
        }
    
        function errno() {
            $db = & DB::object();
            return $db->errno();
        }
    
        /**
         * 返回 DB object 指针
         *
         * @return pointer of db object from discuz core
         */
        function &object() {
            static $db;
            if(empty($db)) {
                $db = new db_mysql();
            }
            return $db;
        }
    }
    
    class discuz_session {
    
        ///sid,ip1-4, uid, username, groupid组id, invisible隐身与否,action行为,上次活动lastactivity,fid板块id,tid帖子id
        var $sid = null;
        var $var;
        var $isnew = false;
        var $newguest = array('sid' = 0, 'ip1' = 0, 'ip2' = 0, 'ip3' = 0, 'ip4' = 0,
        'uid' = 0, 'username' = '', 'groupid' = 7, 'invisible' = 0, 'action' = 0,
        'lastactivity' = 0, 'fid' = 0, 'tid' = 0);
    
        var $old =  array('sid' =  '', 'ip' =  '', 'uid' =  0);
    
        ///与类同名的函数,构造函数,初始化session各值
        function discuz_session($sid = '', $ip = '', $uid = 0) {
            $this->old = array('sid' =  $sid, 'ip' =  $ip, 'uid' =  $uid);
            $this->var = $this->newguest;
            if(!empty($ip)) {
                $this->init($sid, $ip, $uid);
            }
        }
        ///设置$newguest各项值
        function set($key, $value) {
            if(isset($this->newguest[$key])) {
                $this->var[$key] = $value;
            } elseif ($key == 'ip') {
                $ips = explode('.', $value);
                $this->set('ip1', $ips[0]);
                $this->set('ip2', $ips[1]);
                $this->set('ip3', $ips[2]);
                $this->set('ip4', $ips[3]);
            }
        }
    
        ///获取
        function get($key) {
            if(isset($this->newguest[$key])) {
                return $this->var[$key];
            } elseif ($key == 'ip') {
                return $this->get('ip1').'.'.$this->get('ip2').'.'.$this->get('ip3').'.'.$this->get('ip4');
            }
        }
    
        ///初始化,sid有值则可能是老用户,去读session表,判断sid,ip符合的值是否存在,存在则赋值给$sid
        function init($sid, $ip, $uid) {
            $this->old = array('sid' =  $sid, 'ip' =  $ip, 'uid' =  $uid);
            $session = array();
            if($sid) {
                $session = DB::fetch_first("SELECT * FROM ".DB::table('common_session').
                    " WHERE sid='$sid' AND CONCAT_WS('.', ip1,ip2,ip3,ip4)='$ip'");
            }
    
            if(empty($session) || $session['uid'] != $uid) {
                $session = $this->create($ip, $uid);
            }
    
            $this->var = $session;
            $this->sid = $session['sid'];
        }
    
        ///新用户
        function create($ip, $uid) {
    
            $this->isnew = true;
            $this->var = $this->newguest;
            $this->set('sid', random(6));
            $this->set('uid', $uid);
            $this->set('ip', $ip);
            $this->set('lastactivity', time());
            $this->sid = $this->var['sid'];
    
            return $this->var;
        }
    
        function delete() {
    
            $onlinehold = 1800; //此数值应当取自全局变量
            $guestspan = 60; //避免游客重复激活sid
    
            $onlinehold = time() - $onlinehold;
            $guestspan = time() - $guestspan;
    
            //当前用户的sid
            $condition = " sid='{$this->sid}' ";
            //过期的 session
            $condition .= " OR lastactivity<$onlinehold ";
            //频繁的同一ip游客
            $condition .= " OR (uid='0' AND ip1='{$this->var['ip1']}' AND ip2='{$this->var['ip2']}' AND ip3='{$this->var['ip3']}' AND ip4='{$this->var['ip4']}' AND lastactivity$guestspan) ";
            //当前用户的uid
            $condition .= $this->var['uid'] ? " OR (uid='{$this->var['uid']}') " : '';
            DB::delete('common_session', $condition);
        }
    
        function update() {
            if($this->sid !== null) {
    
                $data = daddslashes($this->var);
    
                if($this->isnew) {
                    $this->delete();
                    DB::insert('common_session', $data, false, false, true);
                } else {
                    DB::update('common_session', $data, "sid='$data[sid]'");
                }
                dsetcookie('sid', $this->sid, 86400);
            }
        }
    
        /**
         * 取在线用户数量
         *
         * @param int $type 0=全部 1=会员 2=游客
         */
        function onlinecount($type = 0) {
            $condition = $type == 1 ? ' WHERE uid0 ' : ($type == 2 ? ' WHERE invisible=1 ' : '');
            return DB::result_first("SELECT count(*) FROM ".DB::table('common_session').$condition);
        }
    
    }
    
    class discuz_cron
    {
    
        /**
         * 运行cron
         *
         * @param int $cronid 执行某个cron,如果不指定则运行当前需要运行的
         * @return true
         */
        function run($cronid = 0) {
    
            $timestamp = TIMESTAMP;
            $cron = DB::fetch_first("SELECT * FROM ".DB::table('common_cron')."
                    WHERE ".($cronid ? "cronid='$cronid'" : "available'0' AND nextrun<='$timestamp'")."
                    ORDER BY nextrun LIMIT 1");
    
            $processname ='DZ_CRON_'.(empty($cron) ? 'CHECKER' : $cron['cronid']);
    
            if(!discuz_process::create($processname, 600)) {
                return false;
            }
    
            if($cron) {
    
                $cron['filename'] = str_replace(array('..', '/', '\\'), '', $cron['filename']);
                $cronfile = DISCUZ_ROOT.'./source/include/cron/'.$cron['filename'];
    
                $cron['minute'] = explode("\t", $cron['minute']);
                discuz_cron::setnextime($cron);
    
                @set_time_limit(1000);
                @ignore_user_abort(TRUE);
    
                if(!@include $cronfile) {
                    //debug('CRON', $cron['name'].' : Cron script('.$cron['filename'].') not found or syntax error', 0);
                }
            }
    
            discuz_cron::nextcron();
            discuz_process::delete($processname);
            return true;
        }
    
        /**
         * 设定下一个计划任务将要执行的时间 here...
         *
         */
        function nextcron() {
            $nextrun = DB::result_first("SELECT nextrun FROM ".DB::table('common_cron')." WHERE available>'0' ORDER BY nextrun LIMIT 1");
            if($nextrun !== FALSE) {
                save_syscache('cronnextrun', $nextrun);
            } else {
                save_syscache('cronnextrun', TIMESTAMP + 86400 * 365);
            }
            return true;
        }
    
        /**
         * 设定某个计划任务下次执行时间
         *
         * @param array $cron
         * @return true
         */
        function setnextime($cron) {
    
            global $_G;
    
            if(empty($cron)) return FALSE;
    
            list($yearnow, $monthnow, $daynow, $weekdaynow, $hournow, $minutenow) = explode('-', gmdate('Y-m-d-w-H-i', TIMESTAMP + $_G['setting']['timeoffset'] * 3600));
    
            if($cron['weekday'] == -1) {
                if($cron['day'] == -1) {
                    $firstday = $daynow;
                    $secondday = $daynow + 1;
                } else {
                    $firstday = $cron['day'];
                    $secondday = $cron['day'] + gmdate('t', TIMESTAMP + $_G['setting']['timeoffset'] * 3600);
                }
            } else {
                $firstday = $daynow + ($cron['weekday'] - $weekdaynow);
                $secondday = $firstday + 7;
            }
    
            if($firstday < $daynow) {
                $firstday = $secondday;
            }
    
            if($firstday == $daynow) {
                $todaytime = discuz_cron::todaynextrun($cron);
                if($todaytime['hour'] == -1 && $todaytime['minute'] == -1) {
                    $cron['day'] = $secondday;
                    $nexttime = discuz_cron::todaynextrun($cron, 0, -1);
                    $cron['hour'] = $nexttime['hour'];
                    $cron['minute'] = $nexttime['minute'];
                } else {
                    $cron['day'] = $firstday;
                    $cron['hour'] = $todaytime['hour'];
                    $cron['minute'] = $todaytime['minute'];
                }
            } else {
                $cron['day'] = $firstday;
                $nexttime = discuz_cron::todaynextrun($cron, 0, -1);
                $cron['hour'] = $nexttime['hour'];
                $cron['minute'] = $nexttime['minute'];
            }
    
            $nextrun = @gmmktime($cron['hour'], $cron['minute'] > 0 ? $cron['minute'] : 0, 0, $monthnow, $cron['day'], $yearnow) - $_G['setting']['timeoffset'] * 3600;
    
            $availableadd = $nextrun  TIMESTAMP ? '' : ', available=\'0\'';
            DB::query("UPDATE ".DB::table('common_cron')." SET lastrun='$_G[timestamp]', nextrun='$nextrun' $availableadd WHERE cronid='$cron[cronid]'");
    
            return true;
        }
    
        /**
         * 计算计划任务今日执行状态
         *
         * @param int $cron
         * @param int $hour
         * @param int $minute
         * @return int
         */
        function todaynextrun($cron, $hour = -2, $minute = -2) {
            global $_G;
    
            $hour = $hour == -2 ? gmdate('H', TIMESTAMP + $_G['setting']['timeoffset'] * 3600) : $hour;
            $minute = $minute == -2 ? gmdate('i', TIMESTAMP + $_G['setting']['timeoffset'] * 3600) : $minute;
    
            $nexttime = array();
            if($cron['hour'] == -1 && !$cron['minute']) {
                $nexttime['hour'] = $hour;
                $nexttime['minute'] = $minute + 1;
            } elseif($cron['hour'] == -1 && $cron['minute'] != '') {
                $nexttime['hour'] = $hour;
                if(($nextminute = discuz_cron::nextminute($cron['minute'], $minute)) === false) {
                    ++$nexttime['hour'];
                    $nextminute = $cron['minute'][0];
                }
                $nexttime['minute'] = $nextminute;
            } elseif($cron['hour'] != -1 && $cron['minute'] == '') {
                if($cron['hour'] < $hour) {
                    $nexttime['hour'] = $nexttime['minute'] = -1;
                } elseif($cron['hour'] == $hour) {
                    $nexttime['hour'] = $cron['hour'];
                    $nexttime['minute'] = $minute + 1;
                } else {
                    $nexttime['hour'] = $cron['hour'];
                    $nexttime['minute'] = 0;
                }
            } elseif($cron['hour'] != -1 && $cron['minute'] != '') {
                $nextminute = discuz_cron::nextminute($cron['minute'], $minute);
                if($cron['hour'] &lt; $hour || ($cron['hour'] == $hour && $nextminute === false)) {
                    $nexttime['hour'] = -1;
                    $nexttime['minute'] = -1;
                } else {
                    $nexttime['hour'] = $cron['hour'];
                    $nexttime['minute'] = $nextminute;
                }
            }
    
            return $nexttime;
        }
    
        /**
         * 计算计划任务执行时刻
         *
         * @param int $nextminutes
         * @param int $minutenow
         * @return int
         */
        function nextminute($nextminutes, $minutenow) {
            foreach($nextminutes as $nextminute) {
                if($nextminute > $minutenow) {
                    return $nextminute;
                }
            }
            return false;
        }
    }
    
    /**
     * 功能进程管理
     * 通常用于某些功能禁止?⒎⒃诵?
     *
     */
    
    class discuz_process
    {
    
        /**
         * 获取某进程信息
         *
         * @param string $name 进程名字
         * @return array
         */
        function get($name) {
            $name5 = md5($name);
            $res = DB::fetch_first("SELECT * FROM ".DB::table('common_process')." WHERE processid='$name5'");
    
            if(empty($res)) {
                $res = array();
            } elseif($res['expiry'] < TIMESTAMP) {
                discuz_process::delete($name);
                $res = array();
            }
            return $res;
        }
    
        /**
         * 创建进程
         *
         * @param string $name 进程名
         * @param int $lifespan 进程过期时间
         * @param int $extra 进程附属信息
         * @return boolean
         */
        function create($name, $lifespan = 0, $extra = 0) {
            $check = discuz_process::get($name);
            if(empty($check)) {
                $lifespan = empty($lifespan) ? 600 : $lifespan;
                DB::insert('common_process', array(
                    'processid' => md5($name),
                    'expiry' = TIMESTAMP + $lifespan,
                    'extra' =$extra), false, true);
                return true;
            }
            else {
                return false;
            }
        }
    
        /**
         * 删除某个进程或过期进程
         *
         * @param string $name 进程名
         */
        function delete($name = '') {
            $name = md5($name);
            DB::delete('common_process', "processid='$name' OR expiry<".TIMESTAMP);
        }
    
    }
    
    /**
     * Discuz 内存读写引擎
     * 支持 memcache, eAccelerator, XCache
     *
     * 使用的时候建议直接利用函数 memory()
     */
    class discuz_memory
    {
        var $config;
        var $extension = array();
        var $memory;
        var $prefix;
        var $type;
        var $keys;
        var $enable = false;
    
        /**
         * 确认当前系统支持的内存读写接口
         * @return discuz_memory
         */
        function discuz_memory() {
            $this->extension['eaccelerator'] = extension_loaded('eAccelerator');
            $this->extension['xcache'] = extension_loaded('XCache');
            $this->extension['memcache'] = extension_loaded('memcache');
        }
    
        /**
         * 依据config当中设置,初始化内存引擎
         * @param unknown_type $config
         */
        function init($config) {
    
            $this->config = $config;<span style="font-family: Courier New;"><span style="color: #007700;">&nbsp;</span><span style="color: #ff8000;">//这里的$config能追溯到discuz_core的构造函数,就是把config_global.php的数据加载进来</span></span>
            $this->prefix = empty($config['prefix']) ? substr(md5($_SERVER['HTTP_HOST']), 0, 6).'_' : $config['prefix'];
            $this->keys = array();
    
            // memcache 接口
            if($this->extension['memcache'] && !empty($config['memcache']['server'])) {
                require_once libfile('class/memcache');
                $this->memory = new discuz_memcache();
                $this->memory->init($this->config['memcache']);
                if(!$this->memory->enable) {
                    $this->memory = null;
                }
            }
    
            // eaccelerator 接口
            if(!is_object($this->memory) && $this->extension['eaccelerator'] && $this->config['eaccelerator']) {
                require_once libfile('class/eaccelerator');
                $this->memory = new discuz_eaccelerator();
                $this->memory->init(null);
            }
    
            // xcache 接口
            if(!is_object($this->memory) && $this->extension['xcache'] && $this->config['xcache']) {
                require_once libfile('class/xcache');
                $this->memory = new discuz_xcache();
                $this->memory->init(null);
            }
    
            // 当接口正常,引入当前已经缓存的变量数组
            if(is_object($this->memory)) {
                $this->enable = true;
                $this->type = str_replace('discuz_', '', get_class($this->memory));
                $this->keys = $this->get('memory_system_keys');
                $this->keys = !is_array($this->keys) ? array() : $this->keys;
            }
    
        }
    
        /**
         * 读取内存
         *
         * @param string $key
         * @return mix
         */
        function get($key) {
            $ret = null;
            if($this->enable && (isset($this->keys[$key]) || $key == 'memory_system_keys')) {
                $ret = $this->memory->get($this->_key($key));
                if(!is_array($ret)) {
                    $ret = null;
                } else {
                    return $ret[0];
                }
            }
            return $ret;
        }
    
        /**
         * 写入内存
         *
         * @param string $key
         * @param array_string_number $value
         * @param int过期时间 $ttl
         * @return boolean
         */
        function set($key, $value, $ttl = 0) {
    
            $ret = null;
            if($this->enable) {
                $ret = $this->memory->set($this->_key($key), array($value), $ttl);
                if($ret) {
                    $this->keys[$key] = true;
                    $this->memory->set($this->_key('memory_system_keys'), array($this->keys));
                }
            }
            return $ret;
        }
    
        /**
         * 删除一个内存单元
         * @param 键值string $key
         * @return boolean
         */
        function rm($key) {
            $ret = null;
            if($this->enable) {
                $ret = $this->memory->rm($this->_key($key));
                if($ret) {
                    unset($this->keys[$key]);
                    $this->memory->set($this->_key('memory_system_keys'), array($this->keys));
                }
            }
            return $ret;
        }
    
        /**
         * 清除当前使用的所有内存
         */
        function clear() {
            if($this->enable && is_array($this->keys)) {
                $this->keys['memory_system_keys'] = true;
                foreach ($this->keys as $k = $v) {
                    $this->memory->rm($this->_key($k));
                }
            }
            $this->keys = array();
            return true;
        }
    
        /**
         * 内部函数 追加键值前缀
         * @param string $str
         * @return boolean
         */
        function _key($str) {
            return ($this->prefix).$str;
        }
    
    }
    

    爱J2EE关注Java迈克尔杰克逊视频站JSON在线工具

    http://biancheng.dnbcw.info/php/348684.html pageNo:3
  • 相关阅读:
    linux 总结一下git reset的各个选项吧
    深入C++的new
    Android中binderDied()以及"Unknown binder error code" 出现的原因说明
    C/C++语言void及void指针深层探索
    Android 不通过USB数据线调试的方法
    Android Browser Gallery3D无法两指手势缩放
    Android eMMC Booting
    android基础知识13:AndroidManifest.xml文件解析
    Package sunjava6jdk is not available Ubuntu 10.04 LTS 安装sunjava6jdk ,出现错误
    SQL Server 2008中Service Broker基础应用(上)
  • 原文地址:https://www.cnblogs.com/ooooo/p/2238758.html
Copyright © 2020-2023  润新知