[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]