[zz]discuzX1核心资料class_core.php分析

WBOY
Lepaskan: 2016-06-13 11:03:12
asal
980 orang telah melayarinya

[zz]discuzX1核心文件class_core.php分析

/*Discuz!X 核心文件class_core.php分析
Salin selepas log masuk
2010-08-24 10:20在研究DISCUZ!X核心文件class_core.php时作的DISCUZ!X产品相较之前版本的底层机制上的变化分析及源码部分注释。___________________________________________
Salin selepas log masuk
我今天花了1个多小时,阅读了下class_core.php,DB数据库和cron任务计划没看。总体感觉,比起dz72来说,各项机制和体系都有所增强,变化相当大。【1】最明显的一点是,核心体系基本都用类进行封装了,架构清晰,使用起来相对简易,基本的架构类似Ucenter,但略有增强。【2】安全机制进一步加强,特别是GLOBALS超级全局变量的注销,及各变量的初始化,让人印象深刻。【3】原来的GPC和session机制,大体变化不算很大,但进行了一些优化和增强,考虑得更全面了。不过新版清晰与普通变量进行了区隔,如get、 post用 gp_,而cookie用$cookie数组,而session用$session。【4】功能上,基本上原有的客户端ip、机器人判断、转义、gzhandler、对xss跨站攻击的基本防御、缓存丢失判断等基本上差别不算太大。【5】增加了memory内存读写引擎,支持memcache、xcache,eAccelerator。【6】在原有session机制处理逻辑基础上,精简了一部分实现,重新自定义并增强了SESSION机制,代码的写法与结构与memory写法类似。但具体效果有待验证。
Salin selepas log masuk
附随笔作的注释大家将就看吧*/
Salin selepas log masuk
<?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() 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 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跨站脚本的防御模式,且网址中存在"config['security']['urlxssdefend'] && !empty($_SERVER['REQUEST_URI'])) {            $temp = urldecode($_SERVER['REQUEST_URI']);            if(strpos($temp, '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) 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) 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'] 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 = '
Salin selepas log masuk
'; 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 .= ""; } $phperror .= '
File Line Function
$error[file] $error[line] $error[class]$error[type]$error[function]()
'; $helplink = "http://faq.comsenz.com/?type=mysql&dberrno=".rawurlencode($dberrno)."&dberror=".rawurlencode($dberror); @header('Content-Type: text/html; charset='.$_G['config']['output']['charset']); echo '
'. 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 "PHP Backtrace
$phperror
"; 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 lastactivityvar['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'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 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'] $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'] 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 expiryextension['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;?//这里的$config能追溯到discuz_core的构造函数,就是把config_global.php的数据加载进来 $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; }}

?

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan