程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> php discuz核心類函數分析

php discuz核心類函數分析

編輯:關於PHP編程


Java代碼 
<?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; 
    } 
 

 

作者“pz9042”

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved