商会资讯

 找回密码
 立即注册

QQ登录

只需一步,快速开始

用新浪微博连接

一步搞定

搜索
热搜: 活动 交友 discuz

discuzX class_core.php注释

已有 2335 次阅读2010-6-16 23:29 |个人分类:php

[code]<?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 禁止访问

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);
                if(phpversion() < '5.3.0') {
                        set_magic_quotes_runtime(0);
                }

                define('discuz_root', substr(dirname(__file__), 0, -12));
                define('magic_quotes_gpc', function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc());
                define('iconv_enable', function_exists('iconv'));
                define('mb_enable', function_exists('mb_convert_encoding'));
                define('ext_obgzip', function_exists('ob_gzhandler'));

                define('timestamp', time());
                discuz_core::timezone_set();

                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']);
                $_g['basescript'] = curscript;
                $_g['siteurl'] = htmlspecialchars('http://'.$_server['http_host'].preg_replace("/\/+(api)?\/*$/i", '', substr($_g['php_self'], 0, strrpos($_g['php_self'], '/'))).'/');

               $this->var = & $_g;

        }

        function _init_input() {

                //note 禁止对全局变量注入
                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 处理
                if(!magic_quotes_gpc) {
                        $_get = daddslashes($_get);
                        $_post = daddslashes($_post);
                        $_cookie = daddslashes($_cookie);
                        $_files = daddslashes($_files);
                }

                //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'];

                foreach(array_merge($_post, $_get) as $k => $v) {
                        $this->var['gp_'.$k] = $v;
                }

                $this->var['mod'] = empty($this->var['gp_mod']) ? '' : htmlspecialchars($this->var['gp_mod']);
                $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']));
                $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');
                }

                $_config['security']['authkey'] = empty($config['security']['authkey']) ? md5($_config['cookie']['cookiepre'].$_config['db'][1]['dbname']) : ($config['security']['authkey']);

                $this->config = & $_config;
                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;
                $globals['_g']['authkey'] = md5($this->config['security']['authkey'].$_server['http_user_agent']);
        }

        function _init_output() {

                if($this->config['security']['urlxssdefend'] && !empty($_server['request_uri'])) {
                        $temp = urldecode($_server['request_uri']);
                        if(strpos($temp, '<') !== false || strpos($temp, '"') !== false) {
                                error('request_tainting');
                        }
                }

                if($this->config['output']['gzip'] && ext_obgzip) {
                        ob_start('ob_gzhandler');
                        setglobal('gzipcompress', true);
                } else {
                        ob_start();
                        setglobal('gzipcompress', false);
                }

                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"));
                }
        }

        function _get_client_ip() {
                $clientip = '';
                if(getenv('http_client_ip') && strcasecmp(getenv('http_client_ip'), 'unknown')) {
                        $clientip = getenv('http_client_ip');
                } elseif(getenv('http_x_forwarded_for') && strcasecmp(getenv('http_x_forwarded_for'), 'unknown')) {
                        $clientip = getenv('http_x_forwarded_for');
                } 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'];
                }

                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)
                {
                        $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']['bbclosed'] && !(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 />
";
                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 {

        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);

        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);
                }
        }

        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');
                }
        }

        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 uid>0 ' : ($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'] < $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;
               $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;
        }

}

?>[/code]
收藏 分享邀请 转发到微博 举报

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 立即注册

回顶部