[PHP] 純文本查看 復(fù)制代碼
<?php
/**
* [Discuz!] (C)2001-2099 Comsenz Inc.
* This is NOT a freeware, use is subject to license terms
*
* $Id: function_core.php 36342 2017-01-09 01:15:30Z nemohou $
*/
if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
define('DISCUZ_CORE_FUNCTION', true);
function durlencode($url) {
static $fix = array('%21', '%2A','%3B', '%3A', '%40', '%26', '%3D', '%2B', '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D');
static $replacements = array('!', '*', ';', ":", "@", "&", "=", "+", "$", ",", "/", "?", "%", "#", "[", "]");
return str_replace($fix, $replacements, urlencode($url));
}
function system_error($message, $show = true, $save = true, $halt = true) {
discuz_error::system_error($message, $show, $save, $halt);
}
function updatesession() {
return C::app()->session->updatesession();
}
/**
* 設(shè)置全局變量
* @param string $key 變量的鍵名,如果提供了$group,則為$group下的鍵名
* @param mixed $value 要設(shè)置的變量的值
* @param string|null $group 可選,變量所屬的組,如果不提供,則直接設(shè)置在全局變量中
* @return bool 總是返回true
*/
function setglobal($key , $value, $group = null) {
global $_G;
$key = explode('/', $group === null ? $key : $group.'/'.$key);
$p = &$_G;
foreach ($key as $k) {
if(!isset($p[$k]) || !is_array($p[$k])) {
$p[$k] = array();
}
$p = &$p[$k];
}
$p = $value;
return true;
}
/**
* 獲取全局變量的值
* @param string $key 變量的鍵名,如果提供了$group,則為$group下的鍵名
* @param string|null $group 可選,變量所屬的組,如果不提供,則直接從全局變量中獲取
* @return mixed 返回變量的值,如果未找到則返回null
*/
function getglobal($key, $group = null) {
global $_G;
$key = explode('/', $group === null ? $key : $group.'/'.$key);
$v = &$_G;
foreach ($key as $k) {
if (!isset($v[$k])) {
return null;
}
$v = &$v[$k];
}
return $v;
}
/**
* 獲取GET、POST或COOKIE變量的值,或者根據(jù)優(yōu)先級(jí)獲取GET或POST變量的值
* @param string $k 變量名
* @param string $type 可選,變量來源類型,'G'代表GET,'P'代表POST,'C'代表COOKIE,默認(rèn)為'GP',即先嘗試GET再嘗試POST
* @return mixed 返回變量的值,如果未找到則返回NULL
*/
function getgpc($k, $type='GP') {
$type = strtoupper($type);
switch($type) {
case 'G': $var = &$_GET; break;
case 'P': $var = &$_POST; break;
case 'C': $var = &$_COOKIE; break;
default:
if(isset($_GET[$k])) {
$var = &$_GET;
} else {
$var = &$_POST;
}
break;
}
return isset($var[$k]) ? $var[$k] : NULL;
}
/**
* 簡單獲取GET變量的值
* @param string $k 變量名
* @return mixed 返回GET變量的值,如果未找到則返回null
*/
function dget($k) {
return isset($_GET[$k]) ? $_GET[$k] : null;
}
/**
* 簡單獲取POST變量的值
* @param string $k 變量名
* @return mixed 返回POST變量的值,如果未找到則返回null
*/
function dpost($k) {
return isset($_POST[$k]) ? $_POST[$k] : null;
}
/**
* 根據(jù)用戶ID獲取用戶信息
* @param int $uid 用戶ID
* @param int $fetch_archive 可選,是否獲取歸檔信息,0為不獲取,1為僅獲取歸檔信息,2為同時(shí)獲取當(dāng)前和歸檔信息
* @return array 包含用戶信息的數(shù)組,如果用戶不存在則返回空數(shù)組
*/
function getuserbyuid($uid, $fetch_archive = 0) {
static $users = array();
if(empty($users[$uid])) {
$users[$uid] = C::t('common_member'.($fetch_archive === 2 ? '_archive' : ''))->fetch($uid);
if($fetch_archive === 1 && empty($users[$uid])) {
$users[$uid] = C::t('common_member_archive')->fetch($uid);
}
}
if(!isset($users[$uid]['self']) && $uid == getglobal('uid') && getglobal('uid')) {
$users[$uid]['self'] = 1;
}
return $users[$uid];
}
/**
* 獲取用戶的特定字段信息
* @param string $field 需要獲取的字段名
* @return mixed 返回字段的值,如果未找到或者全局變量未設(shè)置則返回null
*/
function getuserprofile($field) {
global $_G;
if(isset($_G['member'][$field])) {
return $_G['member'][$field];
}
static $tablefields = array(
'count' => array('extcredits1','extcredits2','extcredits3','extcredits4','extcredits5','extcredits6','extcredits7','extcredits8','friends','posts','threads','digestposts','doings','blogs','albums','sharings','attachsize','views','oltime','todayattachs','todayattachsize', 'follower', 'following', 'newfollower', 'blacklist'),
'status' => array('regip','lastip','lastvisit','lastactivity','lastpost','lastsendmail','invisible','buyercredit','sellercredit','favtimes','sharetimes','profileprogress'),
'field_forum' => array('publishfeed','customshow','customstatus','medals','sightml','groupterms','authstr','groups','attentiongroup'),
'field_home' => array('spacename','spacedescription','domain','addsize','addfriend','menunum','theme','spacecss','blockposition','recentnote','spacenote','privacy','feedfriend','acceptemail','magicgift','stickblogs'),
'profile' => array('realname','gender','birthyear','birthmonth','birthday','constellation','zodiac','telephone','mobile','idcardtype','idcard','address','zipcode','nationality','birthcountry','birthprovince','birthcity','residecountry','resideprovince','residecity','residedist','residecommunity','residesuite','graduateschool','company','education','occupation','position','revenue','affectivestatus','lookingfor','bloodtype','height','weight','alipay','icq','qq','yahoo','msn','taobao','site','bio','interest','field1','field2','field3','field4','field5','field6','field7','field8'),
'verify' => array('verify1', 'verify2', 'verify3', 'verify4', 'verify5', 'verify6'),
);
$profiletable = '';
foreach($tablefields as $table => $fields) {
if(in_array($field, $fields)) {
$profiletable = $table;
break;
}
}
if($profiletable) {
if(is_array($_G['member']) && $_G['member']['uid']) {
space_merge($_G['member'], $profiletable);
} else {
foreach($tablefields[$profiletable] as $k) {
$_G['member'][$k] = '';
}
}
return $_G['member'][$field];
}
return null;
}
/**
* 對(duì)字符串進(jìn)行添加反斜杠處理
*
* @param string $string 需要處理的字符串
* @param int $force 強(qiáng)制執(zhí)行標(biāo)志,默認(rèn)為1
* @return string 添加反斜杠后的字符串
*/
function daddslashes($string, $force = 1) {
// 如果輸入的是數(shù)組,則遞歸處理數(shù)組中的每個(gè)元素
if(is_array($string)) {
$keys = array_keys($string);
foreach($keys as $key) {
$val = $string[$key];
unset($string[$key]);
$string[addslashes($key)] = daddslashes($val, $force);
}
} else {
// 對(duì)字符串添加反斜杠
$string = addslashes($string);
}
return $string;
}
/**
* 對(duì)字符串進(jìn)行編碼或者解碼
*
* @param string $string 需要編碼或解碼的字符串
* @param string $operation 操作類型,默認(rèn)為'DECODE'解碼
* @param string $key 加密解密使用的密鑰
* @param int $expiry 過期時(shí)間,默認(rèn)為0,表示不設(shè)置過期
* @return string 編碼或解碼后的字符串
*/
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
// 初始化變量和加密密鑰
$ckey_length = 4;
$key = md5($key != '' ? $key : getglobal('authkey'));
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
// 根據(jù)操作類型進(jìn)行編碼或解碼
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
// 應(yīng)用RC4加密算法
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
// 根據(jù)操作類型返回解碼后的字符串或編碼后的字符串
if($operation == 'DECODE') {
if(((int)substr($result, 0, 10) == 0 || (int)substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) === substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc.str_replace('=', '', base64_encode($result));
}
}
/**
* 嘗試使用多種方法打開與服務(wù)器的Socket連接
*
* @param string $hostname 目標(biāo)主機(jī)名
* @param int $port 端口號(hào),默認(rèn)為80
* @param int &$errno 用于存儲(chǔ)錯(cuò)誤碼的引用
* @param string &$errstr 用于存儲(chǔ)錯(cuò)誤信息的引用
* @param int $timeout 連接超時(shí)時(shí)間,默認(rèn)為15秒
* @return resource 返回Socket連接的文件指針,失敗返回false
*/
function fsocketopen($hostname, $port = 80, &$errno = null, &$errstr = null, $timeout = 15) {
$fp = '';
// 嘗試使用多種函數(shù)打開Socket連接
if(function_exists('fsockopen')) {
$fp = @fsockopen($hostname, $port, $errno, $errstr, $timeout);
} elseif(function_exists('pfsockopen')) {
$fp = @pfsockopen($hostname, $port, $errno, $errstr, $timeout);
} elseif(function_exists('stream_socket_client')) {
$fp = @stream_socket_client($hostname.':'.$port, $errno, $errstr, $timeout);
}
return $fp;
}
/**
* 打開一個(gè)網(wǎng)絡(luò)連接,功能與fsocketopen相似,但提供了更多的選項(xiàng)和靈活性
*
* @param string $url 請求的URL地址
* @param int $limit 下載限制,默認(rèn)為0表示無限制
* @param string $post 提交的POST數(shù)據(jù),默認(rèn)為空
* @param string $cookie 攜帶的Cookie信息,默認(rèn)為空
* @param bool $bysocket 是否通過Socket連接,默認(rèn)為FALSE
* @param string $ip 目標(biāo)IP地址,默認(rèn)為空,用于指定連接的IP地址
* @param int $timeout 連接超時(shí)時(shí)間,默認(rèn)為15秒
* @param bool $block 是否使用阻塞模式,默認(rèn)為TRUE
* @param string $encodetype 提交數(shù)據(jù)的編碼方式,默認(rèn)為'URLENCODE'
* @param bool $allowcurl 是否允許使用cURL,默認(rèn)為TRUE
* @param int $position 文件下載的起點(diǎn)位置,默認(rèn)為0開始下載
* @param array $files 用于存儲(chǔ)上傳文件信息的數(shù)組,默認(rèn)為空數(shù)組
* @return mixed 返回文件指針或者FALSE(在出錯(cuò)時(shí))
*/
function dfsockopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE, $encodetype = 'URLENCODE', $allowcurl = TRUE, $position = 0, $files = array()) {
// 要求先引入filesock函數(shù)文件
require_once libfile('function/filesock');
return _dfsockopen($url, $limit, $post, $cookie, $bysocket, $ip, $timeout, $block, $encodetype, $allowcurl, $position, $files);
}
/**
* 將字符串中的特殊字符轉(zhuǎn)為HTML實(shí)體
*
* @param string $string 需要轉(zhuǎn)換的字符串
* @param int $flags HTML實(shí)體轉(zhuǎn)換的標(biāo)志位,默認(rèn)為null
* @return string 轉(zhuǎn)換后的字符串
*/
function dhtmlspecialchars($string, $flags = null) {
// 如果輸入是數(shù)組,則遞歸處理數(shù)組中的每個(gè)元素
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = dhtmlspecialchars($val, $flags);
}
} else {
// 如果沒有指定標(biāo)志位,則進(jìn)行簡單的字符替換
if($flags === null) {
$string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string);
} else {
// 根據(jù)PHP版本和字符集設(shè)置進(jìn)行不同的HTML實(shí)體轉(zhuǎn)換
if(PHP_VERSION < '5.4.0') {
$string = htmlspecialchars($string, $flags);
} else {
// 根據(jù)字符集確定使用的HTML實(shí)體轉(zhuǎn)換字符集
if(strtolower(CHARSET) == 'utf-8') {
$charset = 'UTF-8';
} else {
$charset = 'ISO-8859-1';
}
$string = htmlspecialchars($string, $flags, $charset);
}
}
}
return $string;
}
/**
* 輸出消息并退出
*
* @param string $message 要輸出的消息,默認(rèn)為空
*/
function dexit($message = '') {
echo $message;
output(); // 執(zhí)行輸出函數(shù)
exit(); // 退出程序
}
/**
* 發(fā)送HTTP頭信息
*
* @param string $string 要發(fā)送的頭信息
* @param bool $replace 是否替換之前的同類頭信息,默認(rèn)為true
* @param int $http_response_code HTTP響應(yīng)代碼,默認(rèn)為0
*/
function dheader($string, $replace = true, $http_response_code = 0) {
// 檢查是否是重定向,并且是否是在移動(dòng)版中,如果是則添加移動(dòng)參數(shù)
$islocation = substr(strtolower(trim($string)), 0, 8) == 'location';
if(defined('IN_MOBILE') && strpos($string, 'mobile') === false && $islocation) {
if (strpos($string, '?') === false) {
$string = $string.'?mobile='.IN_MOBILE;
} else {
if(strpos($string, '#') === false) {
$string = $string.'&mobile='.IN_MOBILE;
} else {
$str_arr = explode('#', $string);
$str_arr[0] = $str_arr[0].'&mobile='.IN_MOBILE;
$string = implode('#', $str_arr);
}
}
}
// 去除頭信息中的換行和回車字符
$string = str_replace(array("\r", "\n"), array('', ''), $string);
// 根據(jù)PHP版本發(fā)送頭信息
if(empty($http_response_code) || PHP_VERSION < '4.3' ) {
@header($string, $replace);
} else {
@header($string, $replace, $http_response_code);
}
// 如果是重定向,則退出程序
if($islocation) {
exit();
}
}
/**
* 設(shè)置Cookie
*
* @param string $var Cookie的名稱
* @param string $value Cookie的值,默認(rèn)為空
* @param int $life Cookie的生命周期,默認(rèn)為0
* @param int $prefix Cookie名稱是否添加前綴,默認(rèn)為1(添加前綴)
* @param bool $httponly 是否僅通過HTTP協(xié)議訪問Cookie,默認(rèn)為false
*/
function dsetcookie($var, $value = '', $life = 0, $prefix = 1, $httponly = false) {
global $_G;
$config = $_G['config']['cookie'];
// 設(shè)置全局Cookie變量和$_COOKIE數(shù)組
$_G['cookie'][$var] = $value;
$var = ($prefix ? $config['cookiepre'] : '').$var;
$_COOKIE[$var] = $value;
// 處理Cookie值為空或生命周期為負(fù)的情況
if($value === '' || $life < 0) {
$value = '';
$life = -1;
}
// 在移動(dòng)版中強(qiáng)制不使用HttpOnly
if(defined('IN_MOBILE')) {
$httponly = false;
}
// 計(jì)算Cookie的過期時(shí)間
$life = $life > 0 ? getglobal('timestamp') + $life : ($life < 0 ? getglobal('timestamp') - 31536000 : 0);
// 根據(jù)PHP版本和是否使用HttpOnly設(shè)置Cookie路徑
$path = $httponly && PHP_VERSION < '5.2.0' ? $config['cookiepath'].'; HttpOnly' : $config['cookiepath'];
$secure = $_G['isHTTPS'];
// 根據(jù)PHP版本調(diào)用不同的setcookie方法
if(PHP_VERSION < '5.2.0') {
setcookie($var, $value, $life, $path, $config['cookiedomain'], $secure);
} else {
setcookie($var, $value, $life, $path, $config['cookiedomain'], $secure, $httponly);
}
}
/**
* 獲取指定Cookie的值
*
* @param string $key Cookie的名稱
* @return string 指定Cookie的值,如果未設(shè)置則返回空字符串
*/
function getcookie($key) {
global $_G;
return isset($_G['cookie'][$key]) ? $_G['cookie'][$key] : '';
}
/**
* 獲取文件的擴(kuò)展名
*
* @param string $filename 文件名稱
* @return string 文件擴(kuò)展名,帶有點(diǎn)號(hào)(.)
*/
function fileext($filename) {
return addslashes(strtolower(substr(strrchr($filename, '.'), 1, 10)));
}
/**
* 生成表單哈希值
* @param string $specialadd 特殊添加內(nèi)容,默認(rèn)為空,會(huì)加入到哈希值計(jì)算中
* @return string 返回8位的哈希值
*/
function formhash($specialadd = '') {
global $_G;
// 如果是在后臺(tái)管理頁面,添加特定字符串到哈希值中
$hashadd = defined('IN_ADMINCP') ? 'Only For Discuz! Admin Control Panel' : '';
return substr(md5(substr($_G['timestamp'], 0, -7).$_G['username'].$_G['uid'].$_G['authkey'].$hashadd.$specialadd), 8, 8);
}
/**
* 檢查訪問者是否為機(jī)器人
* @param string $useragent 用戶代理字符串,默認(rèn)為空,為空時(shí)使用服務(wù)器變量HTTP_USER_AGENT
* @return bool 返回true表示可能是機(jī)器人,返回false表示不是機(jī)器人
*/
function checkrobot($useragent = '') {
static $kw_spiders = array('bot', 'crawl', 'spider' ,'slurp', 'sohu-search', 'lycos', 'robozilla'); // 機(jī)器人關(guān)鍵詞
static $kw_browsers = array('msie', 'netscape', 'opera', 'konqueror', 'mozilla'); // 瀏覽器關(guān)鍵詞
$useragent = strtolower(empty($useragent) ? $_SERVER['HTTP_USER_AGENT'] : $useragent);
// 檢查是否包含機(jī)器人關(guān)鍵詞
if(dstrpos($useragent, $kw_spiders)) return true;
// 檢查是否為純?yōu)g覽器訪問(不包含http://)且是否為指定瀏覽器
if(strpos($useragent, 'http://') === false && dstrpos($useragent, $kw_browsers)) return false;
return false;
}
/**
* 檢查是否為移動(dòng)設(shè)備訪問
* @return bool|mixed 返回false表示不是移動(dòng)設(shè)備,返回'2'表示觸摸屏設(shè)備,返回'3'表示W(wǎng)ML版本設(shè)備,返回true表示未知移動(dòng)設(shè)備
*/
function checkmobile() {
global $_G;
$mobile = array();
static $touchbrowser_list =array('iphone', 'android', 'phone', 'mobile', 'wap', 'netfront', 'java', 'opera mobi', 'opera mini',
'ucweb', 'windows ce', 'symbian', 'series', 'webos', 'sony', 'blackberry', 'dopod', 'nokia', 'samsung',
'palmsource', 'xda', 'pieplus', 'meizu', 'midp', 'cldc', 'motorola', 'foma', 'docomo', 'up.browser',
'up.link', 'blazer', 'helio', 'hosin', 'huawei', 'novarra', 'coolpad', 'webos', 'techfaith', 'palmsource',
'alcatel', 'amoi', 'ktouch', 'nexian', 'ericsson', 'philips', 'sagem', 'wellcom', 'bunjalloo', 'maui', 'smartphone',
'iemobile', 'spice', 'bird', 'zte-', 'longcos', 'pantech', 'gionee', 'portalmmm', 'jig browser', 'hiptop',
'benq', 'haier', '^lct', '320x320', '240x320', '176x220', 'windows phone');
static $wmlbrowser_list = array('cect', 'compal', 'ctl', 'lg', 'nec', 'tcl', 'alcatel', 'ericsson', 'bird', 'daxian', 'dbtel', 'eastcom',
'pantech', 'dopod', 'philips', 'haier', 'konka', 'kejian', 'lenovo', 'benq', 'mot', 'soutec', 'nokia', 'sagem', 'sgh',
'sed', 'capitel', 'panasonic', 'sonyericsson', 'sharp', 'amoi', 'panda', 'zte');
static $pad_list = array('ipad');
$useragent = strtolower($_SERVER['HTTP_USER_AGENT']);
// 檢查是否為平板設(shè)備
if(dstrpos($useragent, $pad_list)) {
return false;
}
// 檢查是否為觸摸屏設(shè)備
if(($v = dstrpos($useragent, $touchbrowser_list, true))){
$_G['mobile'] = $v;
return '2';
}
// 檢查是否為WML版本瀏覽器設(shè)備
if(($v = dstrpos($useragent, $wmlbrowser_list))) {
$_G['mobile'] = $v;
return '3'; //wml版
}
// 檢查是否為其他瀏覽器,若是則返回false
$brower = array('mozilla', 'chrome', 'safari', 'opera', 'm3gate', 'winwap', 'openwave');
if(dstrpos($useragent, $brower)) return false;
$_G['mobile'] = 'unknown';
// 檢查是否啟用了特定的移動(dòng)模板
if(isset($_G['mobiletpl'][$_GET['mobile']])) {
return true;
} else {
return false;
}
}
/**
* 檢查字符串中是否包含數(shù)組中的任何一個(gè)子串,如果找到返回true或返回指定的值
* @param string $string 要搜索的字符串
* @param array $arr 包含要搜索的子串的數(shù)組
* @param bool $returnvalue 如果找到子串,是否返回該子串,默認(rèn)為false,返回true
* @return bool|string 如果找到返回true或指定的值,未找到返回false
*/
function dstrpos($string, $arr, $returnvalue = false) {
if(empty($string)) return false;
foreach((array)$arr as $v) {
if(strpos($string, $v) !== false) {
$return = $returnvalue ? $v : true;
return $return;
}
}
return false;
}
/**
* 驗(yàn)證郵箱格式是否正確
* @param string $email 需要驗(yàn)證的郵箱地址
* @return bool 返回true表示郵箱格式正確,返回false表示郵箱格式錯(cuò)誤
*/
function isemail($email) {
return strlen($email) > 6 && strlen($email) <= 255 && preg_match("/^([A-Za-z0-9\-_.+]+)@([A-Za-z0-9\-]+[.][A-Za-z0-9\-.]+)$/", $email);
}
/**
* 生成指定長度的隨機(jī)字符串
* @param int $length 隨機(jī)字符串的長度
* @param int $numeric 是否僅生成數(shù)字,默認(rèn)為0,如果為1則僅生成數(shù)字,為0則生成數(shù)字和字母的混合串
* @return string 返回生成的隨機(jī)字符串
*/
function random($length, $numeric = 0) {
$seed = base_convert(md5(microtime().$_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
$seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed));
if($numeric) {
$hash = '';
} else {
$hash = chr(rand(1, 26) + rand(0, 1) * 32 + 64);
$length--;
}
$max = strlen($seed) - 1;
for($i = 0; $i < $length; $i++) {
$hash .= $seed[mt_rand(0, $max)];
}
return $hash;
}
/**
* 生成指定長度的隨機(jī)字符串
*
* @param int $length 需要生成的隨機(jī)字符串的長度
* @param int $numeric 是否只生成數(shù)字,0為否,非0為是
* @param bool $strong 是否生成強(qiáng)隨機(jī)數(shù),true為強(qiáng)隨機(jī),false為普通隨機(jī)
* @return string|bool 生成的隨機(jī)字符串或在無法生成強(qiáng)隨機(jī)數(shù)且$strong為true時(shí)返回false
*/
function secrandom($length, $numeric = 0, $strong = false) {
// 初始化字符集
$chars = $numeric ? array('A','B','+','/','=') : array('+','/','=');
// 數(shù)字替代字符集
$num_find = str_split('CDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
$num_repl = str_split('01234567890123456789012345678901234567890123456789');
// 判斷是否支持強(qiáng)隨機(jī)數(shù)生成
$isstrong = false;
if(function_exists('random_bytes')) {
$isstrong = true;
// 使用random_bytes生成隨機(jī)數(shù)
$random_bytes = function($length) {
return random_bytes($length);
};
} elseif(extension_loaded('mcrypt') && function_exists('mcrypt_create_iv')) {
$isstrong = true;
// 使用mcrypt_create_iv生成隨機(jī)數(shù)
$random_bytes = function($length) {
$rand = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
if ($rand !== false && strlen($rand) === $length) {
return $rand;
} else {
return false;
}
};
} elseif(extension_loaded('openssl') && function_exists('openssl_random_pseudo_bytes')) {
$isstrong = true;
// 使用openssl_random_pseudo_bytes生成隨機(jī)數(shù)
$random_bytes = function($length) {
$rand = openssl_random_pseudo_bytes($length, $secure);
if($secure === true) {
return $rand;
} else {
return false;
}
};
}
if(!$isstrong) {
// 不支持強(qiáng)隨機(jī)數(shù)時(shí)的處理
return $strong ? false : random($length, $numeric);
}
// 嘗試生成隨機(jī)字符串
$retry_times = 0;
$return = '';
while($retry_times < 128) {
$getlen = $length - strlen($return); // 為保證隨機(jī)性,可能會(huì)多生成一些字節(jié)
$bytes = $random_bytes(max($getlen, 12));
if($bytes === false) {
return false;
}
// 去除可能包含的特殊字符,避免解碼問題
$bytes = str_replace($chars, '', base64_encode($bytes));
$return .= substr($bytes, 0, $getlen);
if(strlen($return) == $length) {
// 根據(jù)是否只生成數(shù)字返回相應(yīng)的結(jié)果
return $numeric ? str_replace($num_find, $num_repl, $return) : $return;
}
$retry_times++;
}
}
/**
* 檢查字符串中是否存在指定的子字符串
*
* @param string $string 主字符串
* @param string $find 待查找的子字符串
* @return bool 子字符串存在返回true,否則返回false
*/
function strexists($string, $find) {
return !(strpos($string, $find) === FALSE);
}
/**
* 生成用戶頭像URL或HTML標(biāo)簽
*
* @param int $uid 用戶ID
* @param string $size 頭像大小,可選:'big', 'middle', 'small',默認(rèn)為'middle'
* @param int|array $returnsrc 如果為1,則只返回URL;如果為數(shù)組,則允許通過數(shù)組設(shè)置額外參數(shù)
* @param bool $real 是否返回真實(shí)頭像地址
* @param bool $static 是否使用靜態(tài)地址
* @param string $ucenterurl UCenter的URL
* @param string $class 圖片HTML標(biāo)簽的class屬性
* @param string $extra 圖片HTML標(biāo)簽的額外屬性
* @param int $random 是否添加隨機(jī)參數(shù)以強(qiáng)制刷新緩存
* @return string 返回頭像的URL或HTML標(biāo)簽
*/
function avatar($uid, $size = 'middle', $returnsrc = 0, $real = FALSE, $static = FALSE, $ucenterurl = '', $class = '', $extra = '', $random = 0) {
global $_G;
// 檢查插件中是否有自定義的頭像函數(shù)
if(!empty($_G['setting']['plugins']['func'][HOOKTYPE]['avatar']) && !defined('IN_ADMINCP')) {
$_G['hookavatar'] = '';
$param = func_get_args();
hookscript('avatar', 'global', 'funcs', array('param' => $param), 'avatar');
if($_G['hookavatar']) {
return $_G['hookavatar'];
}
}
// 解析傳入的$returnsrc參數(shù)
if(is_array($returnsrc)) {
$random = isset($returnsrc['random']) ? $returnsrc['random'] : 0;
$extra = isset($returnsrc['extra']) ? $returnsrc['extra'] : '';
$class = isset($returnsrc['class']) ? $returnsrc['class'] : '';
$ucenterurl = isset($returnsrc['ucenterurl']) ? $returnsrc['ucenterurl'] : '';
$static = isset($returnsrc['static']) ? $returnsrc['static'] : FALSE;
$real = isset($returnsrc['real']) ? $returnsrc['real'] : FALSE;
$returnsrc = isset($returnsrc['returnsrc']) ? $returnsrc['returnsrc'] : 0;
}
// 靜態(tài)頭像開關(guān)
static $staticavatar;
if($staticavatar === null) {
$staticavatar = $_G['setting']['avatarmethod'];
}
// 頭像存在性緩存
static $avtstatus;
if($avtstatus === null) {
$avtstatus = array();
}
// 動(dòng)態(tài)頭像配置
$dynavt = intval($_G['setting']['dynavt']);
// 處理UCenter URL
$ucenterurl = empty($ucenterurl) ? $_G['setting']['ucenterurl'] : $ucenterurl;
// 處理頭像URL
$avatarurl = empty($_G['setting']['avatarurl']) ? $ucenterurl.'/data/avatar' : $_G['setting']['avatarurl'];
// 規(guī)范化頭像大小參數(shù)
$size = in_array($size, array('big', 'middle', 'small')) ? $size : 'middle';
// 格式化用戶ID
$uid = abs(intval($uid));
$rawuid = $uid;
// 生成UCenter頭像地址
if(!$staticavatar && !$static && $ucenterurl != '.') {
if($avatarurl != $ucenterurl.'/data/avatar') {
$ucenterurl = $avatarurl;
}
$trandom = '';
if($random == 1) {
$trandom = '&random=1';
} elseif($dynavt == 2 || ($dynavt == 1 && $uid == $_G['uid']) || $random == 2) {
$trandom = '&ts=1';
}
if($returnsrc) {
return $ucenterurl.'/avatar.php?uid='.$uid.'&size='.$size.($real ? '&type=real' : '').$trandom;
} else {
return '<img src="'.$ucenterurl.'/avatar.php?uid='.$uid.'&size='.$size.($real ? '&type=real' : '').$trandom.'"'.($class ? ' class="'.$class.'"' : '').($extra ? ' '.$extra : '').'>';
}
} else {
// 生成本地頭像地址
$uid = sprintf("%09d", $uid);
$dir1 = substr($uid, 0, 3);
$dir2 = substr($uid, 3, 2);
$dir3 = substr($uid, 5, 2);
$filepath = $dir1.'/'.$dir2.'/'.$dir3.'/'.substr($uid, -2).($real ? '_real' : '').'_avatar_'.$size.'.jpg';
$file = $avatarurl.'/'.$filepath;
$noavt = $avatarurl.'/noavatar.svg';
$trandom = '';
$avtexist = -1;
if(!$staticavatar && !$static) {
$avatar_file = DISCUZ_ROOT.$_G['setting']['avatarpath'].$filepath;
if(isset($avtstatus[$rawuid])) {
$avtexist = $avtstatus[$rawuid][0];
} else {
$avtexist = file_exists($avatar_file) ? 1 : 0;
$avtstatus[$rawuid][0] = $avtexist;
}
if($avtexist) {
if($dynavt == 2 || ($dynavt == 1 && $rawuid && $rawuid == $_G['uid']) || $random == 2) {
if(empty($avtstatus[$rawuid][1])) {
$avtstatus[$rawuid][1] = filemtime($avatar_file);
}
$trandom = '?ts='.$avtstatus[$rawuid][1];
}
} else {
$file = $noavt;
}
}
if($random == 1 && $avtexist != 0) {
$trandom = '?random='.rand(1000, 9999);
}
if($trandom) {
$file = $file.$trandom;
}
if($returnsrc) {
return $file;
} else {
return '<img src="'.$file.'"'.(($avtexist == -1) ? '' : '').($class ? ' class="'.$class.'"' : '').($extra ? ' '.$extra : '').'>';
}
}
}
/**
* 根據(jù)給定的語言文件和變量名獲取本地化字符串
*
* @param string $file 語言文件名或插件語言標(biāo)識(shí)
* @param string|null $langvar 要獲取的具體語言變量名,如果為null則返回整個(gè)語言文件的內(nèi)容
* @param array $vars 語言字符串中需要替換的變量數(shù)組,鍵為變量名,值為替換值
* @param mixed $default 如果指定的語言變量不存在時(shí)的默認(rèn)返回值
* @return mixed 返回替換后的語言字符串或數(shù)組
*/
function lang($file, $langvar = null, $vars = array(), $default = null) {
global $_G;
$fileinput = $file;
// 分解文件路徑和名稱
$list = explode('/', $file);
$path = $list[0];
$file = isset($list[1]) ? $list[1] : false;
// 如果沒有文件名,則認(rèn)為路徑名即為文件名
if(!$file) {
$file = $path;
$path = '';
}
// 處理插件語言文件特殊情況
if(strpos($file, ':') !== false) {
$path = 'plugin';
list($file) = explode(':', $file);
}
// 加載并合并語言文件
if($path != 'plugin') {
$key = $path == '' ? $file : $path.'_'.$file;
// 檢查語言文件是否已加載,未加載則加載
if(!isset($_G['lang'][$key])) {
$loadfile = DISCUZ_ROOT.'./source/language/'.($path == '' ? '' : $path.'/').'lang_'.$file.'.php';
if(file_exists($loadfile)) {
include $loadfile;
}
$_G['lang'][$key] = (array)$lang;
}
// 手機(jī)版特殊處理
if(defined('IN_MOBILE') && !defined('TPL_DEFAULT')) {
include DISCUZ_ROOT.'./source/language/touch/lang_template.php';
$_G['lang'][$key] = array_merge((array)$_G['lang'][$key], (array)$lang);
}
// 加載插件語言緩存
if(!isset($_G['cache']['pluginlanguage_system'])) {
loadcache('pluginlanguage_system');
}
if(!isset($_G['hooklang'][$fileinput])) {
if(isset($_G['cache']['pluginlanguage_system'][$fileinput]) && is_array($_G['cache']['pluginlanguage_system'][$fileinput])) {
$_G['lang'][$key] = array_merge((array)$_G['lang'][$key], (array)$_G['cache']['pluginlanguage_system'][$fileinput]);
}
$_G['hooklang'][$fileinput] = true;
}
$returnvalue = &$_G['lang'];
} else {
// 處理插件語言變量
if(empty($_G['config']['plugindeveloper'])) {
loadcache('pluginlanguage_script');
} elseif(!isset($_G['cache']['pluginlanguage_script'][$file]) && preg_match("/^[a-z]+[a-z0-9_]*$/i", $file)) {
if(@include(DISCUZ_ROOT.'./data/plugindata/'.$file.'.lang.php')) {
$_G['cache']['pluginlanguage_script'][$file] = $scriptlang[$file];
} else {
loadcache('pluginlanguage_script');
}
}
$returnvalue = & $_G['cache']['pluginlanguage_script'];
!is_array($returnvalue) && $returnvalue = array();
$key = &$file;
}
// 獲取并處理指定的語言變量或整個(gè)語言文件
$return = $langvar !== null ? (isset($returnvalue[$key][$langvar]) ? $returnvalue[$key][$langvar] : null) : (is_array($returnvalue[$key]) ? $returnvalue[$key] : array());
$return = $return === null ? ($default !== null ? $default : ($path != 'plugin' ? '' : $file . ':') . $langvar) : $return;
// 替換語言字符串中的變量
$searchs = $replaces = array();
if($vars && is_array($vars)) {
foreach($vars as $k => $v) {
$searchs[] = '{'.$k.'}';
$replaces[] = $v;
}
}
// 替換語言字符串中的全局變量
if(is_string($return) && strpos($return, '{_G/') !== false) {
preg_match_all('/\{_G\/(.+?)\}/', $return, $gvar);
foreach($gvar[0] as $k => $v) {
$searchs[] = (string)$v;
$replaces[] = getglobal($gvar[1][$k]);
}
}
// 執(zhí)行最后的替換
if($searchs || $replaces) {
$return = str_replace($searchs, $replaces, $return);
}
return $return;
}
/**
* 檢查模板是否需要刷新
*
* @param string $maintpl 主模板文件名
* @param string $subtpl 子模板文件名
* @param int $timecompare 用于比較的最新修改時(shí)間
* @param int $templateid 模板ID
* @param string $cachefile 緩存文件名
* @param string $tpldir 模板目錄
* @param string $file 檢查的文件名
* @return bool 如果模板需要刷新返回true,否則返回false
*/
function checktplrefresh($maintpl, $subtpl, $timecompare, $templateid, $cachefile, $tpldir, $file) {
static $tplrefresh, $timestamp, $targettplname;
if($tplrefresh === null) {
$tplrefresh = getglobal('config/output/tplrefresh');
$timestamp = getglobal('timestamp');
}
// 檢查是否滿足模板刷新條件
if(empty($timecompare) || $tplrefresh == 1 || ($tplrefresh > 1 && !($timestamp % $tplrefresh))) {
if(!file_exists(DISCUZ_ROOT.$subtpl)){
$subtpl = substr($subtpl, 0, -4).'.php';
}
// 檢查子模板文件的修改時(shí)間
if(empty($timecompare) || @filemtime(DISCUZ_ROOT.$subtpl) > $timecompare) {
require_once DISCUZ_ROOT.'/source/class/class_template.php';
$template = new template();
$template->parse_template($maintpl, $templateid, $tpldir, $file, $cachefile);
// 更新并檢查目標(biāo)模板文件名
if($targettplname === null) {
$targettplname = getglobal('style/tplfile');
if(!empty($targettplname)) {
include_once libfile('function/block');
$targettplname = strtr($targettplname, ':', '_');
update_template_block($targettplname, getglobal('style/tpldirectory'), $template->blocks);
}
$targettplname = true;
}
return TRUE;
}
}
return FALSE;
}
/**
* 加載模板文件
*
* @param string $file 模板文件名,可以包含路徑和模板ID標(biāo)識(shí)
* @param int $templateid 模板ID,默認(rèn)為0,代表全局模板
* @param string $tpldir 指定的模板目錄,默認(rèn)為空,會(huì)根據(jù)模板ID自動(dòng)確定
* @param int $gettplfile 是否僅獲取模板文件路徑而不生成緩存,1為是,默認(rèn)為0
* @param string $primaltpl 默認(rèn)模板文件名,用于指定原始模板,當(dāng)$templateid為'diy'時(shí)有效
* @return string 返回模板文件的緩存路徑
*/
function template($file, $templateid = 0, $tpldir = '', $gettplfile = 0, $primaltpl='') {
global $_G;
// 初始化模塊和Hook
if(!defined('CURMODULE')) {
define('CURMODULE', '');
}
if(!defined('HOOKTYPE')) {
define('HOOKTYPE', !defined('IN_MOBILE') ? 'hookscript' : 'hookscriptmobile');
}
// 執(zhí)行插件的Hook
if(!empty($_G['setting']['plugins']['func'][HOOKTYPE]['template'])) {
$param = func_get_args();
$hookreturn = hookscript('template', 'global', 'funcs', array('param' => $param, 'caller' => 'template'), 'template');
if($hookreturn) {
return $hookreturn;
}
}
// 初始化樣式
static $_init_style = false;
if($_init_style === false) {
C::app()->_init_style();
$_init_style = true;
}
// 解析模板文件名,支持模板克隆和DIY模板
$oldfile = $file;
if(strpos($file, ':') !== false) {
$clonefile = '';
list($templateid, $file, $clonefile) = explode(':', $file.'::');
$oldfile = $file;
$file = empty($clonefile) ? $file : $file.'_'.$clonefile;
if($templateid == 'diy') {
// 處理DIY模板邏輯
// ...
} else {
$tpldir = './source/plugin/'.$templateid.'/template';
}
}
// 處理Ajax請求下的模板文件名
$file .= !empty($_G['inajax']) && ($file == 'common/header' || $file == 'common/footer') ? '_ajax' : '';
$tpldir = $tpldir ? $tpldir : (defined('TPLDIR') ? TPLDIR : '');
$templateid = $templateid ? $templateid : (defined('TEMPLATEID') ? TEMPLATEID : '');
$filebak = $file;
// 移動(dòng)端模板處理
if(constant('HOOKTYPE') == 'hookscriptmobile' && defined('IN_MOBILE') && !defined('TPL_DEFAULT') && strpos($file, $_G['mobiletpl'][IN_MOBILE].'/') === false || (isset($_G['forcemobilemessage']) && $_G['forcemobilemessage'])) {
// ...
}
if(!$tpldir) {
$tpldir = './template/default';
}
$tplfile = $tpldir.'/'.$file.'.htm';
// 生成或獲取模板緩存文件
if($gettplfile) {
return $tplfile;
}
checktplrefresh($tplfile, $tplfile, @filemtime(DISCUZ_ROOT.$cachefile), $templateid, $cachefile, $tpldir, $file);
return DISCUZ_ROOT.$cachefile;
}
/**
* 生成基于輸入字符串和長度的安全簽名
*
* @param string $str 輸入字符串
* @param int $length 生成簽名的長度,默認(rèn)為16
* @return string 生成的簽名字符串
*/
function dsign($str, $length = 16){
return substr(md5($str.getglobal('config/security/authkey')), 0, ($length ? max(8, $length) : 16));
}
/**
* 生成模塊認(rèn)證密鑰
*
* @param int $id 模塊ID
* @return string 生成的模塊認(rèn)證密鑰
*/
function modauthkey($id) {
return md5(getglobal('username').getglobal('uid').getglobal('authkey').substr(TIMESTAMP, 0, -7).$id);
}
/**
* 獲取當(dāng)前導(dǎo)航ID
*
* @return string 當(dāng)前導(dǎo)航的ID
*/
function getcurrentnav() {
global $_G;
if(!empty($_G['mnid'])) {
return $_G['mnid'];
}
$mnid = '';
$_G['basefilename'] = $_G['basefilename'] == $_G['basescript'] ? $_G['basefilename'] : $_G['basescript'].'.php';
// 根據(jù)當(dāng)前腳本設(shè)置的導(dǎo)航進(jìn)行匹配
if(isset($_G['setting']['navmns'][$_G['basefilename']])) {
// 對(duì)于特定的腳本和條件,調(diào)整導(dǎo)航匹配
if($_G['basefilename'] == 'home.php' && $_GET['mod'] == 'space' && (empty($_GET['do']) || in_array($_GET['do'], array('follow', 'view')))) {
$_GET['mod'] = 'follow';
}
// 遍歷腳本設(shè)置的導(dǎo)航,匹配當(dāng)前請求的導(dǎo)航
foreach($_G['setting']['navmns'][$_G['basefilename']] as $navmn) {
if($navmn[0] == array_intersect_assoc($navmn[0], $_GET) || (isset($_GET['gid']) && $navmn[0]['mod'] == 'forumdisplay' && $navmn[0]['fid'] == $_GET['gid']) || ($navmn[0]['mod'] == 'space' && $_GET['mod'] == 'spacecp' && ($navmn[0]['do'] == $_GET['ac'] || $navmn[0]['do'] == 'album' && $_GET['ac'] == 'upload'))) {
$mnid = $navmn[1];
}
}
}
// 若未匹配到導(dǎo)航,嘗試根據(jù)請求的域名和URI匹配導(dǎo)航
if(!$mnid && isset($_G['setting']['navdms'])) {
foreach($_G['setting']['navdms'] as $navdm => $navid) {
if(strpos(strtolower($_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']), $navdm) !== false && strpos(strtolower($_SERVER['HTTP_HOST']), $navdm) === false) {
$mnid = $navid;
break;
}
}
}
// 最后嘗試直接獲取當(dāng)前腳本設(shè)置的默認(rèn)導(dǎo)航
if(!$mnid && isset($_G['setting']['navmn'][$_G['basefilename']])) {
$mnid = $_G['setting']['navmn'][$_G['basefilename']];
}
return $mnid;
}
/**
* 加載UCenter配置和客戶端庫
*/
function loaducenter() {
require_once DISCUZ_ROOT.'./config/config_ucenter.php';
require_once DISCUZ_ROOT.'./uc_client/client.php';
}
/**
* 加載緩存函數(shù)。
* 該函數(shù)用于加載指定的緩存數(shù)據(jù)。如果緩存未被加載或強(qiáng)制加載標(biāo)志為true,則會(huì)重新加載緩存。
*
* @param array|string $cachenames 要加載的緩存名稱,可以是一個(gè)字符串或字符串?dāng)?shù)組。
* @param bool $force 是否強(qiáng)制重新加載緩存,默認(rèn)為false。
* @return bool 函數(shù)總是返回true。
*/
function loadcache($cachenames, $force = false) {
global $_G;
static $loadedcache = array();
// 確保$cachenames為數(shù)組
$cachenames = is_array($cachenames) ? $cachenames : array($cachenames);
$caches = array();
// 遍歷緩存名稱,將未加載或需強(qiáng)制加載的緩存加入到加載列表中
foreach ($cachenames as $k) {
if(!isset($loadedcache[$k]) || $force) {
$caches[] = $k;
$loadedcache[$k] = true;
}
}
// 當(dāng)存在需要加載的緩存時(shí),執(zhí)行加載操作
if(!empty($caches)) {
$cachedata = C::t('common_syscache')->fetch_all_syscache($caches);
foreach($cachedata as $cname => $data) {
// 根據(jù)緩存名稱,將緩存數(shù)據(jù)存儲(chǔ)到全局變量或$_G['cache']中
if($cname == 'setting') {
$_G['setting'] = $data;
} elseif($cname == 'usergroup_'.$_G['groupid']) {
$_G['cache'][$cname] = $_G['group'] = $data;
} elseif($cname == 'style_default') {
$_G['cache'][$cname] = $_G['style'] = $data;
} elseif($cname == 'grouplevels') {
$_G['grouplevels'] = $data;
} else {
$_G['cache'][$cname] = $data;
}
}
}
return true;
}
/**
* 根據(jù)指定格式和時(shí)區(qū)偏移量格式化時(shí)間戳。
*
* @param int $timestamp 需要格式化的時(shí)間戳。
* @param string $format 格式化字符串,'dt'為日期和時(shí)間,默認(rèn),'d'為日期,'t'為時(shí)間,'u'為特殊時(shí)間格式。
* @param int $timeoffset 時(shí)區(qū)偏移量,單位為小時(shí),默認(rèn)為9999,表示使用全局設(shè)置。
* @param string $uformat 當(dāng)$format為'u'時(shí),使用的特定格式字符串。
* @return string 返回格式化后的時(shí)間字符串。
*/
function dgmdate($timestamp, $format = 'dt', $timeoffset = 9999, $uformat = '') {
global $_G;
// 當(dāng)指定格式為'u'且全局設(shè)置禁用日期轉(zhuǎn)換時(shí),格式設(shè)為'dt'
$format == 'u' && !$_G['setting']['dateconvert'] && $format = 'dt';
// 靜態(tài)變量初始化,用于緩存配置和語言變量
static $dformat, $tformat, $dtformat, $offset, $lang;
if($dformat === null) {
$dformat = getglobal('setting/dateformat');
$tformat = getglobal('setting/timeformat');
$dtformat = $dformat.' '.$tformat;
$offset = getglobal('member/timeoffset');
$sysoffset = getglobal('setting/timeoffset');
// 系統(tǒng)默認(rèn)時(shí)區(qū)偏移量處理
$offset = $offset == 9999 ? ($sysoffset ? $sysoffset : 0) : $offset;
$lang = lang('core', 'date');
}
// 處理自定義時(shí)區(qū)偏移量
$timeoffset = $timeoffset == 9999 ? $offset : $timeoffset;
$timeoffset = intval($timeoffset);
// 應(yīng)用時(shí)區(qū)偏移量到時(shí)間戳
$timestamp += $timeoffset * 3600;
// 根據(jù)格式參數(shù)選擇合適的格式字符串
$format = empty($format) || $format == 'dt' ? $dtformat : ($format == 'd' ? $dformat : ($format == 't' ? $tformat : $format));
if($format == 'u') {
// 特殊時(shí)間格式處理
$todaytimestamp = TIMESTAMP - (TIMESTAMP + $timeoffset * 3600) % 86400 + $timeoffset * 3600;
$s = gmdate(!$uformat ? $dtformat : $uformat, $timestamp);
$time = TIMESTAMP + $timeoffset * 3600 - $timestamp;
if($timestamp >= $todaytimestamp) {
// 當(dāng)天時(shí)間的特殊處理
if($time > 3600) {
$return = intval($time / 3600).' '.$lang['hour'].$lang['before'];
} elseif($time > 1800) {
$return = $lang['half'].$lang['hour'].$lang['before'];
} elseif($time > 60) {
$return = intval($time / 60).' '.$lang['min'].$lang['before'];
} elseif($time > 0) {
$return = $time.' '.$lang['sec'].$lang['before'];
} elseif($time == 0) {
$return = $lang['now'];
} else {
$return = $s;
}
// 非移動(dòng)設(shè)備上添加時(shí)間標(biāo)題
if($time >=0 && !defined('IN_MOBILE')) {
$return = '<span title="'.$s.'">'.$return.'</span>';
}
} elseif(($days = intval(($todaytimestamp - $timestamp) / 86400)) >= 0 && $days < 7) {
// 本周內(nèi)時(shí)間的特殊處理
if($days == 0) {
$return = $lang['yday'].' '.gmdate($tformat, $timestamp);
} elseif($days == 1) {
$return = $lang['byday'].' '.gmdate($tformat, $timestamp);
} else {
$return = ($days + 1).' '.$lang['day'].$lang['before'];
}
if(!defined('IN_MOBILE')) {
$return = '<span title="'.$s.'">'.$return.'</span>';
}
} else {
// 其他情況直接返回格式化時(shí)間
$return = $s;
}
return $return;
} else {
// 對(duì)于非'u'格式,直接使用gmdate函數(shù)格式化
return gmdate($format, $timestamp);
}
}
/**
* 根據(jù)日期字符串計(jì)算時(shí)間戳。
*
* @param string $date 日期字符串,格式為'YYYY-MM-DD'。
* @return int 返回計(jì)算得到的時(shí)間戳,不合法則返回0。
*/
function dmktime($date) {
if(strpos($date, '-')) {
// 通過字符串分割獲取年、月、日
$time = explode('-', $date);
return mktime(0, 0, 0, $time[1], $time[2], $time[0]);
}
return 0;
}
/**
* 將數(shù)字格式化顯示,如果超過1萬,則以 '<span title="原數(shù)字">數(shù)字/10k</span>' 的形式顯示
* @param int $number 需要格式化的數(shù)字
* @return string 格式化后的數(shù)字字符串
*/
function dnumber($number) {
return abs((int)$number) > 10000 ? '<span title="'.$number.'">'.intval($number / 10000).lang('core', '10k').'</span>' : $number;
}
/**
* 保存緩存數(shù)據(jù)
* @param string $cachename 緩存名稱
* @param mixed $data 緩存數(shù)據(jù)
*/
function savecache($cachename, $data) {
C::t('common_syscache')->insert_syscache($cachename, $data);
}
/**
* 保存系統(tǒng)緩存數(shù)據(jù),功能同savecache
* @param string $cachename 緩存名稱
* @param mixed $data 緩存數(shù)據(jù)
*/
function save_syscache($cachename, $data) {
savecache($cachename, $data);
}
/**
* 根據(jù)參數(shù)獲取區(qū)塊內(nèi)容
* @param mixed $parameter 區(qū)塊參數(shù)
*/
function block_get($parameter) {
include_once libfile('function/block');
block_get_batch($parameter);
}
/**
* 顯示指定ID的區(qū)塊
* @param int $bid 區(qū)塊ID
*/
function block_display($bid) {
include_once libfile('function/block');
block_display_batch($bid);
}
/**
* 將數(shù)組中的每個(gè)元素轉(zhuǎn)義并以逗號(hào)分隔拼接成一個(gè)SQL兼容的字符串
* @param array $array 需要處理的數(shù)組
* @return string 拼接后的字符串
*/
function dimplode($array) {
if(!empty($array)) {
$array = array_map('addslashes', $array);
return "'".implode("','", is_array($array) ? $array : array($array))."'";
} else {
return 0;
}
}
/**
* 獲取庫文件的文件路徑
* @param string $libname 庫名稱
* @param string $folder 文件夾路徑
* @return string|bool 返回庫文件的絕對(duì)路徑,如果路徑不合法則返回false
*/
function libfile($libname, $folder = '') {
$libpath = '/source/'.$folder;
if(strstr($libname, '/')) {
list($pre, $name) = explode('/', $libname);
$path = "{$libpath}/{$pre}/{$pre}_{$name}";
} else {
$path = "{$libpath}/{$libname}";
}
return preg_match('/^[\w\d\/_]+$/i', $path) ? realpath(DISCUZ_ROOT.$path.'.php') : false;
}
/**
* 計(jì)算字符串的長度,針對(duì)UTF-8編碼的字符串會(huì)按字符計(jì)算
* @param string $str 輸入的字符串
* @return int 字符串的長度
*/
function dstrlen($str) {
if(strtolower(CHARSET) != 'utf-8') {
return strlen($str);
}
$count = 0;
for($i = 0; $i < strlen($str); $i++){
$value = ord($str[$i]);
if($value > 127) {
$count++;
if($value >= 192 && $value <= 223) $i++;
elseif($value >= 224 && $value <= 239) $i = $i + 2;
elseif($value >= 240 && $value <= 247) $i = $i + 3;
}
$count++;
}
return $count;
}
/**
* 截取字符串,支持UTF-8編碼。
* @param string $string 原始字符串
* @param int $length 截取的長度
* @param string $dot 截?cái)嗪蟾郊拥淖址?,默認(rèn)為' ...'
* @return string 截取后的字符串
*/
function cutstr($string, $length, $dot = ' ...') {
if(strlen($string) <= $length) {
return $string;
}
$pre = chr(1);
$end = chr(1);
$string = str_replace(array('&', '"', '<', '>'), array($pre.'&'.$end, $pre.'"'.$end, $pre.'<'.$end, $pre.'>'.$end), $string);
$strcut = '';
if(strtolower(CHARSET) == 'utf-8') {
$n = $tn = $noc = 0;
while($n < strlen($string)) {
$t = ord($string[$n]);
if($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
$tn = 1; $n++; $noc++;
} elseif(194 <= $t && $t <= 223) {
$tn = 2; $n += 2; $noc += 2;
} elseif(224 <= $t && $t <= 239) {
$tn = 3; $n += 3; $noc += 2;
} elseif(240 <= $t && $t <= 247) {
$tn = 4; $n += 4; $noc += 2;
} elseif(248 <= $t && $t <= 251) {
$tn = 5; $n += 5; $noc += 2;
} elseif($t == 252 || $t == 253) {
$tn = 6; $n += 6; $noc += 2;
} else {
$n++;
}
if($noc >= $length) {
break;
}
}
if($noc > $length) {
$n -= $tn;
}
$strcut = substr($string, 0, $n);
} else {
$_length = $length - 1;
for($i = 0; $i < $length; $i++) {
if(ord($string[$i]) <= 127) {
$strcut .= $string[$i];
} else if($i < $_length) {
$strcut .= $string[$i].$string[++$i];
}
}
}
$strcut = str_replace(array($pre.'&'.$end, $pre.'"'.$end, $pre.'<'.$end, $pre.'>'.$end), array('&', '"', '<', '>'), $strcut);
$pos = strrpos($strcut, chr(1));
if($pos !== false) {
$strcut = substr($strcut,0,$pos);
}
return $strcut.$dot;
}
/**
* 去除字符串中的反斜杠
*
* @param string $string 待處理的字符串
* @return string 處理后的字符串
*/
function dstripslashes($string) {
if(empty($string)) return $string;
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = dstripslashes($val); // 遞歸處理數(shù)組中的每個(gè)元素
}
} else {
$string = stripslashes($string); // 去除字符串中的反斜杠
}
return $string;
}
/**
* 對(duì)給定的援助ID進(jìn)行編碼
*
* @param int $aid 援助ID
* @param int $type 編碼類型,默認(rèn)為0
* @param int $tid 附加ID,默認(rèn)為0
* @return string 編碼后的字符串
*/
function aidencode($aid, $type = 0, $tid = 0) {
global $_G;
$s = !$type ? $aid.'|'.substr(md5($aid.md5($_G['config']['security']['authkey']).TIMESTAMP.$_G['uid']), 0, 8).'|'.TIMESTAMP.'|'.$_G['uid'].'|'.$tid : $aid.'|'.md5($aid.md5($_G['config']['security']['authkey']).TIMESTAMP).'|'.TIMESTAMP;
return rawurlencode(base64_encode($s)); // 對(duì)字符串進(jìn)行編碼
}
/**
* 獲取論壇圖片的URL
*
* @param int $aid 圖片的援助ID
* @param int $nocache 是否啟用緩存,默認(rèn)為0
* @param int $w 圖片寬度,默認(rèn)為140
* @param int $h 圖片高度,默認(rèn)為140
* @param string $type 圖片類型,默認(rèn)為空
* @return string 圖片的URL
*/
function getforumimg($aid, $nocache = 0, $w = 140, $h = 140, $type = '') {
global $_G;
$key = dsign($aid.'|'.$w.'|'.$h); // 生成簽名
return 'forum.php?mod=image&aid='.$aid.'&size='.$w.'x'.$h.'&key='.rawurlencode($key).($nocache ? '&nocache=yes' : '').($type ? '&type='.$type : '');
}
/**
* 重寫輸出URL
*
* @param string $type 輸出類型
* @param string $returntype 返回類型
* @param string $host 主機(jī)名
* @return string 重寫后的URL
*/
function rewriteoutput($type, $returntype, $host) {
global $_G;
$fextra = '';
// 根據(jù)不同的類型處理參數(shù)并返回相應(yīng)的URL
if($type == 'forum_forumdisplay') {
list(,,, $fid, $page, $extra) = func_get_args();
$r = array(
'{fid}' => empty($_G['setting']['forumkeys'][$fid]) ? $fid : $_G['setting']['forumkeys'][$fid],
'{page}' => $page ? $page : 1,
);
} elseif($type == 'forum_viewthread') {
// ...
// 其他類型處理邏輯相似,省略...
// ...
}
$href = str_replace(array_keys($r), $r, $_G['setting']['rewriterule'][$type]).$fextra;
if(!$returntype) {
return '<a href="'.$host.$href.'"'.(!empty($extra) ? stripslashes($extra) : '').'>'; // 返回HTML鏈接
} else {
return $host.$href; // 返回URL
}
}
/**
* 手機(jī)端替換
*
* @param string $file 文件名
* @param array $replace 替換數(shù)組
* @return string 替換后的字符串
*/
function mobilereplace($file, $replace) {
return helper_mobile::mobilereplace($file, $replace);
}
/**
* 手機(jī)端輸出設(shè)置
*/
function mobileoutput() {
helper_mobile::mobileoutput();
}
/**
* 輸出處理函數(shù)
* 本函數(shù)負(fù)責(zé)處理全局輸出,包括但不限于:
* 1. 判斷是否已輸出,防止重復(fù)輸出。
* 2. 處理區(qū)塊更新緩存。
* 3. 移動(dòng)端輸出處理。
* 4. 輸出替換,如URL替換等。
* 5. HTML緩存生成。
* 6. 調(diào)試信息輸出。
*
*/
function output() {
global $_G;
// 檢查是否已定義輸出標(biāo)識(shí),防止重復(fù)輸出
if(defined('DISCUZ_OUTPUTED')) {
return;
} else {
define('DISCUZ_OUTPUTED', 1);
}
// 處理區(qū)塊更新緩存
if(!empty($_G['blockupdate'])) {
block_updatecache($_G['blockupdate']['bid']);
}
// 移動(dòng)端輸出處理
if(defined('IN_MOBILE')) {
mobileoutput();
}
// 處理URL重寫和域名配置,進(jìn)行內(nèi)容替換
$havedomain = implode('', $_G['setting']['domain']['app']);
if($_G['setting']['rewritestatus'] || !empty($havedomain)) {
$content = ob_get_contents();
$content = output_replace($content); // 對(duì)內(nèi)容進(jìn)行替換處理
ob_end_clean();
$_G['gzipcompress'] ? ob_start('ob_gzhandler') : ob_start(); // 啟用gzip壓縮
echo $content; // 輸出處理后的內(nèi)容
}
// 生成HTML緩存
if(isset($_G['makehtml'])) {
helper_makehtml::make_html();
}
// 關(guān)閉FTP連接
if($_G['setting']['ftp']['connid']) {
@ftp_close($_G['setting']['ftp']['connid']);
}
$_G['setting']['ftp'] = array(); // 清空FTP配置
// 生成緩存文件
if(defined('CACHE_FILE') && CACHE_FILE && !defined('CACHE_FORBIDDEN') && !defined('IN_MOBILE') && !IS_ROBOT && !checkmobile()) {
if(diskfreespace(DISCUZ_ROOT.'./'.$_G['setting']['cachethreaddir']) > 1000000) {
$content = empty($content) ? ob_get_contents() : $content;
// 生成臨時(shí)變量替換formhash和siteurl,防止緩存被惡意修改
$temp_md5 = md5(substr($_G['timestamp'], 0, -3).substr($_G['config']['security']['authkey'], 3, -3));
$temp_formhash = substr($temp_md5, 8, 8);
$content = preg_replace('/(name=[\'|\"]formhash[\'|\"] value=[\'\"]|formhash=)('.constant("FORMHASH").')/ismU', '${1}'.$temp_formhash, $content);
$temp_siteurl = 'siteurl_'.substr($temp_md5, 16, 8);
$content = preg_replace('/("|\')('.preg_quote($_G['siteurl'], '/').')/ismU', '${1}'.$temp_siteurl, $content);
$content = empty($content) ? ob_get_contents() : $content;
file_put_contents(CACHE_FILE, $content, LOCK_EX); // 寫入緩存文件
chmod(CACHE_FILE, 0777); // 修改緩存文件權(quán)限
}
}
// 輸出調(diào)試信息
if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG && @include(libfile('function/debug'))) {
function_exists('debugmessage') && debugmessage();
}
}
/**
* 輸出替換函數(shù)
* 本函數(shù)用于根據(jù)配置替換輸出內(nèi)容中的特定字符串或正則表達(dá)式。
*
* @param string $content 要處理的內(nèi)容
* @return string 返回處理后的內(nèi)容
*/
function output_replace($content) {
global $_G;
// 管理后臺(tái)輸出不進(jìn)行替換
if(defined('IN_MODCP') || defined('IN_ADMINCP')) return $content;
// 字符串替換處理
if(!empty($_G['setting']['output']['str']['search'])) {
if(empty($_G['setting']['domain']['app']['default'])) {
$_G['setting']['output']['str']['replace'] = str_replace('{CURHOST}', $_G['siteurl'], $_G['setting']['output']['str']['replace']);
}
$content = str_replace($_G['setting']['output']['str']['search'], $_G['setting']['output']['str']['replace'], $content);
}
// 正則表達(dá)式替換處理
if(!empty($_G['setting']['output']['preg']['search']) && (empty($_G['setting']['rewriteguest']) || empty($_G['uid']))) {
if(empty($_G['setting']['domain']['app']['default'])) {
$_G['setting']['output']['preg']['search'] = str_replace('\{CURHOST\}', preg_quote($_G['siteurl'], '/'), $_G['setting']['output']['preg']['search']);
$_G['setting']['output']['preg']['replace'] = str_replace('{CURHOST}', $_G['siteurl'], $_G['setting']['output']['preg']['replace']);
}
foreach($_G['setting']['output']['preg']['search'] as $key => $value) {
$content = preg_replace_callback(
$value,
function ($matches) use ($_G, $key) {
return eval('return ' . $_G['setting']['output']['preg']['replace'][$key] . ';');
},
$content
);
}
}
return $content;
}
/**
* 輸出AJAX內(nèi)容
* 本函數(shù)獲取當(dāng)前輸出內(nèi)容,進(jìn)行清理和替換,然后返回處理后的字符串。
*/
function output_ajax() {
global $_G;
// 獲取當(dāng)前輸出緩沖區(qū)的內(nèi)容
$s = ob_get_contents();
ob_end_clean(); // 清除輸出緩沖區(qū)
// 替換掉控制字符和特定字符
$s = preg_replace("/([\\x01-\\x08\\x0b-\\x0c\\x0e-\\x1f])+/", ' ', $s);
$s = str_replace(array(chr(0), ']]>'), array(' ', ']]>'), $s);
// 如果處于調(diào)試模式,添加調(diào)試信息
if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG && @include(libfile('function/debug'))) {
function_exists('debugmessage') && $s .= debugmessage(1);
}
// 處理URL重寫和域名設(shè)置
$havedomain = implode('', $_G['setting']['domain']['app']);
if($_G['setting']['rewritestatus'] || !empty($havedomain)) {
$s = output_replace($s);
}
return $s; // 返回處理后的字符串
}
/**
* 執(zhí)行插件鉤子
* 本函數(shù)用于觸發(fā)并執(zhí)行插件鉤子。
*
* @param string $scriptextra 額外的腳本參數(shù)
*/
function runhooks($scriptextra = '') {
if(!defined('HOOKTYPE')) {
define('HOOKTYPE', !defined('IN_MOBILE') ? 'hookscript' : 'hookscriptmobile');
}
// 觸發(fā)全局插件鉤子
if(defined('CURMODULE')) {
global $_G;
if($_G['setting']['plugins']['func'][HOOKTYPE]['common']) {
hookscript('common', 'global', 'funcs', array(), 'common');
}
hookscript(CURMODULE, $_G['basescript'], 'funcs', array(), '', $scriptextra);
}
}
/**
* 執(zhí)行具體的插件鉤子腳本
* 本函數(shù)根據(jù)提供的參數(shù),執(zhí)行相應(yīng)的插件鉤子腳本。
*
* @param string $script 腳本名稱
* @param string $hscript 執(zhí)行環(huán)境腳本名稱
* @param string $type 鉤子類型
* @param array $param 傳遞給鉤子函數(shù)的參數(shù)數(shù)組
* @param string $func 鉤子函數(shù)名,為空則執(zhí)行所有相關(guān)函數(shù)
* @param string $scriptextra 額外的腳本參數(shù)
*/
function hookscript($script, $hscript, $type = 'funcs', $param = array(), $func = '', $scriptextra = '') {
global $_G;
static $pluginclasses = array(); // 靜態(tài)變量存儲(chǔ)已加載的插件類
// 處理特定腳本的額外邏輯
if($hscript == 'home') {
if($script == 'space') {
$scriptextra = !$scriptextra ? getgpc('do') : $scriptextra;
$script = 'space'.(!empty($scriptextra) ? '_'.$scriptextra : '');
} elseif($script == 'spacecp') {
$scriptextra = !$scriptextra ? getgpc('ac') : $scriptextra;
$script .= !empty($scriptextra) ? '_'.$scriptextra : '';
}
}
if(!defined('HOOKTYPE')) {
define('HOOKTYPE', !defined('IN_MOBILE') ? 'hookscript' : 'hookscriptmobile');
}
// 檢查是否存在該鉤子的設(shè)置
if(!isset($_G['setting'][HOOKTYPE][$hscript][$script][$type])) {
return;
}
// 加載插件設(shè)置
if(!isset($_G['cache']['plugin'])) {
loadcache('plugin');
}
// 循環(huán)遍歷并加載所有相關(guān)插件
foreach((array)$_G['setting'][HOOKTYPE][$hscript][$script]['module'] as $identifier => $include) {
if($_G['pluginrunlist'] && !in_array($identifier, $_G['pluginrunlist'])) {
continue;
}
$hooksadminid[$identifier] = !$_G['setting'][HOOKTYPE][$hscript][$script]['adminid'][$identifier] || ($_G['setting'][HOOKTYPE][$hscript][$script]['adminid'][$identifier] && $_G['adminid'] > 0 && $_G['setting']['hookscript'][$hscript][$script]['adminid'][$identifier] >= $_G['adminid']);
if($hooksadminid[$identifier]) {
@include_once DISCUZ_ROOT.'./source/plugin/'.$include.'.class.php';
}
}
// 執(zhí)行鉤子函數(shù)
if(isset($_G['setting'][HOOKTYPE][$hscript][$script][$type]) && is_array($_G['setting'][HOOKTYPE][$hscript][$script][$type])) {
$_G['inhookscript'] = true;
$funcs = !$func ? $_G['setting'][HOOKTYPE][$hscript][$script][$type] : array($func => $_G['setting'][HOOKTYPE][$hscript][$script][$type][$func]);
foreach($funcs as $hookkey => $hookfuncs) {
foreach($hookfuncs as $hookfunc) {
if($hooksadminid[$hookfunc[0]]) {
$classkey = (HOOKTYPE != 'hookscriptmobile' ? '' : 'mobile').'plugin_'.($hookfunc[0].($hscript != 'global' ? '_'.$hscript : ''));
if(!class_exists($classkey, false)) {
continue;
}
if(!isset($pluginclasses[$classkey])) {
$pluginclasses[$classkey] = new $classkey;
}
if(!method_exists($pluginclasses[$classkey], $hookfunc[1])) {
continue;
}
// 調(diào)用插件方法
$return = call_user_func(array($pluginclasses[$classkey], $hookfunc[1]), $param);
// 處理擴(kuò)展鉤子和更新插件鉤子緩存
if(substr($hookkey, -7) == '_extend' && !empty($_G['setting']['pluginhooks'][$hookkey])) {
continue;
}
if(is_array($return)) {
// 更新插件鉤子緩存
if(!isset($_G['setting']['pluginhooks'][$hookkey]) || is_array($_G['setting']['pluginhooks'][$hookkey])) {
foreach($return as $k => $v) {
$_G['setting']['pluginhooks'][$hookkey][$k] .= $v;
}
} else {
foreach($return as $k => $v) {
$_G['setting']['pluginhooks'][$hookkey][$k] = $v;
}
}
} else {
// 單個(gè)字符串返回的處理
if(!(isset($_G['setting']['pluginhooks'][$hookkey]) && is_array($_G['setting']['pluginhooks'][$hookkey]))) {
if(!isset($_G['setting']['pluginhooks'][$hookkey])) {
$_G['setting']['pluginhooks'][$hookkey] = '';
}
$_G['setting']['pluginhooks'][$hookkey] .= $return;
} else {
foreach($_G['setting']['pluginhooks'][$hookkey] as $k => $v) {
$_G['setting']['pluginhooks'][$hookkey][$k] .= $return;
}
}
}
}
}
}
}
$_G['inhookscript'] = false; // 重置鉤子執(zhí)行標(biāo)志
}
/**
* 執(zhí)行全局鉤子腳本輸出
*
* @param string $tplfile 模板文件名
*/
function hookscriptoutput($tplfile) {
global $_G;
// 如果已經(jīng)執(zhí)行過鉤子腳本輸出,則不再執(zhí)行
if(!empty($_G['hookscriptoutput'])) {
return;
}
// 加載全局鉤子腳本
hookscript('global', 'global');
$_G['hookscriptoutput'] = true;
// 如果定義了當(dāng)前模塊,執(zhí)行模塊輸出鉤子
if(defined('CURMODULE')) {
$param = array('template' => $tplfile, 'message' => getglobal('hookscriptmessage'), 'values' => getglobal('hookscriptmessage'));
hookscript(CURMODULE, $_G['basescript'], 'outputfuncs', $param);
}
}
/**
* 根據(jù)插件ID和類型獲取插件模塊文件路徑
*
* @param string $pluginid 插件ID
* @param string $type 插件類型
* @return string 插件模塊文件的完整路徑
*/
function pluginmodule($pluginid, $type) {
global $_G;
$pluginid = $pluginid ? preg_replace("/[^A-Za-z0-9_:]/", '', $pluginid) : '';
// 加載插件緩存
if(!isset($_G['cache']['plugin'])) {
loadcache('plugin');
}
list($identifier, $module) = explode(':', $pluginid);
// 檢查插件是否存在
if(!is_array($_G['setting']['plugins'][$type]) || !array_key_exists($pluginid, $_G['setting']['plugins'][$type])) {
showmessage('plugin_nonexistence');
}
// 處理插件URL跳轉(zhuǎn)
if(!empty($_G['setting']['plugins'][$type][$pluginid]['url'])) {
dheader('location: '.$_G['setting']['plugins'][$type][$pluginid]['url']);
}
$directory = $_G['setting']['plugins'][$type][$pluginid]['directory'];
// 檢查插件目錄和模塊名稱是否合法
if(empty($identifier) || !preg_match("/^[a-z]+[a-z0-9_]*\/$/i", $directory) || !preg_match("/^[a-z0-9_\-]+$/i", $module)) {
showmessage('undefined_action');
}
// 檢查插件模塊文件是否存在
if(@!file_exists(DISCUZ_ROOT.($modfile = './source/plugin/'.$directory.$module.'.inc.php'))) {
showmessage('plugin_module_nonexistence', '', array('mod' => $modfile));
}
return DISCUZ_ROOT.$modfile;
}
/**
* 根據(jù)操作更新用戶積分
*
* @param string $action 操作名稱
* @param int $uid 用戶ID,默認(rèn)為0表示全局操作
* @param array $extrasql 額外的SQL語句數(shù)組
* @param string $needle 匹配規(guī)則中的關(guān)鍵字
* @param int $coef 積分規(guī)則的系數(shù)
* @param int $update 是否更新用戶積分,默認(rèn)為1表示更新
* @param int $fid 論壇ID,默認(rèn)為0
* @return mixed 更新結(jié)果
*/
function updatecreditbyaction($action, $uid = 0, $extrasql = array(), $needle = '', $coef = 1, $update = 1, $fid = 0) {
$credit = credit::instance();
if($extrasql) {
$credit->extrasql = $extrasql;
}
return $credit->execrule($action, $uid, $needle, $coef, $update, $fid);
}
/**
* 檢查操作是否低于積分下限
*
* @param string $action 操作名稱
* @param int $uid 用戶ID,默認(rèn)為0
* @param int $coef 積分規(guī)則的系數(shù)
* @param int $fid 論壇ID,默認(rèn)為0
* @param int $returnonly 是否只返回不拋出異常,默認(rèn)為0,表示拋出異常
* @return mixed 檢查結(jié)果
*/
function checklowerlimit($action, $uid = 0, $coef = 1, $fid = 0, $returnonly = 0) {
require_once libfile('function/credit');
return _checklowerlimit($action, $uid, $coef, $fid, $returnonly);
}
/**
* 批量更新用戶積分
*
* @param string $action 操作名稱
* @param array $uids 用戶ID數(shù)組
* @param array $extrasql 額外的SQL語句數(shù)組
* @param int $coef 積分規(guī)則的系數(shù)
* @param int $fid 論壇ID,默認(rèn)為0
* @return mixed 更新結(jié)果
*/
function batchupdatecredit($action, $uids = 0, $extrasql = array(), $coef = 1, $fid = 0) {
$credit = & credit::instance();
if($extrasql) {
$credit->extrasql = $extrasql;
}
return $credit->updatecreditbyrule($action, $uids, $coef, $fid);
}
/**
* 更新成員統(tǒng)計(jì)數(shù)字
*
* @param array $uids 用戶ID數(shù)組
* @param array $dataarr 要更新的數(shù)據(jù)數(shù)組
* @param bool $checkgroup 是否檢查用戶組,默認(rèn)為true
* @param string $operation 操作類型
* @param int $relatedid 關(guān)聯(lián)ID
* @param string $ruletxt 規(guī)則文本
* @param string $customtitle 自定義標(biāo)題
* @param string $custommemo 自定義備注
* @return bool 更新結(jié)果
*/
function updatemembercount($uids, $dataarr = array(), $checkgroup = true, $operation = '', $relatedid = 0, $ruletxt = '', $customtitle = '', $custommemo = '') {
if(!empty($uids) && (is_array($dataarr) && $dataarr)) {
require_once libfile('function/credit');
return _updatemembercount($uids, $dataarr, $checkgroup, $operation, $relatedid, $ruletxt, $customtitle, $custommemo);
}
return true;
}
/**
* 檢查用戶組
*
* @param int $uid 用戶ID,默認(rèn)為0
*/
function checkusergroup($uid = 0) {
$credit = & credit::instance();
$credit->checkusergroup($uid);
}
/**
* 檢查公式語法正確性
*
* @param string $formula 公式字符串
* @param array $operators 運(yùn)算符數(shù)組
* @param array $tokens 變量令牌數(shù)組
* @param string $values 替換值,默認(rèn)為空
* @param array $funcs 函數(shù)數(shù)組
* @return bool|mixed 正確返回true,錯(cuò)誤返回錯(cuò)誤信息
*/
function checkformulasyntax($formula, $operators, $tokens, $values = '', $funcs = array()) {
$var = implode('|', $tokens);
if(!empty($formula)) {
$formula = preg_replace("/($var)/", "\$\\1", $formula);
return formula_tokenize($formula, $operators, $tokens, $values, $funcs);
}
return true;
}
/**
* 對(duì)給定的公式進(jìn)行分詞處理
*
* @param string $formula 待分詞的公式
* @param array $operators 運(yùn)算符數(shù)組
* @param array $tokens 特殊令牌數(shù)組,如變量前綴等
* @param string|array $values 可接受的字符串或字符串?dāng)?shù)組值
* @param array $funcs 可接受的函數(shù)名數(shù)組
* @return bool 分詞成功返回true,否則返回false
*/
function formula_tokenize($formula, $operators, $tokens, $values, $funcs) {
// 將公式封裝成PHP代碼后進(jìn)行token解析
$fexp = token_get_all('<?php '.$formula);
$prevseg = 1; // 上一個(gè)段落標(biāo)記:1左括號(hào), 2右括號(hào), 3變量, 4運(yùn)算符, 5函數(shù)
$isclose = 0; // 括號(hào)是否匹配
$tks = implode('|', $tokens); // 將令牌數(shù)組合并為一個(gè)正則表達(dá)式方便匹配
$op1 = $op2 = array(); // 分別存儲(chǔ)單字符和雙字符運(yùn)算符
foreach($operators as $orts) {
if(strlen($orts) === 1) {
$op1[] = $orts;
} else {
$op2[] = $orts;
}
}
foreach($fexp as $k => $val) {
if(is_array($val)) {
// 處理變量、字符串、數(shù)字等
if(in_array($val[0], array(T_VARIABLE, T_CONSTANT_ENCAPSED_STRING, T_LNUMBER, T_DNUMBER))) {
if(!in_array($prevseg, array(1, 4))) {
return false;
}
$prevseg = 3;
// 檢查變量是否符合要求
if($val[0] == T_VARIABLE && !preg_match('/^\$('.$tks.')$/', $val[1])) {
return false;
}
// 檢查字符串是否符合給定的值
if($val[0] == T_CONSTANT_ENCAPSED_STRING && !($values && preg_match('/^'.$values.'$/', $val[1]))) {
return false;
}
} elseif($val[0] == T_STRING && in_array($val[1], $funcs)) {
// 處理函數(shù)
if(!in_array($prevseg, array(1, 4))) {
return false;
}
$prevseg = 5;
} elseif($val[0] == T_WHITESPACE || ($k == 0 && $val[0] == T_OPEN_TAG)) {
// 忽略空白字符和開頭的T_OPEN_TAG
} elseif(in_array($val[1], $op2)) {
// 處理雙字符運(yùn)算符
if(!in_array($prevseg, array(2, 3))) {
return false;
}
$prevseg = 4;
} else {
return false;
}
} else {
// 處理括號(hào)和單字符運(yùn)算符
if($val === '(') {
if(!in_array($prevseg, array(1, 4, 5))) {
return false;
}
$prevseg = 1;
$isclose++;
} elseif($val === ')') {
if(!in_array($prevseg, array(2, 3))) {
return false;
}
$prevseg = 2;
$isclose--;
if($isclose < 0) {
return false;
}
} elseif(in_array($val, $op1)) {
// 處理單字符運(yùn)算符,特別處理負(fù)號(hào)情況
if(!in_array($prevseg, array(2, 3)) && $val !== '-') {
return false;
}
$prevseg = 4;
} else {
return false;
}
}
}
// 檢查括號(hào)是否匹配,上一個(gè)段落標(biāo)記是否正確
return (in_array($prevseg, array(2, 3)) && $isclose === 0);
}
/**
* 檢查公式的語法信用
*
* @param string $formula 待檢查的公式
* @return bool 語法檢查通過返回true,否則返回false
*/
function checkformulacredits($formula) {
return checkformulasyntax(
$formula,
array('+', '-', '*', '/'),
array('extcredits[1-8]', 'digestposts', 'posts', 'threads', 'oltime', 'friends', 'doings', 'polls', 'blogs', 'albums', 'sharings')
);
}
/**
* 頁面調(diào)試信息輸出
*
* @param mixed $var 要調(diào)試的變量,默認(rèn)為null,如果為null則輸出整個(gè)頁面變量
* @param bool $vardump 是否使用var_dump輸出,默認(rèn)為false,使用var_dump需要設(shè)置為true
*/
function debug($var = null, $vardump = false) {
echo '<pre>';
$vardump = empty($var) ? true : $vardump;
if($vardump) {
var_dump($var);
} else {
print_r($var);
}
exit();
}
/**
* 獲取調(diào)試信息
*
* @global array $_G 全局變量數(shù)組
* @return bool 如果啟用了調(diào)試模式返回調(diào)試信息,否則返回false
*/
function debuginfo() {
global $_G;
if(getglobal('setting/debug')) {
$_G['debuginfo'] = array(
'time' => number_format((microtime(true) - $_G['starttime']), 6),
'queries' => DB::object()->querynum,
'memory' => ucwords(C::memory()->type)
);
if(DB::object()->slaveid) {
$_G['debuginfo']['queries'] = 'Total '.DB::object()->querynum.', Slave '.DB::object()->slavequery;
}
return TRUE;
} else {
return FALSE;
}
}
/**
* 獲取指定模塊的隨機(jī)焦點(diǎn)圖片ID
*
* @param string $module 模塊名稱
* @return null|mixed 返回隨機(jī)焦點(diǎn)圖片的ID,若未設(shè)置或不存在則返回null
*/
function getfocus_rand($module) {
global $_G;
// 檢查焦點(diǎn)設(shè)置是否存在且指定模塊有效,以及用戶是否關(guān)閉了焦點(diǎn)圖片顯示
if(empty($_G['setting']['focus']) || !array_key_exists($module, $_G['setting']['focus']) || !empty($_G['cookie']['nofocus_'.$module]) || !$_G['setting']['focus'][$module]) {
return null;
}
loadcache('focus'); // 加載焦點(diǎn)緩存
if(empty($_G['cache']['focus']['data']) || !is_array($_G['cache']['focus']['data'])) {
return null;
}
// 隨機(jī)獲取一個(gè)焦點(diǎn)圖片ID
$focusid = $_G['setting']['focus'][$module][array_rand($_G['setting']['focus'][$module])];
return $focusid;
}
/**
* 校驗(yàn)驗(yàn)證碼
*
* @param string $value 用戶輸入的驗(yàn)證碼值
* @param string $idhash 驗(yàn)證碼ID哈希值
* @param int $fromjs 是否來自JS提交,默認(rèn)為0(非JS)
* @param string $modid 模塊ID,默認(rèn)為空
* @param bool $verifyonly 是否只進(jìn)行驗(yàn)證碼校驗(yàn),默認(rèn)為false
* @return mixed 返回校驗(yàn)結(jié)果
*/
function check_seccode($value, $idhash, $fromjs = 0, $modid = '', $verifyonly = false) {
return helper_seccheck::check_seccode($value, $idhash, $fromjs, $modid, $verifyonly);
}
/**
* 校驗(yàn)QAA安全問題
*
* @param string $value 用戶輸入的安全問題答案
* @param string $idhash 安全問題ID哈希值
* @param bool $verifyonly 是否只進(jìn)行安全問題校驗(yàn),默認(rèn)為false
* @return mixed 返回校驗(yàn)結(jié)果
*/
function check_secqaa($value, $idhash, $verifyonly = false) {
return helper_seccheck::check_secqaa($value, $idhash, $verifyonly);
}
/**
* 執(zhí)行安全檢查
*
* @param string $rule 安全檢查規(guī)則
* @param array $param 傳遞給規(guī)則的參數(shù),默認(rèn)為空數(shù)組
* @return mixed 返回安全檢查結(jié)果
*/
function seccheck($rule, $param = array()) {
return helper_seccheck::seccheck($rule, $param);
}
/**
* 生成驗(yàn)證碼
*
* @param string $seccode 驗(yàn)證碼內(nèi)容,默認(rèn)為空
* @return string 返回生成的驗(yàn)證碼
*/
function make_seccode($seccode = '') {
return helper_seccheck::make_seccode($seccode);
}
/**
* 生成QAA安全問題
*
* @return string 返回生成的安全問題
*/
function make_secqaa() {
return helper_seccheck::make_secqaa();
}
/**
* 顯示廣告
*
* @param string $parameter 廣告參數(shù)
* @return string 返回廣告內(nèi)容或空字符串
*/
function adshow($parameter) {
global $_G;
// 判斷是否在AJAX請求中或用戶組關(guān)閉了廣告顯示
if(getgpc('inajax') || $_G['group']['closead']) {
return;
}
$return = (isset($_G['config']['plugindeveloper']) && $_G['config']['plugindeveloper'] == 2) ? '<hook>[ad '.$parameter.']</hook>' : '';
$params = explode('/', $parameter);
$customid = 0;
$customc = explode('_', $params[0]);
// 處理自定義廣告
if($customc[0] == 'custom') {
$params[0] = $customc[0];
$customid = $customc[1];
}
$adcontent = null;
// 檢查廣告類型是否設(shè)置
if(empty($_G['setting']['advtype']) || !in_array($params[0], $_G['setting']['advtype'])) {
$adcontent = '';
}
if($adcontent === null) {
loadcache('advs'); // 加載廣告緩存
$adids = array();
$evalcode = &$_G['cache']['advs']['evalcode'][$params[0]];
$parameters = &$_G['cache']['advs']['parameters'][$params[0]];
$codes = &$_G['cache']['advs']['code'][$_G['basescript']][$params[0]];
// 評(píng)估并選擇合適的廣告進(jìn)行顯示
if(!empty($codes)) {
foreach($codes as $adid => $code) {
$parameter = &$parameters[$adid];
$checked = true;
@eval($evalcode['check']);
if($checked) {
$adids[] = $adid;
}
}
if(!empty($adids)) {
$adcode = $extra = '';
@eval($evalcode['create']);
if(empty($notag)) {
$adcontent = '<div'.($params[1] != '' ? ' class="'.$params[1].'"' : '').$extra.'>'.$adcode.'</div>';
} else {
$adcontent = $adcode;
}
}
}
}
$adfunc = 'ad_'.$params[0];
$_G['setting']['pluginhooks'][$adfunc] = null;
// 執(zhí)行插件鉤子
hookscript('ad', 'global', 'funcs', array('params' => $params, 'content' => $adcontent, 'customid' => $customid), $adfunc);
if(empty($_G['setting']['hookscript']['global']['ad']['funcs'][$adfunc])) {
hookscript('ad', $_G['basescript'], 'funcs', array('params' => $params, 'content' => $adcontent, 'customid' => $customid), $adfunc);
}
return $return.($_G['setting']['pluginhooks'][$adfunc] === null ? $adcontent : $_G['setting']['pluginhooks'][$adfunc]);
}
/**
* 顯示消息并跳轉(zhuǎn)
*
* @param string $message 要顯示的消息
* @param string $url_forward 跳轉(zhuǎn)的URL
* @param array $values 傳遞給消息頁面的變量
* @param array $extraparam 額外的參數(shù)
* @param int $custom 自定義參數(shù)
* @return string 返回消息顯示和跳轉(zhuǎn)的HTML代碼
*/
function showmessage($message, $url_forward = '', $values = array(), $extraparam = array(), $custom = 0) {
require_once libfile('function/message');
return dshowmessage($message, $url_forward, $values, $extraparam, $custom);
}
/**
* 檢查提交的變量是否合法
*
* @param string $var 要檢查的變量名
* @param int $allowget 是否允許通過GET方式提交
* @param int $seccodecheck 是否檢查驗(yàn)證碼
* @param int $secqaacheck 是否檢查安全問題
* @return bool 如果檢查通過返回TRUE,否則返回FALSE
*/
function submitcheck($var, $allowget = 0, $seccodecheck = 0, $secqaacheck = 0) {
if(!getgpc($var)) {
return FALSE;
} else {
return helper_form::submitcheck($var, $allowget, $seccodecheck, $secqaacheck);
}
}
/**
* 生成分頁鏈接
*
* @param int $num 總數(shù)量
* @param int $perpage 每頁數(shù)量
* @param int $curpage 當(dāng)前頁碼
* @param string $mpurl 分頁跳轉(zhuǎn)的URL
* @param int $maxpages 最大顯示頁數(shù)
* @param int $page 顯示的頁碼數(shù)
* @param bool $autogoto 是否自動(dòng)跳轉(zhuǎn)到當(dāng)前頁
* @param bool $simple 是否為簡單分頁模式
* @param bool $jsfunc 是否通過JS函數(shù)處理分頁
* @return string 返回分頁HTML代碼
*/
function multi($num, $perpage, $curpage, $mpurl, $maxpages = 0, $page = 10, $autogoto = FALSE, $simple = FALSE, $jsfunc = FALSE) {
return $num > $perpage ? helper_page::multi($num, $perpage, $curpage, $mpurl, $maxpages, $page, $autogoto, $simple, $jsfunc) : '';
}
/**
* 生成簡單分頁鏈接
*
* @param int $num 總數(shù)量
* @param int $perpage 每頁數(shù)量
* @param int $curpage 當(dāng)前頁碼
* @param string $mpurl 分頁跳轉(zhuǎn)的URL
* @return string 返回分頁HTML代碼
*/
function simplepage($num, $perpage, $curpage, $mpurl) {
return helper_page::simplepage($num, $perpage, $curpage, $mpurl);
}
/**
* 檢查并過濾敏感詞
*
* @param string $message 要檢查的消息
* @param string $modword 指定的敏感詞列表
* @param bool $return 是否返回過濾后的消息
* @param bool $modasban 是否將含有敏感詞的帖子默認(rèn)禁言
* @return mixed 根據(jù)$return參數(shù)返回過濾后的消息或TRUE/FALSE
*/
function censor($message, $modword = NULL, $return = FALSE, $modasban = TRUE) {
return helper_form::censor($message, $modword, $return, $modasban);
}
/**
* 檢測消息是否包含敏感詞
*
* @param string $message 要檢查的消息
* @return bool 如果消息包含敏感詞返回FALSE,否則返回TRUE
*/
function censormod($message) {
return getglobal('group/ignorecensor') || !$message ? false :helper_form::censormod($message);
}
/**
* 合并用戶空間數(shù)據(jù)
*
* @param array &$values 要合并的數(shù)據(jù)數(shù)組
* @param string $tablename 數(shù)據(jù)表名
* @param bool $isarchive 是否為歸檔數(shù)據(jù)
* @global array $_G 全局變量數(shù)組
* @return void
*/
function space_merge(&$values, $tablename, $isarchive = false) {
global $_G;
$uid = empty($values['uid'])?$_G['uid']:$values['uid'];
$var = "member_{$uid}_{$tablename}";
if($uid) {
if(!isset($_G[$var])) {
$ext = $isarchive ? '_archive' : '';
if(($_G[$var] = C::t('common_member_'.$tablename.$ext)->fetch($uid)) !== false) {
if($tablename == 'field_home') {
// 處理個(gè)人空間字段的特殊邏輯
$_G['setting']['privacy'] = empty($_G['setting']['privacy']) ? array() : (is_array($_G['setting']['privacy']) ? $_G['setting']['privacy'] : dunserialize($_G['setting']['privacy']));
$_G[$var]['privacy'] = empty($_G[$var]['privacy']) ? array() : (is_array($_G[$var]['privacy']) ? $_G[$var]['privacy'] : dunserialize($_G[$var]['privacy']));
foreach (array('feed','view','profile') as $pkey) {
if(empty($_G[$var]['privacy'][$pkey]) && !isset($_G[$var]['privacy'][$pkey])) {
$_G[$var]['privacy'][$pkey] = isset($_G['setting']['privacy'][$pkey]) ? $_G['setting']['privacy'][$pkey] : array();
}
}
$_G[$var]['acceptemail'] = empty($_G[$var]['acceptemail'])? array() : dunserialize($_G[$var]['acceptemail']);
if(empty($_G[$var]['acceptemail'])) {
$_G[$var]['acceptemail'] = empty($_G['setting']['acceptemail'])?array():dunserialize($_G['setting']['acceptemail']);
}
}
} else {
C::t('common_member_'.$tablename.$ext)->insert(array('uid'=>$uid));
$_G[$var] = array();
}
}
$values = array_merge($values, $_G[$var]);
}
}
/**
* 記錄運(yùn)行日志
*
* @param string $file 日志文件名
* @param string $message 要記錄的消息
* @param int $halt 是否停止執(zhí)行
* @return void
*/
function runlog($file, $message, $halt=0) {
helper_log::runlog($file, $message, $halt);
}
/**
* 去除搜索關(guān)鍵詞中的特殊字符
*
* @param string $string 搜索關(guān)鍵詞
* @return string 處理后的關(guān)鍵詞
*/
function stripsearchkey($string) {
$string = trim($string);
$string = str_replace('*', '%', addcslashes($string, '%_'));
return $string;
}
/**
* 創(chuàng)建目錄及其子目錄
*
* @param string $dir 要?jiǎng)?chuàng)建的目錄路徑
* @param int $mode 目錄權(quán)限
* @param bool $makeindex 是否創(chuàng)建index文件
* @return bool 創(chuàng)建成功返回true,否則返回false
*/
function dmkdir($dir, $mode = 0777, $makeindex = TRUE){
if(!is_dir($dir)) {
dmkdir(dirname($dir), $mode, $makeindex);
@mkdir($dir, $mode);
if(!empty($makeindex)) {
@touch($dir.'/index.html'); @chmod($dir.'/index.html', 0777);
}
}
return true;
}
/**
* 獲取并處理引用地址
*
* 本函數(shù)用于獲取并處理當(dāng)前的引用地址(即來源地址)。如果引用地址不符合特定條件,
* 則會(huì)返回一個(gè)默認(rèn)地址。處理過程包括去除查詢字符串、檢查是否為登錄頁面、驗(yàn)證域名等。
*
* @param string $default 默認(rèn)的引用地址,若為空且當(dāng)前應(yīng)用環(huán)境定義了'curapp'則默認(rèn)為'curapp.php'
* @return string 處理后的引用地址
*/
function dreferer($default = '') {
global $_G;
// 初始化默認(rèn)值
$default = empty($default) && $_ENV['curapp'] ? $_ENV['curapp'].'.php' : '';
// 獲取并處理GET參數(shù)中的引用地址或HTTP頭部中的引用地址
$_G['referer'] = !empty($_GET['referer']) ? $_GET['referer'] : $_SERVER['HTTP_REFERER'];
// 去除引用地址中的查詢字符串
$_G['referer'] = substr($_G['referer'], -1) == '?' ? substr($_G['referer'], 0, -1) : $_G['referer'];
// 如果引用地址是登錄頁面,則使用默認(rèn)地址
if(strpos($_G['referer'], 'member.php?mod=logging')) {
$_G['referer'] = $default;
}
// 解析引用地址的URL
$reurl = parse_url($_G['referer']);
// 構(gòu)造帶有端口的主機(jī)地址
$hostwithport = $reurl['host'] . (isset($reurl['port']) ? ':' . $reurl['port'] : '');
// 驗(yàn)證引用地址的有效性
if(!$reurl || (isset($reurl['scheme']) && !in_array(strtolower($reurl['scheme']), array('http', 'https')))) {
$_G['referer'] = '';
}
// 處理跨域引用的情況
if(!empty($hostwithport) && !in_array($hostwithport, array($_SERVER['HTTP_HOST'], 'www.'.$_SERVER['HTTP_HOST'])) && !in_array($_SERVER['HTTP_HOST'], array($hostwithport, 'www.'.$hostwithport))) {
if(!in_array($hostwithport, $_G['setting']['domain']['app']) && !isset($_G['setting']['domain']['list'][$hostwithport])) {
$domainroot = substr($hostwithport, strpos($hostwithport, '.')+1);
if(empty($_G['setting']['domain']['root']) || (is_array($_G['setting']['domain']['root']) && !in_array($domainroot, $_G['setting']['domain']['root']))) {
$_G['referer'] = $_G['setting']['domain']['defaultindex'] ? $_G['setting']['domain']['defaultindex'] : 'index.php';
}
}
} elseif(empty($hostwithport)) {
// 修正不帶域名的引用地址
$_G['referer'] = $_G['siteurl'].'./'.$_G['referer'];
}
// 對(duì)處理后的引用地址進(jìn)行URL編碼
$_G['referer'] = durlencode($_G['referer']);
return $_G['referer'];
}
/**
* 執(zhí)行FTP命令
*
* 本函數(shù)用于通過FTP客戶端執(zhí)行指定的FTP命令。支持的命令包括上傳、刪除文件以及連接關(guān)閉等。
*
* @param string $cmd 要執(zhí)行的FTP命令
* @param string $arg1 傳遞給FTP命令的參數(shù),具體取決于命令類型
* @return mixed 執(zhí)行結(jié)果,具體取決于FTP命令
*/
function ftpcmd($cmd, $arg1 = '') {
static $ftp;
$ftpconfig = getglobal('setting/ftp');
// 判斷FTP配置是否啟用以及FTP客戶端是否已初始化
if(empty($ftpconfig['on']) || empty($ftpconfig['host'])) {
// FTP未啟用或未配置返回錯(cuò)誤碼或0
return $cmd == 'error' ? -101 : 0;
} elseif($ftp == null) {
// FTP客戶端初始化
$ftp = & discuz_ftp::instance();
}
if(!$ftp->enabled) {
// FTP客戶端未啟用返回錯(cuò)誤信息
return $ftp->error();
} elseif($ftp->enabled && !$ftp->connectid) {
// FTP連接未建立則建立連接
$ftp->connect();
}
switch ($cmd) {
// 根據(jù)命令類型執(zhí)行相應(yīng)的操作
case 'upload' : return $ftp->upload(getglobal('setting/attachdir').'/'.$arg1, $arg1); break;
case 'delete' : return $ftp->ftp_delete($arg1); break;
case 'close' : return $ftp->ftp_close(); break;
case 'error' : return $ftp->error(); break;
case 'object' : return $ftp; break;
default : return false;
}
}
/**
* 檢查文件上傳權(quán)限
*
* 本函數(shù)用于檢查特定文件擴(kuò)展名和文件大小是否符合FTP上傳的規(guī)則設(shè)置。
*
* @param string $fileext 文件擴(kuò)展名
* @param int $filesize 文件大?。ㄒ宰止?jié)為單位)
* @return bool 文件是否具有上傳權(quán)限
*/
function ftpperm($fileext, $filesize) {
global $_G;
$return = false;
if($_G['setting']['ftp']['on']) {
// 檢查文件擴(kuò)展名和文件大小是否符合設(shè)置要求
if(((!$_G['setting']['ftp']['allowedexts'] && !$_G['setting']['ftp']['disallowedexts']) || ($_G['setting']['ftp']['allowedexts'] && in_array($fileext, $_G['setting']['ftp']['allowedexts'])) || ($_G['setting']['ftp']['disallowedexts'] && !in_array($fileext, $_G['setting']['ftp']['disallowedexts']) && (!$_G['setting']['ftp']['allowedexts'] || $_G['setting']['ftp']['allowedexts'] && in_array($fileext, $_G['setting']['ftp']['allowedexts'])))) && (!$_G['setting']['ftp']['minsize'] || $filesize >= $_G['setting']['ftp']['minsize'] * 1024)) {
$return = true;
}
}
return $return;
}
/**
* 將字符串從一個(gè)字符集轉(zhuǎn)換到另一個(gè)字符集。
*
* @param string $str 需要轉(zhuǎn)換的字符串。
* @param string $in_charset 輸入字符串的字符集。
* @param string $out_charset 輸出字符串的字符集,默認(rèn)為全局字符集。
* @param bool $ForceTable 是否強(qiáng)制使用轉(zhuǎn)換表,默認(rèn)為不強(qiáng)制。
* @return string 轉(zhuǎn)換后的字符串。
*/
function diconv($str, $in_charset, $out_charset = CHARSET, $ForceTable = FALSE) {
global $_G;
$in_charset = strtoupper($in_charset); // 將輸入字符集轉(zhuǎn)換為大寫
$out_charset = strtoupper($out_charset); // 將輸出字符集轉(zhuǎn)換為大寫
// 如果輸入字符串為空或字符集相同,則直接返回原字符串
if(empty($str) || $in_charset == $out_charset) {
return $str;
}
$out = ''; // 初始化輸出字符串
// 如果不強(qiáng)制使用轉(zhuǎn)換表,則嘗試使用iconv或mb_convert_encoding進(jìn)行轉(zhuǎn)換
if(!$ForceTable) {
if(function_exists('iconv')) {
$out = iconv($in_charset, $out_charset.'//IGNORE', $str);
} elseif(function_exists('mb_convert_encoding')) {
$out = mb_convert_encoding($str, $out_charset, $in_charset);
}
}
// 如果上述方法都未能成功轉(zhuǎn)換,則使用Chinese類進(jìn)行轉(zhuǎn)換
if($out == '') {
$chinese = new Chinese($in_charset, $out_charset, true);
$out = $chinese->Convert($str);
}
return $out; // 返回轉(zhuǎn)換后的字符串
}
/**
* 自動(dòng)調(diào)整寬度的開關(guān)狀態(tài)判定。
*
* @return int 返回寬度自動(dòng)調(diào)整的狀態(tài):0-關(guān)閉,1-開啟。
*/
function widthauto() {
global $_G;
// 若已明確禁用寬度自動(dòng)調(diào)整,則直接返回0
if($_G['disabledwidthauto']) {
return 0;
}
// 檢查是否已有寬度自動(dòng)調(diào)整的設(shè)置
if(!empty($_G['widthauto'])) {
return $_G['widthauto'] > 0 ? 1 : 0;
}
// 檢查cookie中是否有寬度自動(dòng)調(diào)整的設(shè)置
if($_G['setting']['switchwidthauto'] && !empty($_G['cookie']['widthauto'])) {
return $_G['cookie']['widthauto'] > 0 ? 1 : 0;
} else {
// 默認(rèn)返回寬度自動(dòng)調(diào)整的配置狀態(tài)
return $_G['setting']['allowwidthauto'] ? 0 : 1;
}
}
/**
* 對(duì)數(shù)組中的數(shù)值進(jìn)行重新分配和歸類。
*
* @param array $array 需要處理的數(shù)組,其值為數(shù)字。
* @return array 返回一個(gè)包含兩個(gè)數(shù)組的數(shù)組:第一個(gè)數(shù)組為數(shù)值數(shù)組,第二個(gè)數(shù)組為數(shù)值對(duì)應(yīng)的鍵名數(shù)組。
*/
function renum($array) {
$newnums = $nums = array();
foreach ($array as $id => $num) { // 遍歷數(shù)組,重新組織數(shù)據(jù)
$newnums[$num][] = $id;
$nums[$num] = $num;
}
return array($nums, $newnums);
}
/**
* 根據(jù)文件大小返回帶單位的可讀大小。
*
* @param int $size 文件大小,單位為字節(jié)。
* @return string 返回格式化后的文件大小字符串,單位為GB、MB、KB或Bytes。
*/
function sizecount($size) {
// 分別對(duì)應(yīng)GB、MB、KB,如果小于1KB則顯示為Bytes
if($size >= 1073741824) {
$size = round($size / 1073741824 * 100) / 100 . ' GB';
} elseif($size >= 1048576) {
$size = round($size / 1048576 * 100) / 100 . ' MB';
} elseif($size >= 1024) {
$size = round($size / 1024 * 100) / 100 . ' KB';
} else {
$size = intval($size) . ' Bytes';
}
return $size;
}
/**
* 交換兩個(gè)類的靜態(tài)變量存儲(chǔ)
*
* @param string $class1 第一個(gè)類名
* @param string $class2 第二個(gè)類名,默認(rèn)為空字符串
* @return string 交換后的類名存儲(chǔ)
*/
function swapclass($class1, $class2 = '') {
static $swapc = null; // 靜態(tài)變量存儲(chǔ),用于記錄上一次交換的類名
// 判斷并進(jìn)行類名交換
$swapc = isset($swapc) && $swapc != $class1 ? $class1 : $class2;
return $swapc;
}
/**
* 寫入日志
*
* @param string $file 日志文件名
* @param string $log 日志內(nèi)容
*/
function writelog($file, $log) {
// 調(diào)用helper_log類的writelog方法,進(jìn)行日志寫入
helper_log::writelog($file, $log);
}
/**
* 獲取狀態(tài)值中某一位的狀態(tài)
*
* @param int $status 總的狀態(tài)值
* @param int $position 指定的狀態(tài)位
* @return int 指定狀態(tài)位的狀態(tài)(1或0)
*/
function getstatus($status, $position) {
$t = (int)$status & pow(2, (int)$position - 1) ? 1 : 0; // 通過位運(yùn)算獲取指定狀態(tài)位的值
return $t;
}
/**
* 設(shè)置狀態(tài)值中某一位的狀態(tài)
*
* @param int $position 指定的狀態(tài)位
* @param int $value 指定狀態(tài)位的新值
* @param int $baseon 基礎(chǔ)狀態(tài)值,默認(rèn)為null
* @return int 更新后的狀態(tài)值
*/
function setstatus($position, $value, $baseon = null) {
$t = pow(2, $position - 1); // 計(jì)算指定狀態(tài)位的掩碼
if($value) {
$t = $baseon | $t; // 設(shè)置指定狀態(tài)位為1
} elseif ($baseon !== null) {
$t = $baseon & ~$t; // 清除指定狀態(tài)位為0
} else {
$t = ~$t; // 取反以設(shè)置所有位,除了指定狀態(tài)位
}
return $t & 0xFFFF; // 保證返回的狀態(tài)值在16位范圍內(nèi)
}
/**
* 添加通知
*
* @param int $touid 接收通知的用戶ID
* @param string $type 通知類型
* @param string $note 通知內(nèi)容
* @param array $notevars 通知內(nèi)容中的變量數(shù)組,默認(rèn)為空數(shù)組
* @param int $system 是否為系統(tǒng)通知,默認(rèn)為0
* @return mixed 添加結(jié)果,通常為布爾值或特定的標(biāo)識(shí)符
*/
function notification_add($touid, $type, $note, $notevars = array(), $system = 0) {
return helper_notification::notification_add($touid, $type, $note, $notevars, $system);
}
/**
* 添加管理通知
*
* @param string $type 通知類型
* @param int $from_num 發(fā)送方數(shù)量
* @param array $langvar 語言變量數(shù)組
*/
function manage_addnotify($type, $from_num = 0, $langvar = array()) {
helper_notification::manage_addnotify($type, $from_num, $langvar);
}
/**
* 發(fā)送私信
*
* @param int $toid 接收私信的用戶ID
* @param string $subject 私信主題
* @param string $message 私信內(nèi)容
* @param string $fromid 發(fā)送私信的用戶ID,默認(rèn)為空字符串
* @param int $replypmid 回復(fù)的私信ID,默認(rèn)為0
* @param int $isusername 是否使用用戶名作為發(fā)送者,默認(rèn)為0
* @param int $type 私信類型,默認(rèn)為0
* @return mixed 發(fā)送結(jié)果,通常為布爾值或特定的標(biāo)識(shí)符
*/
function sendpm($toid, $subject, $message, $fromid = '', $replypmid = 0, $isusername = 0, $type = 0) {
return helper_pm::sendpm($toid, $subject, $message, $fromid, $replypmid, $isusername, $type);
}
/**
* 獲取用戶組圖標(biāo)
*
* @param string $groupid 用戶組ID
* @param int $return 是否返回圖標(biāo)HTML,默認(rèn)為0(即直接輸出)
*/
function g_icon($groupid, $return = 0) {
global $_G;
// 判斷用戶組圖標(biāo)是否存在
if(empty($_G['cache']['usergroups'][$groupid]['icon'])) {
$s = '';
} else {
// 根據(jù)圖標(biāo)地址生成完整的HTML標(biāo)簽
if(preg_match('/^https?:\/\//is', $_G['cache']['usergroups'][$groupid]['icon'])) {
$s = '<img src="'.$_G['cache']['usergroups'][$groupid]['icon'].'" alt="" class="vm" />';
} else {
$s = '<img src="'.$_G['setting']['attachurl'].'common/'.$_G['cache']['usergroups'][$groupid]['icon'].'" alt="" class="vm" />';
}
}
// 根據(jù)$return參數(shù)決定是返回還是輸出圖標(biāo)HTML
if($return) {
return $s;
} else {
echo $s;
}
}
/**
* 更新DIY模板
* @param string $targettplname 目標(biāo)模板名稱
* @param string $tpldirectory 模板目錄
* @return boolean 更新結(jié)果,成功返回true,失敗返回false
*/
function updatediytemplate($targettplname = '', $tpldirectory = '') {
$r = false;
$alldata = !empty($targettplname) ? array( C::t('common_diy_data')->fetch_diy($targettplname, $tpldirectory)) : C::t('common_diy_data')->range();
require_once libfile('function/portalcp');
foreach($alldata as $value) {
$r = save_diy_data($value['tpldirectory'], $value['primaltplname'], $value['targettplname'], dunserialize($value['diycontent']));
}
return $r;
}
/**
* 根據(jù)主題ID獲取帖子表
* @param array $tids 主題ID數(shù)組
* @param int $primary 主表標(biāo)識(shí),默認(rèn)為0
* @return string 帖子表名稱
*/
function getposttablebytid($tids, $primary = 0) {
return table_forum_post::getposttablebytid($tids, $primary);
}
/**
* 獲取帖子表
* @param int $tableid 表ID,默認(rèn)為0
* @param bool $prefix 表前綴,默認(rèn)為false
* @return string 帖子表名稱
*/
function getposttable($tableid = 0, $prefix = false) {
return table_forum_post::getposttable($tableid, $prefix);
}
/**
* 操作緩存內(nèi)存
* @param string $cmd 操作命令
* @param string|array $key 鍵名,對(duì)于某些命令可以是鍵名數(shù)組
* @param string|array $value 對(duì)于設(shè)置、添加等操作的值
* @param int $ttl 時(shí)間生存期,默認(rèn)為0
* @param string $prefix 鍵的前綴
* @return mixed 操作結(jié)果,具體取決于執(zhí)行的命令
*/
function memory($cmd, $key='', $value='', $ttl = 0, $prefix = '') {
static $supported_command = array(
'set', 'add', 'get', 'rm', 'inc', 'dec', 'exists',
'incex', /* 存在時(shí)才inc */
'sadd', 'srem', 'scard', 'smembers', 'sismember',
'hmset', 'hgetall', 'hexists', 'hget',
'eval',
'zadd', 'zcard', 'zrem', 'zscore', 'zrevrange', 'zincrby', 'zrevrangewithscore' /* 帶score返回 */,
'pipeline', 'commit', 'discard'
);
if($cmd == 'check') {
return C::memory()->enable ? C::memory()->type : '';
} elseif(C::memory()->enable && in_array($cmd, $supported_command)) {
if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
if(is_array($key)) {
foreach($key as $k) {
C::memory()->debug[$cmd][] = ($cmd == 'get' || $cmd == 'rm' || $cmd == 'add' ? $value : '').$prefix.$k;
}
} else {
if ($cmd === 'hget') {
C::memory()->debug[$cmd][] = $prefix . $key . "->" . $value;
} elseif ($cmd === 'eval') {
C::memory()->debug[$cmd][] = $key . "->" . $ttl;
} else {
C::memory()->debug[$cmd][] = ($cmd == 'get' || $cmd == 'rm' || $cmd == 'add' ? $value : '').$prefix.$key;
}
}
}
switch ($cmd) {
// 執(zhí)行具體的緩存操作
case 'set': return C::memory()->set($key, $value, $ttl, $prefix); break;
case 'add': return C::memory()->add($key, $value, $ttl, $prefix); break;
case 'get': return C::memory()->get($key, $value/*prefix*/); break;
case 'rm': return C::memory()->rm($key, $value/*prefix*/); break;
case 'exists': return C::memory()->exists($key, $value/*prefix*/); break;
case 'inc': return C::memory()->inc($key, $value ? $value : 1, $prefix); break;
case 'incex': return C::memory()->incex($key, $value ? $value : 1, $prefix); break;
case 'dec': return C::memory()->dec($key, $value ? $value : 1, $prefix); break;
case 'sadd': return C::memory()->sadd($key, $value, $prefix); break;
case 'srem': return C::memory()->srem($key, $value, $prefix); break;
case 'scard': return C::memory()->scard($key, $value/*prefix*/); break;
case 'smembers': return C::memory()->smembers($key, $value/*prefix*/); break;
case 'sismember': return C::memory()->sismember($key, $value, $prefix); break;
case 'hmset': return C::memory()->hmset($key, $value, $prefix); break;
case 'hgetall': return C::memory()->hgetall($key, $value/*prefix*/); break;
case 'hexists': return C::memory()->hexists($key, $value/*field*/, $prefix); break;
case 'hget': return C::memory()->hget($key, $value/*field*/, $prefix); break;
case 'eval': return C::memory()->evalscript($key/*script*/, $value/*args*/, $ttl/*sha key*/, $prefix); break;
case 'zadd': return C::memory()->zadd($key, $value, $ttl/*score*/, $prefix); break;
case 'zrem': return C::memory()->zrem($key, $value, $prefix); break;
case 'zscore': return C::memory()->zscore($key, $value, $prefix); break;
case 'zcard': return C::memory()->zcard($key, $value/*prefix*/); break;
case 'zrevrange': return C::memory()->zrevrange($key, $value/*start*/, $ttl/*end*/, $prefix); break;
case 'zrevrangewithscore': return C::memory()->zrevrange($key, $value/*start*/, $ttl/*end*/, $prefix, true); break;
case 'zincrby': return C::memory()->zincrby($key, $value/*member*/, $ttl ? $ttl : 1/*to increase*/, $prefix); break;
case 'pipeline': return C::memory()->pipeline(); break;
case 'commit': return C::memory()->commit(); break;
case 'discard': return C::memory()->discard(); break;
}
}
return null;
}
/**
* 檢查IP是否在訪問列表中
* @param string $ip 要檢查的IP地址
* @param array $accesslist 訪問列表,包含允許或禁止的IP范圍
* @return bool 返回IP是否被允許訪問
*/
function ipaccess($ip, $accesslist) {
return ip::checkaccess($ip, $accesslist);
}
/**
* 檢查IP是否被禁止
* @param string $ip 要檢查的IP地址
* @return bool 返回IP是否被禁止
*/
function ipbanned($ip) {
return ip::checkbanned($ip);
}
/**
* 根據(jù)條件獲取記錄數(shù)
* @param string $tablename 表名
* @param string|array $condition 查詢條件,可以是字符串或條件數(shù)組
* @return int 返回符合條件的記錄數(shù)
*/
function getcount($tablename, $condition) {
// 根據(jù)條件構(gòu)建SQL WHERE子句
if(empty($condition)) {
$where = '1';
} elseif(is_array($condition)) {
$where = DB::implode_field_value($condition, ' AND ');
} else {
$where = $condition;
}
// 執(zhí)行SQL查詢并返回記錄數(shù)
$ret = intval(DB::result_first("SELECT COUNT(*) AS num FROM ".DB::table($tablename)." WHERE $where"));
return $ret;
}
/**
* 顯示系統(tǒng)消息
* @param string $message 要顯示的消息內(nèi)容
*/
function sysmessage($message) {
helper_sysmessage::show($message);
}
/**
* 檢查用戶組權(quán)限
* @param string $permstr 權(quán)限字符串
* @param int $groupid 用戶組ID,默認(rèn)為0
* @return bool 返回用戶組是否有對(duì)應(yīng)的權(quán)限
*/
function forumperm($permstr, $groupid = 0) {
global $_G;
$groupidarray = array($_G['groupid']);
// 如果指定用戶組ID,檢查該用戶組是否有權(quán)限
if($groupid) {
return preg_match("/(^|\t)(".$groupid.")(\t|$)/", $permstr);
}
// 構(gòu)建用戶所屬用戶組ID數(shù)組
$groupterms = dunserialize(getuserprofile('groupterms'));
foreach(explode("\t", $_G['member']['extgroupids']) as $extgroupid) {
if($extgroupid = intval(trim($extgroupid))) {
if($groupterms['ext'][$extgroupid] && $groupterms['ext'][$extgroupid] < TIMESTAMP){
continue;
}
$groupidarray[] = $extgroupid;
}
}
// 檢查驗(yàn)證組權(quán)限
if($_G['setting']['verify']['enabled']) {
getuserprofile('verify1');
foreach($_G['setting']['verify'] as $vid => $verify) {
if($verify['available'] && $_G['member']['verify'.$vid] == 1) {
$groupidarray[] = 'v'.$vid;
}
}
}
return preg_match("/(^|\t)(".implode('|', $groupidarray).")(\t|$)/", $permstr);
}
/**
* 檢查用戶權(quán)限
* @param string $perm 權(quán)限標(biāo)識(shí)
* @return bool 返回用戶是否具有該權(quán)限
*/
function checkperm($perm) {
global $_G;
// 在后臺(tái)則直接返回true,否則檢查用戶組權(quán)限設(shè)置
return defined('IN_ADMINCP') ? true : (empty($_G['group'][$perm])?'':$_G['group'][$perm]);
}
/**
* 檢查特定時(shí)間段內(nèi)用戶是否有權(quán)限發(fā)帖或執(zhí)行某些操作
*
* @param string $periods 指定的時(shí)期類型,如 'postmodperiods' 或 'postbanperiods'
* @param int $showmessage 當(dāng)檢查失敗時(shí),是否顯示錯(cuò)誤消息。1為顯示,其他為不顯示。
* @return bool 返回檢查結(jié)果,如果通過檢查返回false,否則返回true。
*/
function periodscheck($periods, $showmessage = 1) {
global $_G;
// 檢查是否忽略特定IP或地區(qū)發(fā)帖限制
if(($periods == 'postmodperiods' || $periods == 'postbanperiods') && (getglobal('setting/postignorearea') || getglobal('setting/postignoreip'))) {
// 檢查IP是否在忽略列表中
if($_G['setting']['postignoreip']) {
foreach(explode("\n", $_G['setting']['postignoreip']) as $ctrlip) {
if(preg_match("/^(".preg_quote(($ctrlip = trim($ctrlip)), '/').")/", $_G['clientip'])) {
return false;
break;
}
}
}
// 檢查地區(qū)是否在忽略列表中
if($_G['setting']['postignorearea']) {
$location = $whitearea = '';
require_once libfile('function/misc');
$location = trim(convertip($_G['clientip']));
if($location) {
$whitearea = preg_quote(trim($_G['setting']['postignorearea']), '/');
$whitearea = str_replace(array("\\*"), array('.*'), $whitearea);
$whitearea = '.*'.$whitearea.'.*';
$whitearea = '/^('.str_replace(array("\r\n", ' '), array('.*|.*', ''), $whitearea).')$/i';
if(@preg_match($whitearea, $location)) {
return false;
}
}
}
}
// 檢查用戶組是否受時(shí)間段控制以及是否在受控時(shí)間段內(nèi)
if(!$_G['group']['disableperiodctrl'] && $_G['setting'][$periods]) {
$now = dgmdate(TIMESTAMP, 'G.i', $_G['setting']['timeoffset']);
foreach(explode("\r\n", str_replace(':', '.', $_G['setting'][$periods])) as $period) {
list($periodbegin, $periodend) = explode('-', $period);
if(($periodbegin > $periodend && ($now >= $periodbegin || $now < $periodend)) || ($periodbegin < $periodend && $now >= $periodbegin && $now < $periodend)) {
$banperiods = str_replace("\r\n", ', ', $_G['setting'][$periods]);
if($showmessage) {
showmessage('period_nopermission', NULL, array('banperiods' => $banperiods), array('login' => 1));
} else {
return TRUE;
}
}
}
}
return FALSE;
}
/**
* 檢查新用戶是否滿足發(fā)帖條件
*
* @param int $return 是否返回檢查結(jié)果,0為不返回,其他為返回結(jié)果。
* @return bool 如果檢查通過返回true,否則根據(jù)$return參數(shù)決定是否顯示錯(cuò)誤信息并返回false。
*/
function cknewuser($return=0) {
global $_G;
$result = true;
if(!$_G['uid']) return true;
if(checkperm('disablepostctrl')) {
return $result;
}
$ckuser = $_G['member'];
// 檢查新用戶發(fā)帖限制
if($_G['setting']['newbiespan'] && $_G['timestamp']-$ckuser['regdate']<$_G['setting']['newbiespan']*60) {
if(empty($return)) showmessage('no_privilege_newbiespan', '', array('newbiespan' => $_G['setting']['newbiespan']), array());
$result = false;
}
// 檢查是否設(shè)置了需要驗(yàn)證頭像的條件
if($_G['setting']['need_avatar'] && empty($ckuser['avatarstatus'])) {
if(empty($return)) showmessage('no_privilege_avatar', '', array(), array());
$result = false;
}
// 檢查是否設(shè)置了需要驗(yàn)證手機(jī)的條件
if($_G['setting']['need_secmobile'] && empty($ckuser['secmobilestatus'])) {
if(empty($return)) showmessage('no_privilege_secmobile', '', array(), array());
$result = false;
}
// 檢查是否設(shè)置了需要驗(yàn)證郵箱的條件
if($_G['setting']['need_email'] && empty($ckuser['emailstatus'])) {
if(empty($return)) showmessage('no_privilege_email', '', array(), array());
$result = false;
}
// 檢查是否設(shè)置了需要達(dá)到一定好友數(shù)的條件
if($_G['setting']['need_friendnum']) {
space_merge($ckuser, 'count');
if($ckuser['friends'] < $_G['setting']['need_friendnum']) {
if(empty($return)) showmessage('no_privilege_friendnum', '', array('friendnum' => $_G['setting']['need_friendnum']), array());
$result = false;
}
}
return $result;
}
/**
* 記錄用戶行為日志
*
* @param int $uid 用戶ID
* @param string $action 用戶行為描述
* @return mixed 執(zhí)行結(jié)果
*/
function useractionlog($uid, $action) {
return helper_log::useractionlog($uid, $action);
}
/**
* 獲取用戶行為日志
*
* @param mixed $var 變量,用于獲取特定的日志信息
* @return mixed 返回用戶行為日志信息
*/
function getuseraction($var) {
return helper_log::getuseraction($var);
}
/**
* 獲取用戶應(yīng)用信息
*
* @param int $panel 應(yīng)用面板ID,默認(rèn)為0
* @return string 返回用戶應(yīng)用信息
*/
function getuserapp($panel = 0) {
return '';
}
/**
* 獲取我的應(yīng)用圖標(biāo)路徑
*
* @param int $appid 應(yīng)用ID
* @param int $iconstatus 圖標(biāo)狀態(tài),默認(rèn)為0
* @return string 返回應(yīng)用圖標(biāo)路徑
*/
function getmyappiconpath($appid, $iconstatus=0) {
return '';
}
/**
* 獲取過期時(shí)間
*
* @return int 返回過期時(shí)間戳
*/
function getexpiration() {
global $_G;
$date = getdate($_G['timestamp']);
return mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']) + 86400;
}
/**
* 將帶單位的字節(jié)值轉(zhuǎn)換為純數(shù)字字節(jié)值。
* 支持的單位有:B, KB, MB, GB。
*
* @param string $val 待轉(zhuǎn)換的字節(jié)值,可以帶單位。
* @return int 轉(zhuǎn)換后的純數(shù)字字節(jié)值。
*/
function return_bytes($val) {
$last = strtolower($val[strlen($val)-1]); // 獲取并轉(zhuǎn)換單位字符為小寫
if (!is_numeric($val)) {
$val = substr(trim($val), 0, -1); // 移除單位字符,準(zhǔn)備計(jì)算
}
switch($last) { // 根據(jù)單位進(jìn)行轉(zhuǎn)換
case 'g': $val *= 1024;
case 'm': $val *= 1024;
case 'k': $val *= 1024;
}
return $val; // 返回轉(zhuǎn)換后的字節(jié)值
}
/**
* 檢查給定的主機(jī)名是否在白名單中。
*
* @param string $host 待檢查的主機(jī)名。
* @return bool 如果主機(jī)名在白名單中,則返回true;否則返回false。
*/
function iswhitelist($host) {
global $_G;
static $iswhitelist = array(); // 靜態(tài)數(shù)組用于緩存已檢查的主機(jī)名結(jié)果
if(isset($iswhitelist[$host])) {
return $iswhitelist[$host]; // 如果已檢查過該主機(jī)名,直接返回之前的結(jié)果
}
$hostlen = strlen($host); // 計(jì)算主機(jī)名長度
$iswhitelist[$host] = false; // 默認(rèn)設(shè)置為不在白名單中
if(!$_G['cache']['domainwhitelist']) {
loadcache('domainwhitelist'); // 加載白名單緩存
}
if(is_array($_G['cache']['domainwhitelist'])) foreach($_G['cache']['domainwhitelist'] as $val) { // 遍歷白名單檢查是否匹配
$domainlen = strlen($val);
if($domainlen > $hostlen) {
continue; // 如果白名單中的域名長度大于待檢查的主機(jī)名長度,跳過檢查
}
if(substr($host, -$domainlen) == $val) {
$iswhitelist[$host] = true; // 如果匹配成功,設(shè)置結(jié)果為在白名單中,并結(jié)束循環(huán)
break;
}
}
if($iswhitelist[$host] == false) {
$iswhitelist[$host] = $host == $_SERVER['HTTP_HOST']; // 如果未在白名單中找到,檢查是否與當(dāng)前HTTP_HOST匹配
}
return $iswhitelist[$host]; // 返回檢查結(jié)果
}
/**
* 根據(jù)附件ID獲取附件表名稱。
*
* @param int $aid 附件ID。
* @return string 返回附件存儲(chǔ)的表名。
*/
function getattachtablebyaid($aid) {
$attach = C::t('forum_attachment')->fetch($aid); // 通過附件ID獲取附件信息
$tableid = $attach['tableid']; // 獲取附件存儲(chǔ)的表ID
return 'forum_attachment_'.($tableid >= 0 && $tableid < 10 ? intval($tableid) : 'unused'); // 返回附件表名稱,對(duì)于無效的表ID返回'unused'
}
/**
* 根據(jù)主題ID獲取附件表ID。
*
* @param string $tid 主題ID。
* @return int 返回附件存儲(chǔ)的表ID。
*/
function getattachtableid($tid) {
$tid = (string)$tid; // 確保主題ID為字符串類型
return intval($tid[strlen($tid)-1]); // 返回最后一位字符作為表ID
}
/**
* 根據(jù)主題ID獲取附件表名稱。
*
* @param string $tid 主題ID。
* @return string 返回附件存儲(chǔ)的表名。
*/
function getattachtablebytid($tid) {
return 'forum_attachment_'.getattachtableid($tid); // 調(diào)用getattachtableid函數(shù)獲取表ID,并拼接成表名
}
/**
* 根據(jù)帖子ID獲取附件表名稱。
*
* @param int $pid 帖子ID。
* @return string 返回附件存儲(chǔ)的表名。
*/
function getattachtablebypid($pid) {
$tableid = DB::result_first("SELECT tableid FROM ".DB::table('forum_attachment')." WHERE pid='$pid' LIMIT 1"); // 通過帖子ID查詢附件表ID
return 'forum_attachment_'.($tableid >= 0 && $tableid < 10 ? intval($tableid) : 'unused'); // 返回附件表名稱,對(duì)于無效的表ID返回'unused'
}
/**
* 為指定用戶(默認(rèn)為當(dāng)前用戶)生成一個(gè)新的附件ID。
*
* @param int $uid 用戶ID,默認(rèn)為0,表示當(dāng)前用戶。
* @return int 返回新生成的附件ID。
*/
function getattachnewaid($uid = 0) {
global $_G;
$uid = !$uid ? $_G['uid'] : $uid; // 如果未指定用戶ID,則使用當(dāng)前用戶ID
return C::t('forum_attachment')->insert(array('tid' => 0, 'pid' => 0, 'uid' => $uid, 'tableid' => 127), true); // 插入新附件記錄,并返回新附件ID
}
/**
* 獲取SEO設(shè)置
* @param string $page 頁面名稱
* @param array $data 附加數(shù)據(jù)數(shù)組
* @param array $defset 默認(rèn)設(shè)置數(shù)組
* @return mixed 返回SEO設(shè)置
*/
function get_seosetting($page, $data = array(), $defset = array()) {
return helper_seo::get_seosetting($page, $data, $defset);
}
/**
* 生成圖片縮略圖名稱
* @param string $fileStr 原始文件名
* @param string $extend 縮略圖文件擴(kuò)展名,默認(rèn)為'.thumb.jpg'
* @param bool $holdOldExt 是否保留原文件擴(kuò)展名,默認(rèn)為true
* @return string 返回縮略圖文件名
*/
function getimgthumbname($fileStr, $extend='.thumb.jpg', $holdOldExt=true) {
if(empty($fileStr)) {
return '';
}
if(!$holdOldExt) {
$fileStr = substr($fileStr, 0, strrpos($fileStr, '.'));
}
$extend = strstr($extend, '.') ? $extend : '.'.$extend;
return $fileStr.$extend;
}
/**
* 更新審核狀態(tài)
* @param string $idtype ID類型
* @param array/int $ids 需要更新審核狀態(tài)的ID或ID數(shù)組
* @param int $status 新的審核狀態(tài),默認(rèn)為0
*/
function updatemoderate($idtype, $ids, $status = 0) {
helper_form::updatemoderate($idtype, $ids, $status);
}
/**
* 用戶應(yīng)用提示函數(shù)
*/
function userappprompt() {
}
/**
* 轉(zhuǎn)換整數(shù),支持處理數(shù)組
* @param mixed $int 需要轉(zhuǎn)換的整數(shù)或數(shù)組
* @param bool $allowarray 是否允許輸入數(shù)組,默認(rèn)為false
* @return mixed 返回轉(zhuǎn)換后的整數(shù)或數(shù)組
*/
function dintval($int, $allowarray = false) {
$ret = intval($int);
if($int == '' || $int == $ret || !$allowarray && is_array($int)) return $ret;
if($allowarray && is_array($int)) {
foreach($int as &$v) {
$v = dintval($v, true);
}
return $int;
} elseif($int <= 0xffffffff) {
$l = strlen($int);
$m = substr($int, 0, 1) == '-' ? 1 : 0;
if(($l - $m) === strspn($int,'0987654321', $m)) {
return $int;
}
}
return $ret;
}
/**
* 生成搜索簽名URL
* @return array 返回生成的URL數(shù)組
*/
function makeSearchSignUrl() {
return array();
}
/**
* 獲取相關(guān)鏈接
* @param string $extent 擴(kuò)展參數(shù)
* @return mixed 返回相關(guān)鏈接
*/
function get_related_link($extent) {
return helper_seo::get_related_link($extent);
}
/**
* 解析相關(guān)鏈接
* @param string $content 待解析的內(nèi)容
* @param string $extent 擴(kuò)展參數(shù)
* @return mixed 返回解析后的內(nèi)容
*/
function parse_related_link($content, $extent) {
return helper_seo::parse_related_link($content, $extent);
}
/**
* 檢查DIY權(quán)限
* @param array $topic 主題信息數(shù)組
* @param string $flag 指定檢查的權(quán)限類型
* @return bool 返回權(quán)限檢查結(jié)果
*/
function check_diy_perm($topic = array(), $flag = '') {
static $ret = array();
if(empty($ret)) {
global $_G;
$common = !empty($_G['style']['tplfile']) || getgpc('inajax');
$blockallow = getstatus(getglobal('member/allowadmincp'), 4) || getstatus(getglobal('member/allowadmincp'), 5) || getstatus(getglobal('member/allowadmincp'), 6);
$ret['data'] = $common && $blockallow;
$ret['layout'] = $common && (!empty($_G['group']['allowdiy']) || (
CURMODULE === 'topic' && ($_G['group']['allowmanagetopic'] || $_G['group']['allowaddtopic'] && $topic && $topic['uid'] == $_G['uid'])
));
}
return empty($flag) ? $ret['data'] || $ret['layout'] : $ret[$flag];
}
/**
* 對(duì)字符串進(jìn)行加密或解密操作
*
* @param string $string 需要進(jìn)行加密或解密的字符串
* @param string $operation 操作類型,'DECODE'為解密,其他為加密,默認(rèn)為'DECODE'
* @param string $key 加密解密使用的密鑰,默認(rèn)使用全局authkey
* @return string 返回解密后的字符串或加密后的字符串
*/
function strhash($string, $operation = 'DECODE', $key = '') {
// 根據(jù)提供的密鑰生成實(shí)際使用的密鑰
$key = md5($key != '' ? $key : getglobal('authkey'));
if($operation == 'DECODE') {
// 對(duì)加密字符串進(jìn)行解密操作
$hashcode = gzuncompress(base64_decode($string));
$string = substr($hashcode, 0, -16);
$hash = substr($hashcode, -16);
unset($hashcode);
}
// 生成驗(yàn)證字符串的密鑰
$vkey = substr(md5($string.substr($key, 0, 16)), 4, 8).substr(md5($string.substr($key, 16, 16)), 18, 8);
if($operation == 'DECODE') {
// 解密操作時(shí),驗(yàn)證密鑰是否正確,正確則返回解密字符串,否則返回空
return $hash == $vkey ? $string : '';
}
// 加密操作時(shí),返回加密后的字符串
return base64_encode(gzcompress($string.$vkey));
}
/**
* 嘗試反序列化一個(gè)字符串,支持處理被轉(zhuǎn)義的字符串
*
* @param string $data 需要反序列化的字符串
* @return mixed 反序列化后的數(shù)據(jù),失敗時(shí)返回原字符串或空數(shù)組
*/
function dunserialize($data) {
// 如果輸入就是數(shù)組,直接返回
if(is_array($data)) {
$ret = $data;
} elseif(($ret = unserialize($data)) === false) {
// 如果常規(guī)反序列化失敗,嘗試去除反斜杠后再次反序列化
$ret = unserialize(stripslashes($data));
}
return $ret;
}
/**
* 獲取瀏覽器版本信息
*
* @param string $type 需要獲取的瀏覽器類型,若不指定則返回所有瀏覽器類型及其版本的數(shù)組
* @return mixed 返回指定瀏覽器類型的版本號(hào),若未指定則返回所有瀏覽器類型及其版本的數(shù)組
*/
function browserversion($type = '') {
static $return = array();
static $types = array('ie' => 'msie', 'firefox' => '', 'chrome' => '', 'opera' => '', 'safari' => '', 'mozilla' => '', 'webkit' => '', 'maxthon' => '', 'qq' => 'qqbrowser');
if(!$return) {
// 初始化瀏覽器版本信息
$useragent = strtolower($_SERVER['HTTP_USER_AGENT']);
$other = 1;
foreach($types as $i => $v) {
$v = $v ? $v : $i;
if(strpos($useragent, $v) !== false) {
// 檢測并記錄瀏覽器版本
preg_match('/'.$v.'(\/|\s)([\d\.]+)/i', $useragent, $matches);
$ver = $matches[2];
$other = $ver !== 0 && $v != 'mozilla' ? 0 : $other;
} else {
$ver = 0;
}
$return[$i] = $ver;
}
$return['other'] = $other;
}
return isset($return[$type]) ? $return[$type] : $return;
}
/**
* 獲取當(dāng)前語言環(huán)境
*
* @return string 返回當(dāng)前語言環(huán)境的標(biāo)識(shí)符
*/
function currentlang() {
$charset = strtoupper(CHARSET);
if($charset == 'GBK') {
return 'SC_GBK';
} elseif($charset == 'BIG5') {
return 'TC_BIG5';
} elseif($charset == 'UTF-8') {
global $_G;
// 根據(jù)配置確定是簡體還是繁體中文環(huán)境
if($_G['config']['output']['language'] == 'zh_cn') {
return 'SC_UTF8';
} elseif ($_G['config']['output']['language'] == 'zh_tw') {
return 'TC_UTF8';
}
} else {
return '';
}
}
/**
* 根據(jù)給定的模式替換字符串。
*
* 這個(gè)函數(shù)是為了處理PHP版本兼容性問題而設(shè)計(jì)的。如果PHP版本小于7.0.0,它會(huì)使用
* PHP內(nèi)置的preg_replace函數(shù)進(jìn)行模式替換;如果PHP版本大于等于7.0.0,則會(huì)調(diào)用
* 自定義的_dpreg_replace函數(shù)以處理可能的preg_replace行為變化。
*
* @param string $pattern 需要匹配的模式。
* @param string $replacement 用于替換匹配到模式的字符串。
* @param string $subject 待處理的源字符串。
* @param int $limit 替換的次數(shù)限制,默認(rèn)為-1,表示不限制替換次數(shù)。
* @param int &$count 替換操作執(zhí)行的次數(shù),如果提供,會(huì)在此函數(shù)執(zhí)行后被設(shè)置為實(shí)際替換的次數(shù)。
* @return string 替換后的字符串。
*/
function dpreg_replace($pattern, $replacement, $subject, $limit = -1, &$count = null) {
// 檢查PHP版本,以決定使用哪個(gè)函數(shù)進(jìn)行模式替換
if(PHP_VERSION < '7.0.0') {
return preg_replace($pattern, $replacement, $subject, $limit, $count);
} else {
// PHP版本大于等于7.0.0時(shí),使用自定義的替換函數(shù)
require_once libfile('function/preg');
return _dpreg_replace($pattern, $replacement, $subject, $limit, $count);
}
}
?>