Home > Article > Backend Development > PHP discuz core class function analysis_PHP tutorial
Java code
/**
* [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 is the function to be completed, including banning IP and banning access
//TODO ban ip
//TODO prohibited access
///Same as DZ72, ensure that all files need to load the core file first
define('IN_DISCUZ', true);
/**
* Discuz core engine
*Variables used in other processing codes should not be set before this core new, otherwise they will be automatically cleared
*
*/
class discuz_core {
// Database storage engine
var $db = null;
// Memory buffer object
var $mem = null;
// session object
var $session = null;
// Program configuration
var $config = array();
// $_G array mapping
var $var = array();
// Load cached array
var $cachelist = array();
// Whether to initialize
var $init_setting = true; //Settings
var $init_user = true;//User
var $init_session = true;//session
var $init_cron = true;//task plan
var $init_misc = true;//Other functions
var $init_memory = true;//Memory
// Whether it has been initialized
var $initiated = 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->initiated = true;
}
Function _init_env() {
error_reporting(E_ALL ^ E_NOTICE);
// error_reporting(E_ALL);
///Prior to php 5.3, magic quote matching (automatic escaping) is turned off
If(phpversion() < '5.3.0') {
set_magic_quotes_runtime(0);
}
The main directory, is determined according to the core file. It used to be -7, which means it is under include, and now it is 12, which means it is under source/class
define('DISCUZ_ROOT', substr(dirname(__FILE__), 0, -12));
///Same as dz72, set magic quotes (automatic escaping, single and double quotes backslash)
define('MAGIC_QUOTES_GPC', function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc());
///Determine whether the character encoding conversion function exists
define('ICONV_ENABLE', function_exists('iconv'));
///Does the Asian character transcoding function exist? Because the characters starting with mb_ will be more efficient in processing Asian characters, it is initially judged that mb_ should be used for transcoding:
define('MB_ENABLE', function_exists('mb_convert_encoding'));
///Whether there is an output cache compression function, the purpose of this function is to use this function to compress all output content after confirming that the browser supports page compression, otherwise it will be transmitted directly
define('EXT_OBGZIP', function_exists('ob_gzhandler'));
///Same as DZ72, but the current timestamp is defined as a constant, which is more efficient and does not require global.
define('TIMESTAMP', time());
///Get the default time zone
discuz_core::timezone_set();
///Load function_core.php, the function is presumed to be similar to global.func.php
If(!defined('DISCUZ_CORE_FUNCTION') && !@include(DISCUZ_ROOT.'./source/function/function_core.php')) {
$this->error('function_core.php is missing');
}
//Determine whether the browser is a spider
define('IS_ROBOT', checkrobot());
//Clear global variables
///It’s all cleaned up, all variables have been completely unregistered from the memory
foreach ($GLOBALS as $key = $value) {
If (!isset($this->superglobal[$key])) {
$GLOBALS[$key] = null; unset($GLOBALS[$key]);
}
// Configure global variables
///Combined with the previous step, leave only the variables you need and initialize them.
This is ruthless, as long as you are a little careful, there will be no security issues caused by uninitialized variables
global $_G;
$_G = array(
//Public global definition
'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']);
//Basic script name, which will be defined before the homepage of each functional script
//For example, forum.php, define CURSCRIPT as forum, but forum_forumdisplay.php is not defined because it belongs to forum
$_G['basescript'] = CURSCRIPT;
//Site URL
$_G['siteurl'] = htmlspecialchars('http://'.$_SERVER['HTTP_HOST'].preg_replace("//+(api)?/*$/i", '', substr($_G[ 'PHP_SELF'], 0, strrpos($_G['PHP_SELF'], '/'))).'/');
///Map of $_G, that is, super global variable
$this->var = & $_G;
}
Function _init_input() {
//note Injection of global variables is prohibited
///Similar to dz72, injection using GLOBALS=xxx is prohibited
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 processing, if there is no magic quote processing (automatic escaping), manually escape single and double quotes and null backslashes in GET/POST/COOKIE/FILES
If(!MAGIC_QUOTES_GPC) {
$_GET = daddslashes($_GET);
$_POST = daddslashes($_POST);
$_COOKIE = daddslashes($_COOKIE);
$_FILES = daddslashes($_FILES);
}
//Cookie processing
///Verify whether the cookie prefix is consistent with the setting value in config. If they are consistent, it will be converted to the value in the $cookie array
$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 and $_POST are converted into variables with the same name as the index plus the "gp_" prefix
///For example, $_GET['username'] directly uses $gp_username to access
foreach(array_merge($_POST, $_GET) as $k = $v) {
$this->var['gp_'.$k] = $v;
}
///Determine the value of m based on $_GET['mod'], $this->var is the global array, gp_ is the additional prefix of the previous statement
$this->var['mod'] = empty($this->var['gp_mod']) ? '' : htmlspecialchars($this->var['gp_mod']);
///If you use ajax, then judge whether the post value is passed or the get and xmlhttprequest are valid at the same time
$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);
///Current page number
$this->var['page'] = empty($this->var['gp_page']) ? 1 : max(1, intval($this->var['gp_page']));
///Determine the sid value in the cookie
$this->var['sid'] = $this->var['cookie']['sid'] = isset($this->var['cookie']['sid']) ? htmlspecialchars ($this->var['cookie']['sid']) : '';
}
///Initialization settings
Function _init_config() {
///Load settings file
$_config = array();
@include DISCUZ_ROOT.'./config/config_global.php';
If(empty($_config)) {
error('config_notfound');
}
///Determine the key. If the value is empty, the key defaults to the md5 value of the cookie prefix and the database name, otherwise it is the value in the configuration file
///The authkey key is an important parameter for encryption and decryption of sid and other parameters
$_config['security']['authkey'] = empty($config['security']['authkey']) ? md5($_config['cookie']['cookiepre'].$_config['db' ][1]['dbname']) : ($config['security']['authkey']);
$this->config = & $_config;
///Debugging of 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;
///Use the browser version as a reference to perform secondary md5 encryption of the key
$GLOBALS['_G']['authkey'] = md5($this->config['security']['authkey'].$_SERVER['HTTP_USER_AGENT']);
}
Function _init_output() {
///If the xss cross-site scripting defense mode is turned on in the settings and there are illegal characters such as "<" and """ in the URL, the request will be rejected
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 ob_gzhandler exists, output cache compression is enabled
If($this->config['output']['gzip'] && EXT_OBGZIP) {
ob_start('ob_gzhandler');
setglobal('gzipcompress', true);
} else {
ob_start();
setglobal('gzipcompress', false);
}
///Determine the HTML page encoding and other encodings
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']);
}
///Deny robot access
Function reject_robot() {
If(IS_ROBOT) {
exit(header("HTTP/1.1 403 Forbidden"));
}
}
///Get client ip,
Function _get_client_ip() {
$clientip = '';
///If the environment variable client ip has a value and the character length is greater than unknown, it means that the variable is valid and is determined to be the client ip
If(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
$clientip = getenv('HTTP_CLIENT_IP');
///Otherwise, get the gateway IP address of the current browsing user
} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
$clientip = getenv('HTTP_X_FORWARDED_FOR');
///The IP address of the user’s computer
} 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'];
}
///Determine whether it is a 7-15 character composed of numbers and dots
Preg_match("/[d.]{7,15}/", $clientip, $clientipmatches);
$clientip = $clientipmatches[0] ? $clientipmatches[0] : 'unknown';
return $clientip;
}
Function _init_db() {
///Generate database object
$this->db = & DB::object();
///Load the setting file and connect to the database
$this->db->set_config($this->config['db']);
$this->db->connect();
}
Function _init_session() {
$this->session = new discuz_session();
If($this->init_session)
///Incoming sid, client ip and uid are used as the session judgment mechanism to classify new and old users. For old users, check the session table, otherwise create
$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);
// Update the last access time when logging in for the first time, and update the user’s last action time every 10 minutes
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;
Update membership status
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 support
*
*/
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 = '
File | Line | Function |
$error[file] | $error[line] | $error[class]$error[type]$error[function]() |