DiscuzX /source/function/function_core.php通用核心函数库文件分析
。。。
1 <?php 2 3 /** 4 * [Discuz!] (C)2001-2099 Comsenz Inc. 5 * This is NOT a freeware, use is subject to license terms 6 * 7 * $Id: function_core.php 28890 2012-03-19 02:05:42Z liudongdong $ 8 */ 9 10 if(!defined('IN_DISCUZ')) { 11 exit('Access Denied'); 12 } 13 14 //通用函数集合 15 define('DISCUZ_CORE_FUNCTION', true); 16 17 /** 18 * 系统错误处理 19 * @param <type> $message 错误信息 20 * @param <type> $show 是否显示信息 21 * @param <type> $save 是否存入日志 22 * @param <type> $halt 是否中断访问 23 */ 24 function system_error($message, $show = true, $save = true, $halt = true) { 25 require_once libfile('class/error'); 26 discuz_error::system_error($message, $show, $save, $halt); 27 } 28 29 /** 30 * 更新 session 31 * @global <type> $_G 32 * @staticvar boolean $updated 33 * @param boolean $force 34 * @return boolean 35 */ 36 function updatesession($force = false) { 37 38 global $_G; 39 static $updated = false; 40 41 if(!$updated) { 42 if($_G['uid']) { 43 if($_G['cookie']['ulastactivity']) { 44 $ulastactivity = authcode($_G['cookie']['ulastactivity'], 'DECODE'); 45 } else { 46 $ulastactivity = getuserprofile('lastactivity'); 47 dsetcookie('ulastactivity', authcode($ulastactivity, 'ENCODE'), 31536000); 48 } 49 } 50 $discuz = & discuz_core::instance(); 51 //note 更新在线时间 52 $oltimespan = $_G['setting']['oltimespan']; 53 $lastolupdate = $discuz->session->var['lastolupdate']; 54 if($_G['uid'] && $oltimespan && TIMESTAMP - ($lastolupdate ? $lastolupdate : $ulastactivity) > $oltimespan * 60) { 55 DB::query("UPDATE ".DB::table('common_onlinetime')." 56 SET total=total+'$oltimespan', thismonth=thismonth+'$oltimespan', lastupdate='" . TIMESTAMP . "' 57 WHERE uid='{$_G['uid']}'"); 58 if(!DB::affected_rows()) { 59 DB::insert('common_onlinetime', array( 60 'uid' => $_G['uid'], 61 'thismonth' => $oltimespan, 62 'total' => $oltimespan, 63 'lastupdate' => TIMESTAMP, 64 )); 65 } 66 $discuz->session->set('lastolupdate', TIMESTAMP); 67 } 68 foreach($discuz->session->var as $k => $v) { 69 if(isset($_G['member'][$k]) && $k != 'lastactivity') { 70 $discuz->session->set($k, $_G['member'][$k]); 71 } 72 } 73 74 foreach($_G['action'] as $k => $v) { 75 $discuz->session->set($k, $v); 76 } 77 78 $discuz->session->update(); 79 80 $updated = true; 81 82 if($_G['uid'] && TIMESTAMP - $ulastactivity > 21600) { 83 if($oltimespan && TIMESTAMP - $ulastactivity > 43200) { 84 $total = DB::result_first("SELECT total FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'"); 85 DB::update('common_member_count', array('oltime' => round(intval($total) / 60)), "uid='$_G[uid]'", 1); 86 } 87 dsetcookie('ulastactivity', authcode(TIMESTAMP, 'ENCODE'), 31536000); 88 DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1); 89 } 90 } 91 return $updated; 92 } 93 94 /** 95 * 获取 microtime float 数值,为了兼容php4 96 * @return <float> 97 */ 98 function dmicrotime() { 99 return array_sum(explode(' ', microtime())); 100 } 101 102 /** 103 * 设置全局 $_G 中的变量 104 * @global <array> $_G 105 * @param <string> $key 键 106 * @param <string> $value 值 107 * @param <mix> $group 组(准备废弃,尽量不用) 108 * @return true 109 * 110 * @example 111 * setglobal('test', 1); // $_G['test'] = 1; 112 * setglobal('config/test/abc') = 2; //$_G['config']['test']['abc'] = 2; 113 * 114 */ 115 function setglobal($key , $value, $group = null) { 116 global $_G; 117 $k = explode('/', $group === null ? $key : $group.'/'.$key); 118 switch (count($k)) { 119 case 1: $_G[$k[0]] = $value; break; 120 case 2: $_G[$k[0]][$k[1]] = $value; break; 121 case 3: $_G[$k[0]][$k[1]][$k[2]] = $value; break; 122 case 4: $_G[$k[0]][$k[1]][$k[2]][$k[3]] = $value; break; 123 case 5: $_G[$k[0]][$k[1]][$k[2]][$k[3]][$k[4]] =$value; break; 124 } 125 return true; 126 } 127 128 /** 129 * 获取全局变量 $_G 当中的某个数值 130 * @global $_G 131 * @param <type> $key 132 * @param <type> $group 计划废弃的参数,不建议使用 133 * @return <mix> 134 * 135 * $v = getglobal('test'); // $v = $_G['test'] 136 * $v = getglobal('test/hello/ok'); // $v = $_G['test']['hello']['ok'] 137 */ 138 function getglobal($key, $group = null) { 139 global $_G; 140 $k = explode('/', $group === null ? $key : $group.'/'.$key); 141 switch (count($k)) { 142 case 1: return isset($_G[$k[0]]) ? $_G[$k[0]] : null; break; 143 case 2: return isset($_G[$k[0]][$k[1]]) ? $_G[$k[0]][$k[1]] : null; break; 144 case 3: return isset($_G[$k[0]][$k[1]][$k[2]]) ? $_G[$k[0]][$k[1]][$k[2]] : null; break; 145 case 4: return isset($_G[$k[0]][$k[1]][$k[2]][$k[3]]) ? $_G[$k[0]][$k[1]][$k[2]][$k[3]] : null; break; 146 case 5: return isset($_G[$k[0]][$k[1]][$k[2]][$k[3]][$k[4]]) ? $_G[$k[0]][$k[1]][$k[2]][$k[3]][$k[4]] : null; break; 147 } 148 return null; 149 } 150 151 /** 152 * 取出 get, post, cookie 当中的某个变量 153 * 154 * @param string $k key 值 155 * @param string $type 类型 156 * @return mix 157 */ 158 function getgpc($k, $type='GP') { 159 $type = strtoupper($type); 160 switch($type) { 161 case 'G': $var = &$_GET; break; 162 case 'P': $var = &$_POST; break; 163 case 'C': $var = &$_COOKIE; break; 164 default: 165 if(isset($_GET[$k])) { 166 $var = &$_GET; 167 } else { 168 $var = &$_POST; 169 } 170 break; 171 } 172 173 return isset($var[$k]) ? $var[$k] : NULL; 174 175 } 176 177 /** 178 * 根据uid 获取用户基本数据 179 * @staticvar array $users 存放已经获取的用户的信息,避免重复查库 180 * @param <int> $uid 181 * @return <array> 182 */ 183 function getuserbyuid($uid) { 184 static $users = array(); 185 if(empty($users[$uid])) { 186 $users[$uid] = DB::fetch_first("SELECT * FROM ".DB::table('common_member')." WHERE uid='$uid'"); 187 } 188 return $users[$uid]; 189 } 190 191 /** 192 * 获取当前用户的扩展资料 193 * @param $field 字段 194 */ 195 function getuserprofile($field) { 196 global $_G; 197 if(isset($_G['member'][$field])) { 198 return $_G['member'][$field]; 199 } 200 static $tablefields = array( 201 'count' => array('extcredits1','extcredits2','extcredits3','extcredits4','extcredits5','extcredits6','extcredits7','extcredits8','friends','posts','threads','digestposts','doings','blogs','albums','sharings','attachsize','views','oltime','todayattachs','todayattachsize'), 202 'status' => array('regip','lastip','lastvisit','lastactivity','lastpost','lastsendmail','invisible','buyercredit','sellercredit','favtimes','sharetimes','profileprogress'), 203 'field_forum' => array('publishfeed','customshow','customstatus','medals','sightml','groupterms','authstr','groups','attentiongroup'), 204 'field_home' => array('videophoto','spacename','spacedescription','domain','addsize','addfriend','menunum','theme','spacecss','blockposition','recentnote','spacenote','privacy','feedfriend','acceptemail','magicgift','stickblogs'), 205 'profile' => array('realname','gender','birthyear','birthmonth','birthday','constellation','zodiac','telephone','mobile','idcardtype','idcard','address','zipcode','nationality','birthprovince','birthcity','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'), 206 'verify' => array('verify1', 'verify2', 'verify3', 'verify4', 'verify5', 'verify6', 'verify7'), 207 ); 208 $profiletable = ''; 209 foreach($tablefields as $table => $fields) { 210 if(in_array($field, $fields)) { 211 $profiletable = $table; 212 break; 213 } 214 } 215 if($profiletable) { 216 $data = array(); 217 if($_G['uid']) { 218 $data = DB::fetch_first("SELECT ".implode(', ', $tablefields[$profiletable])." FROM ".DB::table('common_member_'.$profiletable)." WHERE uid='$_G[uid]'"); 219 } 220 if(!$data) { 221 foreach($tablefields[$profiletable] as $k) { 222 $data[$k] = ''; 223 } 224 } 225 $_G['member'] = array_merge(is_array($_G['member']) ? $_G['member'] : array(), $data); 226 return $_G['member'][$field]; 227 } 228 } 229 230 /** 231 * 对字符串或者输入进行 addslashes 操作 232 * @param <mix> $string 233 * @param <int> $force 234 * @return <mix> 235 */ 236 function daddslashes($string, $force = 1) { 237 if(is_array($string)) { 238 $keys = array_keys($string); 239 foreach($keys as $key) { 240 $val = $string[$key]; 241 unset($string[$key]); 242 $string[addslashes($key)] = daddslashes($val, $force); 243 } 244 } else { 245 $string = addslashes($string); 246 } 247 return $string; 248 } 249 250 /** 251 * 对字符串进行加密和解密 252 * @param <string> $string 253 * @param <string> $operation DECODE 解密 | ENCODE 加密 254 * @param <string> $key 当为空的时候,取全局密钥 255 * @param <int> $expiry 有效期,单位秒 256 * @return <string> 257 */ 258 function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) { 259 $ckey_length = 4; 260 $key = md5($key != '' ? $key : getglobal('authkey')); 261 $keya = md5(substr($key, 0, 16)); 262 $keyb = md5(substr($key, 16, 16)); 263 $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : ''; 264 265 $cryptkey = $keya.md5($keya.$keyc); 266 $key_length = strlen($cryptkey); 267 268 $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string; 269 $string_length = strlen($string); 270 271 $result = ''; 272 $box = range(0, 255); 273 274 $rndkey = array(); 275 for($i = 0; $i <= 255; $i++) { 276 $rndkey[$i] = ord($cryptkey[$i % $key_length]); 277 } 278 279 for($j = $i = 0; $i < 256; $i++) { 280 $j = ($j + $box[$i] + $rndkey[$i]) % 256; 281 $tmp = $box[$i]; 282 $box[$i] = $box[$j]; 283 $box[$j] = $tmp; 284 } 285 286 for($a = $j = $i = 0; $i < $string_length; $i++) { 287 $a = ($a + 1) % 256; 288 $j = ($j + $box[$a]) % 256; 289 $tmp = $box[$a]; 290 $box[$a] = $box[$j]; 291 $box[$j] = $tmp; 292 $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); 293 } 294 295 if($operation == 'DECODE') { 296 if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) { 297 return substr($result, 26); 298 } else { 299 return ''; 300 } 301 } else { 302 return $keyc.str_replace('=', '', base64_encode($result)); 303 } 304 305 } 306 307 function fsocketopen($hostname, $port = 80, &$errno, &$errstr, $timeout = 15) { 308 $fp = ''; 309 if(function_exists('fsockopen')) { 310 $fp = @fsockopen($hostname, $port, $errno, $errstr, $timeout); 311 } elseif(function_exists('pfsockopen')) { 312 $fp = @pfsockopen($hostname, $port, $errno, $errstr, $timeout); 313 } elseif(function_exists('stream_socket_client')) { 314 //note php5支持 315 $fp = @stream_socket_client($hostname.':'.$port, $errno, $errstr, $timeout); 316 } 317 return $fp; 318 } 319 320 /** 321 * 远程文件文件请求兼容函数 322 */ 323 function dfsockopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) { 324 require_once libfile('function/filesock'); 325 return _dfsockopen($url, $limit, $post, $cookie, $bysocket, $ip, $timeout, $block); 326 } 327 328 /** 329 * HTML转义字符 330 * @param $string - 字符串 331 * @return 返回转义好的字符串 332 */ 333 function dhtmlspecialchars($string) { 334 if(is_array($string)) { 335 foreach($string as $key => $val) { 336 $string[$key] = dhtmlspecialchars($val); 337 } 338 } else { 339 $string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string); 340 if(strpos($string, '&#') !== false) { 341 $string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string); 342 } 343 } 344 return $string; 345 } 346 347 /** 348 * 退出程序 同 exit 的区别, 对输出数据会进行 重新加工和处理 349 * 通常情况下,我们建议使用本函数终止程序, 除非有特别需求 350 * @param <type> $message 351 */ 352 function dexit($message = '') { 353 echo $message; 354 output(); 355 exit(); 356 } 357 358 /** 359 * 同 php header函数, 针对 location 跳转做了特殊处理 360 * @param <type> $string 361 * @param <type> $replace 362 * @param <type> $http_response_code 363 */ 364 function dheader($string, $replace = true, $http_response_code = 0) { 365 //noteX 手机header跳转的统一修改(IN_MOBILE) 366 $islocation = substr(strtolower(trim($string)), 0, 8) == 'location'; 367 if(defined('IN_MOBILE') && strpos($string, 'mobile') === false && $islocation) { 368 if (strpos($string, '?') === false) { 369 $string = $string.'?mobile=yes'; 370 } else { 371 if(strpos($string, '#') === false) { 372 $string = $string.'&mobile=yes'; 373 } else { 374 $str_arr = explode('#', $string); 375 $str_arr[0] = $str_arr[0].'&mobile=yes'; 376 $string = implode('#', $str_arr); 377 } 378 } 379 } 380 $string = str_replace(array("\r", "\n"), array('', ''), $string); 381 if(empty($http_response_code) || PHP_VERSION < '4.3' ) { 382 @header($string, $replace); 383 } else { 384 @header($string, $replace, $http_response_code); 385 } 386 if($islocation) { 387 exit(); 388 } 389 } 390 391 /** 392 * 设置cookie 393 * @param $var - 变量名 394 * @param $value - 变量值 395 * @param $life - 生命期 396 * @param $prefix - 前缀 397 */ 398 function dsetcookie($var, $value = '', $life = 0, $prefix = 1, $httponly = false) { 399 400 global $_G; 401 402 $config = $_G['config']['cookie']; 403 404 $_G['cookie'][$var] = $value; 405 $var = ($prefix ? $config['cookiepre'] : '').$var; 406 $_COOKIE[$var] = $value; 407 408 if($value == '' || $life < 0) { 409 $value = ''; 410 $life = -1; 411 } 412 413 /*手机浏览器设置cookie,强制取消HttpOnly(IN_MOBILE)*/ 414 if(defined('IN_MOBILE')) { 415 $httponly = false; 416 } 417 418 $life = $life > 0 ? getglobal('timestamp') + $life : ($life < 0 ? getglobal('timestamp') - 31536000 : 0); 419 $path = $httponly && PHP_VERSION < '5.2.0' ? $config['cookiepath'].'; HttpOnly' : $config['cookiepath']; 420 421 $secure = $_SERVER['SERVER_PORT'] == 443 ? 1 : 0; 422 if(PHP_VERSION < '5.2.0') { 423 setcookie($var, $value, $life, $path, $config['cookiedomain'], $secure); 424 } else { 425 setcookie($var, $value, $life, $path, $config['cookiedomain'], $secure, $httponly); 426 } 427 } 428 429 /** 430 * 获取cookie 431 */ 432 function getcookie($key) { 433 global $_G; 434 return isset($_G['cookie'][$key]) ? $_G['cookie'][$key] : ''; 435 } 436 437 /** 438 * 获取文件扩展名 439 */ 440 function fileext($filename) { 441 return addslashes(strtolower(substr(strrchr($filename, '.'), 1, 10))); 442 } 443 444 //note 规则待调整 445 function formhash($specialadd = '') { 446 global $_G; 447 $hashadd = defined('IN_ADMINCP') ? 'Only For Discuz! Admin Control Panel' : ''; 448 return substr(md5(substr($_G['timestamp'], 0, -7).$_G['username'].$_G['uid'].$_G['authkey'].$hashadd.$specialadd), 8, 8); 449 } 450 451 function checkrobot($useragent = '') { 452 static $kw_spiders = array('bot', 'crawl', 'spider' ,'slurp', 'sohu-search', 'lycos', 'robozilla'); 453 static $kw_browsers = array('msie', 'netscape', 'opera', 'konqueror', 'mozilla'); 454 455 $useragent = strtolower(empty($useragent) ? $_SERVER['HTTP_USER_AGENT'] : $useragent); 456 if(strpos($useragent, 'http://') === false && dstrpos($useragent, $kw_browsers)) return false; 457 if(dstrpos($useragent, $kw_spiders)) return true; 458 return false; 459 } 460 /** 461 * 检查是否是以手机浏览器进入(IN_MOBILE) 462 */ 463 function checkmobile() { 464 global $_G; 465 $mobile = array(); 466 static $mobilebrowser_list =array('iphone', 'android', 'phone', 'mobile', 'wap', 'netfront', 'java', 'opera mobi', 'opera mini', 467 'ucweb', 'windows ce', 'symbian', 'series', 'webos', 'sony', 'blackberry', 'dopod', 'nokia', 'samsung', 468 'palmsource', 'xda', 'pieplus', 'meizu', 'midp', 'cldc', 'motorola', 'foma', 'docomo', 'up.browser', 469 'up.link', 'blazer', 'helio', 'hosin', 'huawei', 'novarra', 'coolpad', 'webos', 'techfaith', 'palmsource', 470 'alcatel', 'amoi', 'ktouch', 'nexian', 'ericsson', 'philips', 'sagem', 'wellcom', 'bunjalloo', 'maui', 'smartphone', 471 'iemobile', 'spice', 'bird', 'zte-', 'longcos', 'pantech', 'gionee', 'portalmmm', 'jig browser', 'hiptop', 472 'benq', 'haier', '^lct', '320x320', '240x320', '176x220'); 473 $useragent = strtolower($_SERVER['HTTP_USER_AGENT']); 474 //note 获取手机浏览器 475 if(($v = dstrpos($useragent, $mobilebrowser_list, true))) { 476 $_G['mobile'] = $v; 477 return true; 478 } 479 $brower = array('mozilla', 'chrome', 'safari', 'opera', 'm3gate', 'winwap', 'openwave', 'myop'); 480 if(dstrpos($useragent, $brower)) return false; 481 482 $_G['mobile'] = 'unknown'; 483 if($_GET['mobile'] === 'yes') { 484 return true; 485 } else { 486 return false; 487 } 488 } 489 490 /** 491 * 字符串方式实现 preg_match("/(s1|s2|s3)/", $string, $match) 492 * @param string $string 源字符串 493 * @param array $arr 要查找的字符串 如array('s1', 's2', 's3') 494 * @param bool $returnvalue 是否返回找到的值 495 * @return bool 496 */ 497 function dstrpos($string, &$arr, $returnvalue = false) { 498 if(empty($string)) return false; 499 foreach((array)$arr as $v) { 500 if(strpos($string, $v) !== false) { 501 $return = $returnvalue ? $v : true; 502 return $return; 503 } 504 } 505 return false; 506 } 507 508 /** 509 * 检查邮箱是否有效 510 * @param $email 要检查的邮箱 511 * @param 返回结果 512 */ 513 function isemail($email) { 514 return strlen($email) > 6 && preg_match("/^([A-Za-z0-9\-_.+]+)@([A-Za-z0-9\-]+[.][A-Za-z0-9\-.]+)$/", $email); 515 } 516 517 /** 518 * 问题答案加密 519 * @param $questionid - 问题 520 * @param $answer - 答案 521 * @return 返回加密的字串 522 */ 523 function quescrypt($questionid, $answer) { 524 return $questionid > 0 && $answer != '' ? substr(md5($answer.md5($questionid)), 16, 8) : ''; 525 } 526 527 /** 528 * 产生随机码 529 * @param $length - 要多长 530 * @param $numberic - 数字还是字符串 531 * @return 返回字符串 532 */ 533 function random($length, $numeric = 0) { 534 $seed = base_convert(md5(microtime().$_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35); 535 $seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed)); 536 $hash = ''; 537 $max = strlen($seed) - 1; 538 for($i = 0; $i < $length; $i++) { 539 $hash .= $seed{mt_rand(0, $max)}; 540 } 541 return $hash; 542 } 543 544 /** 545 * 判断一个字符串是否在另一个字符串中存在 546 * 547 * @param string 原始字串 $string 548 * @param string 查找 $find 549 * @return boolean 550 */ 551 function strexists($string, $find) { 552 return !(strpos($string, $find) === FALSE); 553 } 554 555 /** 556 * 获取头像 557 * 558 * @param int $uid 需要获取的用户UID值 559 * @param string $size 获取尺寸 'small', 'middle', 'big' 560 * @param boolean $returnsrc 是否直接返回图片src 561 * @param boolean $real 是否返回真实图片 562 * @param boolean $static 是否返回真实路径 563 * @param string $ucenterurl 强制uc路径 564 */ 565 function avatar($uid, $size = 'middle', $returnsrc = FALSE, $real = FALSE, $static = FALSE, $ucenterurl = '') { 566 global $_G; 567 static $staticavatar; 568 if($staticavatar === null) { 569 $staticavatar = $_G['setting']['avatarmethod']; 570 } 571 572 $ucenterurl = empty($ucenterurl) ? $_G['setting']['ucenterurl'] : $ucenterurl; 573 $size = in_array($size, array('big', 'middle', 'small')) ? $size : 'middle'; 574 $uid = abs(intval($uid)); 575 if(!$staticavatar && !$static) { 576 return $returnsrc ? $ucenterurl.'/avatar.php?uid='.$uid.'&size='.$size : '<img src="'.$ucenterurl.'/avatar.php?uid='.$uid.'&size='.$size.($real ? '&type=real' : '').'" />'; 577 } else { 578 $uid = sprintf("%09d", $uid); 579 $dir1 = substr($uid, 0, 3); 580 $dir2 = substr($uid, 3, 2); 581 $dir3 = substr($uid, 5, 2); 582 $file = $ucenterurl.'/data/avatar/'.$dir1.'/'.$dir2.'/'.$dir3.'/'.substr($uid, -2).($real ? '_real' : '').'_avatar_'.$size.'.jpg'; 583 return $returnsrc ? $file : '<img src="'.$file.'" onerror="this.onerror=null;this.src=\''.$ucenterurl.'/images/noavatar_'.$size.'.gif\'" />'; 584 } 585 } 586 587 /** 588 * 加载语言 589 * 语言文件统一为 $lang = array(); 590 * @param $file - 语言文件,可包含路径如 forum/xxx home/xxx 591 * @param $langvar - 语言文字索引 592 * @param $vars - 变量替换数组 593 * @return 语言文字 594 */ 595 function lang($file, $langvar = null, $vars = array(), $default = null) { 596 global $_G; 597 list($path, $file) = explode('/', $file); 598 if(!$file) { 599 $file = $path; 600 $path = ''; 601 } 602 603 if($path != 'plugin') { 604 $key = $path == '' ? $file : $path.'_'.$file; 605 if(!isset($_G['lang'][$key])) { 606 include DISCUZ_ROOT.'./source/language/'.($path == '' ? '' : $path.'/').'lang_'.$file.'.php'; 607 $_G['lang'][$key] = $lang; 608 } 609 //noteX 合并手机语言包(IN_MOBILE) 610 if(defined('IN_MOBILE') && !defined('TPL_DEFAULT')) { 611 include DISCUZ_ROOT.'./source/language/mobile/lang_template.php'; 612 $_G['lang'][$key] = array_merge($_G['lang'][$key], $lang); 613 } 614 $returnvalue = &$_G['lang']; 615 } else { 616 if(empty($_G['config']['plugindeveloper'])) { 617 loadcache('pluginlanguage_script'); 618 } elseif(!isset($_G['cache']['pluginlanguage_script'][$file]) && preg_match("/^[a-z]+[a-z0-9_]*$/i", $file)) { 619 if(@include(DISCUZ_ROOT.'./data/plugindata/'.$file.'.lang.php')) { 620 $_G['cache']['pluginlanguage_script'][$file] = $scriptlang[$file]; 621 } else { 622 loadcache('pluginlanguage_script'); 623 } 624 } 625 $returnvalue = & $_G['cache']['pluginlanguage_script']; 626 $key = &$file; 627 } 628 $return = $langvar !== null ? (isset($returnvalue[$key][$langvar]) ? $returnvalue[$key][$langvar] : null) : $returnvalue[$key]; 629 $return = $return === null ? ($default !== null ? $default : $langvar) : $return; 630 $searchs = $replaces = array(); 631 if($vars && is_array($vars)) { 632 foreach($vars as $k => $v) { 633 $searchs[] = '{'.$k.'}'; 634 $replaces[] = $v; 635 } 636 } 637 if(is_string($return) && strpos($return, '{_G/') !== false) { 638 preg_match_all('/\{_G\/(.+?)\}/', $return, $gvar); 639 foreach($gvar[0] as $k => $v) { 640 $searchs[] = $v; 641 $replaces[] = getglobal($gvar[1][$k]); 642 } 643 } 644 $return = str_replace($searchs, $replaces, $return); 645 return $return; 646 } 647 648 /** 649 * 检查模板源文件是否更新 650 * 当编译文件不存时强制重新编译 651 * 当 tplrefresh = 1 时检查文件 652 * 当 tplrefresh > 1 时,则根据 tplrefresh 取余,无余时则检查更新 653 * 654 */ 655 function checktplrefresh($maintpl, $subtpl, $timecompare, $templateid, $cachefile, $tpldir, $file) { 656 static $tplrefresh, $timestamp, $targettplname; 657 if($tplrefresh === null) { 658 $tplrefresh = getglobal('config/output/tplrefresh'); 659 $timestamp = getglobal('timestamp'); 660 } 661 662 if(empty($timecompare) || $tplrefresh == 1 || ($tplrefresh > 1 && !($timestamp % $tplrefresh))) { 663 if(empty($timecompare) || @filemtime(DISCUZ_ROOT.$subtpl) > $timecompare) { 664 require_once DISCUZ_ROOT.'/source/class/class_template.php'; 665 $template = new template(); 666 $template->parse_template($maintpl, $templateid, $tpldir, $file, $cachefile); 667 //更新页面和模块的关联 668 if($targettplname === null) { 669 $targettplname = getglobal('style/tplfile'); 670 if(!empty($targettplname)) { 671 $targettplname = strtr($targettplname, ':', '_'); 672 update_template_block($targettplname, $template->blocks); 673 } 674 $targettplname = true; 675 } 676 return TRUE; 677 } 678 } 679 return FALSE; 680 } 681 682 /** 683 * 解析模板 684 * @return 返回域名 685 * 1、模板文件 686 * 2、模板类型,如:diy模板和普通模板,diy模板位于data/diy,普通模板位于 template/default/下 687 * 3、生成的tpl模板文件的存放位置 688 * 4、是否返回模板文件的路径,0-返回编译后的php文件 689 * 5、原始的模板文件 690 */ 691 function template($file, $templateid = 0, $tpldir = '', $gettplfile = 0, $primaltpl='') { 692 global $_G;//超级全局变量:$_G 693 694 static $_init_style = false;//初始化样式标志为false 695 if($_init_style === false) { 696 $discuz = & discuz_core::instance();//实例化一个discuz_core对象 697 $discuz->_init_style();//调用discuz_core对象的_init_style()函数进行样式的初始化 698 $_init_style = true;//样式初始化完成标志设置为true 699 } 700 $oldfile = $file; //原模板,如:"diy:forum/discuz:0" 701 if(strpos($file, ':') !== false) { 702 $clonefile = ''; 703 /* 704 * $templateid:diy 705 * $file:forum/discuz 706 * $clonefile:0 707 */ 708 list($templateid, $file, $clonefile) = explode(':', $file);//将文件以":"分割,如:"diy:forum/discuz:0" 709 $oldfile = $file;//结果:forum/discuz 710 $file = empty($clonefile) || STYLEID != $_G['cache']['style_default']['styleid'] ? $file : $file.'_'.$clonefile;//默认样式id为1:$_G['cache']['style_default']['styleid'];STYLEID:默认值为1 711 if($templateid == 'diy' && STYLEID == $_G['cache']['style_default']['styleid']) {//默认执行 712 $_G['style']['prefile'] = ''; //非预览环境标记预览文件是否存在 713 $diypath = DISCUZ_ROOT.'./data/diy/'; //DIY模板文件目录 714 $preend = '_diy_preview'; //预览文件后缀 715 $_G['gp_preview'] = !empty($_G['gp_preview']) ? $_G['gp_preview'] : ''; //是否预览 716 $curtplname = $oldfile;//当前模板名,如:"forum/discuz" 717 $basescript = $_G['mod'] == 'viewthread' && !empty($_G['thread']) ? 'forum' : $_G['basescript']; //帖子查看页归到froum中,默认值:forum 718 if(isset($_G['cache']['diytemplatename'.$basescript])) { 719 $diytemplatename = &$_G['cache']['diytemplatename'.$basescript];//当前应用的DIY文件缓存 720 } else { 721 $diytemplatename = &$_G['cache']['diytemplatename'];//所有DIY文件缓存 722 //echo $_G['cache']['diytemplatename'];//无任何输出,不知道什么意思 723 //echo "bbbb";//执行else代码段 724 } 725 726 $tplsavemod = 0; //公共DIY页面标记 727 //独立DIY页面 || 分区或版块没有指定模板 && 公共DIY页面 728 if(isset($diytemplatename[$file]) && file_exists($diypath.$file.'.htm') && ($tplsavemod = 1) || empty($_G['forum']['styleid']) && ($file = $primaltpl ? $primaltpl : $oldfile) && isset($diytemplatename[$file]) && file_exists($diypath.$file.'.htm')) { 729 $tpldir = 'data/diy'; //文件目录 730 !$gettplfile && $_G['style']['tplsavemod'] = $tplsavemod; //独立DIY页面标记:1,公共DIY页面标记:0 731 $curtplname = $file; //当前模板名 732 if($_G['gp_diy'] == 'yes' || $_G['gp_preview'] == 'yes') { //DIY模式或预览模式下做以下判断 733 $flag = file_exists($diypath.$file.$preend.'.htm'); //预览文件是否存在 734 if($_G['gp_preview'] == 'yes') { //预览环境 735 $file .= $flag ? $preend : ''; //使用预览模板文件 736 } else { 737 $_G['style']['prefile'] = $flag ? 1 : ''; //非预览环境标记预览文件是否存在 738 } 739 } 740 } else { 741 $file = $primaltpl ? $primaltpl : $oldfile; //无DIY页面则使用原模板 742 } 743 //根据模板自动刷新开关$tplrefresh 更新DIY模板 744 $tplrefresh = $_G['config']['output']['tplrefresh']; 745 //在有DIY生成模板文件时 && 自动刷新开启 && DIY生成模板文件修改时间 < 原模板修改修改 746 if($tpldir == 'data/diy' && ($tplrefresh ==1 || ($tplrefresh > 1 && !($_G['timestamp'] % $tplrefresh))) && filemtime($diypath.$file.'.htm') < filemtime(DISCUZ_ROOT.TPLDIR.'/'.($primaltpl ? $primaltpl : $oldfile).'.htm')) { 747 //原模板更改则更新DIY模板,如果更新失败则删除DIY模板 748 if (!updatediytemplate($file)) { 749 unlink($diypath.$file.'.htm'); 750 $tpldir = ''; 751 } 752 } 753 754 //保存当前模板名 755 if (!$gettplfile && empty($_G['style']['tplfile'])) { 756 $_G['style']['tplfile'] = empty($clonefile) ? $curtplname : $oldfile.':'.$clonefile; 757 } 758 759 //是否显示继续DIY 760 $_G['style']['prefile'] = !empty($_G['gp_preview']) && $_G['gp_preview'] == 'yes' ? '' : $_G['style']['prefile']; 761 762 } else { 763 $tpldir = './source/plugin/'.$templateid.'/template'; 764 } 765 } 766 767 $file .= !empty($_G['inajax']) && ($file == 'common/header' || $file == 'common/footer') ? '_ajax' : ''; 768 $tpldir = $tpldir ? $tpldir : (defined('TPLDIR') ? TPLDIR : ''); 769 $templateid = $templateid ? $templateid : (defined('TEMPLATEID') ? TEMPLATEID : ''); 770 $filebak = $file; 771 772 //noteX 将页面模板加一层Mobile目录,用以定位手机模板页面(IN_MOBILE) 773 if(defined('IN_MOBILE') && !defined('TPL_DEFAULT') && strpos($file, 'mobile/') === false || $_G['forcemobilemessage']) { 774 $file = 'mobile/'.$oldfile; 775 } 776 777 $tplfile = ($tpldir ? $tpldir.'/' : './template/').$file.'.htm'; 778 779 $file == 'common/header' && defined('CURMODULE') && CURMODULE && $file = 'common/header_'.$_G['basescript'].'_'.CURMODULE; 780 781 //noteX 手机模板的判断(IN_MOBILE) 782 if(defined('IN_MOBILE') && !defined('TPL_DEFAULT')) { 783 //首先判断是否是DIY模板,如果是就删除可能存在的forumdisplay_1中的数字 784 if(strpos($tpldir, 'plugin')) { 785 if(!file_exists(DISCUZ_ROOT.$tpldir.'/'.$file.'.htm')) { 786 require_once libfile('class/error'); 787 discuz_error::template_error('template_notfound', $tpldir.'/'.$file.'.htm'); 788 } else { 789 $mobiletplfile = $tpldir.'/'.$file.'.htm'; 790 } 791 } 792 !$mobiletplfile && $mobiletplfile = $file.'.htm'; 793 if(strpos($tpldir, 'plugin') && file_exists(DISCUZ_ROOT.$mobiletplfile)) { 794 $tplfile = $mobiletplfile; 795 } elseif(!file_exists(DISCUZ_ROOT.TPLDIR.'/'.$mobiletplfile)) { 796 $mobiletplfile = './template/default/'.$mobiletplfile; 797 if(!file_exists(DISCUZ_ROOT.$mobiletplfile) && !$_G['forcemobilemessage']) { 798 $tplfile = str_replace('mobile/', '', $tplfile); 799 $file = str_replace('mobile/', '', $file); 800 define('TPL_DEFAULT', true); 801 } else { 802 $tplfile = $mobiletplfile; 803 } 804 } else { 805 $tplfile = TPLDIR.'/'.$mobiletplfile; 806 } 807 } 808 809 $cachefile = './data/template/'.(defined('STYLEID') ? STYLEID.'_' : '_').$templateid.'_'.str_replace('/', '_', $file).'.tpl.php'; 810 811 if($templateid != 1 && !file_exists(DISCUZ_ROOT.$tplfile)) { 812 $tplfile = './template/default/'.$filebak.'.htm'; 813 } 814 815 if($gettplfile) { 816 return $tplfile; 817 } 818 checktplrefresh($tplfile, $tplfile, @filemtime(DISCUZ_ROOT.$cachefile), $templateid, $cachefile, $tpldir, $file); 819 return DISCUZ_ROOT.$cachefile; 820 } 821 822 /** 823 * 对某id进行个性化md5 824 */ 825 function modauthkey($id) { 826 global $_G; 827 return md5($_G['username'].$_G['uid'].$_G['authkey'].substr(TIMESTAMP, 0, -7).$id); 828 } 829 830 /** 831 * 获得当前应用页面选中的导航id 832 */ 833 function getcurrentnav() { 834 global $_G; 835 if(!empty($_G['mnid'])) { 836 return $_G['mnid']; 837 } 838 $mnid = ''; 839 $_G['basefilename'] = $_G['basefilename'] == $_G['basescript'] ? $_G['basefilename'] : $_G['basescript'].'.php'; 840 if(isset($_G['setting']['navmns'][$_G['basefilename']])) { 841 foreach($_G['setting']['navmns'][$_G['basefilename']] as $navmn) { 842 if($navmn[0] == array_intersect_assoc($navmn[0], $_GET)) { 843 $mnid = $navmn[1]; 844 } 845 } 846 } 847 if(!$mnid && isset($_G['setting']['navdms'])) { 848 foreach($_G['setting']['navdms'] as $navdm => $navid) { 849 if(strpos(strtolower($_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']), $navdm) !== false) { 850 $mnid = $navid; 851 break; 852 } 853 } 854 } 855 if(!$mnid && isset($_G['setting']['navmn'][$_G['basefilename']])) { 856 $mnid = $_G['setting']['navmn'][$_G['basefilename']]; 857 } 858 return $mnid; 859 } 860 861 //读取UC库 862 function loaducenter() { 863 require_once DISCUZ_ROOT.'./config/config_ucenter.php'; 864 require_once DISCUZ_ROOT.'./uc_client/client.php'; 865 } 866 867 /** 868 * 读取缓存 869 * @param $cachenames - 缓存名称数组或字串 870 */ 871 function loadcache($cachenames, $force = false) { 872 global $_G; 873 static $loadedcache = array(); 874 $cachenames = is_array($cachenames) ? $cachenames : array($cachenames); 875 $caches = array(); 876 foreach ($cachenames as $k) { 877 if(!isset($loadedcache[$k]) || $force) { 878 $caches[] = $k; 879 $loadedcache[$k] = true; 880 } 881 } 882 883 if(!empty($caches)) { 884 $cachedata = cachedata($caches); 885 foreach($cachedata as $cname => $data) { 886 if($cname == 'setting') { 887 $_G['setting'] = $data; 888 } elseif(strpos($cname, 'usergroup_'.$_G['groupid']) !== false) { 889 $_G['cache'][$cname] = $_G['group'] = $data; 890 } elseif($cname == 'style_default') { 891 $_G['cache'][$cname] = $_G['style'] = $data; 892 } elseif($cname == 'grouplevels') { 893 $_G['grouplevels'] = $data; 894 } else { 895 $_G['cache'][$cname] = $data; 896 } 897 } 898 } 899 return true; 900 } 901 902 /** 903 * 通过memcache\mysql\file等几种手段读缓存 904 * @param mixed $cachenames 缓存名的数组或字串 905 */ 906 function cachedata($cachenames) { 907 global $_G; 908 static $isfilecache, $allowmem; 909 //$discuz = & discuz_core::instance(); 910 911 if(!isset($isfilecache)) { 912 $isfilecache = getglobal('config/cache/type') == 'file'; 913 $allowmem = memory('check'); 914 } 915 916 $data = array(); 917 $cachenames = is_array($cachenames) ? $cachenames : array($cachenames); 918 if($allowmem) { 919 $newarray = array(); 920 foreach ($cachenames as $name) { 921 $data[$name] = memory('get', $name); 922 if($data[$name] === null) { 923 $data[$name] = null; 924 $newarray[] = $name; 925 } 926 } 927 if(empty($newarray)) { 928 return $data; 929 } else { 930 $cachenames = $newarray; 931 } 932 } 933 934 if($isfilecache) { 935 $lostcaches = array(); 936 foreach($cachenames as $cachename) { 937 if(!@include_once(DISCUZ_ROOT.'./data/cache/cache_'.$cachename.'.php')) { 938 $lostcaches[] = $cachename; 939 } 940 } 941 if(!$lostcaches) { 942 return $data; 943 } 944 $cachenames = $lostcaches; 945 unset($lostcaches); 946 } 947 $query = DB::query("SELECT * FROM ".DB::table('common_syscache')." WHERE cname IN ('".implode("','", $cachenames)."')"); 948 while($syscache = DB::fetch($query)) { 949 $data[$syscache['cname']] = $syscache['ctype'] ? unserialize($syscache['data']) : $syscache['data']; 950 $allowmem && (memory('set', $syscache['cname'], $data[$syscache['cname']])); 951 if($isfilecache) { 952 $cachedata = '$data[\''.$syscache['cname'].'\'] = '.var_export($data[$syscache['cname']], true).";\n\n"; 953 if($fp = @fopen(DISCUZ_ROOT.'./data/cache/cache_'.$syscache['cname'].'.php', 'wb')) { 954 fwrite($fp, "<?php\n//Discuz! cache file, DO NOT modify me!\n//Identify: ".md5($syscache['cname'].$cachedata.$_G['config']['security']['authkey'])."\n\n$cachedata?>"); 955 fclose($fp); 956 } 957 } 958 } 959 960 foreach($cachenames as $name) { 961 if($data[$name] === null) { 962 $data[$name] = null; 963 $allowmem && (memory('set', $name, array())); 964 } 965 } 966 967 return $data; 968 } 969 970 /** 971 * 格式化时间 972 * @param $timestamp - 时间戳 973 * @param $format - dt=日期时间 d=日期 t=时间 u=个性化 其他=自定义 974 * @param $timeoffset - 时区 975 * @return string 976 */ 977 function dgmdate($timestamp, $format = 'dt', $timeoffset = '9999', $uformat = '') { 978 global $_G; 979 $format == 'u' && !$_G['setting']['dateconvert'] && $format = 'dt'; 980 static $dformat, $tformat, $dtformat, $offset, $lang; 981 if($dformat === null) { 982 $dformat = getglobal('setting/dateformat'); 983 $tformat = getglobal('setting/timeformat'); 984 $dtformat = $dformat.' '.$tformat; 985 $offset = getglobal('member/timeoffset'); 986 $lang = lang('core', 'date'); 987 } 988 $timeoffset = $timeoffset == 9999 ? $offset : $timeoffset; 989 $timestamp += $timeoffset * 3600; 990 $format = empty($format) || $format == 'dt' ? $dtformat : ($format == 'd' ? $dformat : ($format == 't' ? $tformat : $format)); 991 if($format == 'u') { 992 $todaytimestamp = TIMESTAMP - (TIMESTAMP + $timeoffset * 3600) % 86400 + $timeoffset * 3600; 993 $s = gmdate(!$uformat ? str_replace(":i", ":i:s", $dtformat) : $uformat, $timestamp); 994 $time = TIMESTAMP + $timeoffset * 3600 - $timestamp; 995 if($timestamp >= $todaytimestamp) { 996 if($time > 3600) { 997 return '<span title="'.$s.'">'.intval($time / 3600).' '.$lang['hour'].$lang['before'].'</span>'; 998 } elseif($time > 1800) { 999 return '<span title="'.$s.'">'.$lang['half'].$lang['hour'].$lang['before'].'</span>'; 1000 } elseif($time > 60) { 1001 return '<span title="'.$s.'">'.intval($time / 60).' '.$lang['min'].$lang['before'].'</span>'; 1002 } elseif($time > 0) { 1003 return '<span title="'.$s.'">'.$time.' '.$lang['sec'].$lang['before'].'</span>'; 1004 } elseif($time == 0) { 1005 return '<span title="'.$s.'">'.$lang['now'].'</span>'; 1006 } else { 1007 return $s; 1008 } 1009 } elseif(($days = intval(($todaytimestamp - $timestamp) / 86400)) >= 0 && $days < 7) { 1010 if($days == 0) { 1011 return '<span title="'.$s.'">'.$lang['yday'].' '.gmdate($tformat, $timestamp).'</span>'; 1012 } elseif($days == 1) { 1013 return '<span title="'.$s.'">'.$lang['byday'].' '.gmdate($tformat, $timestamp).'</span>'; 1014 } else { 1015 return '<span title="'.$s.'">'.($days + 1).' '.$lang['day'].$lang['before'].'</span>'; 1016 } 1017 } else { 1018 return $s; 1019 } 1020 } else { 1021 return gmdate($format, $timestamp); 1022 } 1023 } 1024 1025 /** 1026 得到时间戳 1027 */ 1028 function dmktime($date) { 1029 if(strpos($date, '-')) { 1030 $time = explode('-', $date); 1031 return mktime(0, 0, 0, $time[1], $time[2], $time[0]); 1032 } 1033 return 0; 1034 } 1035 1036 /** 1037 * 更新缓存 1038 * @param $cachename - 缓存名称 1039 * @param $data - 缓存数据 1040 */ 1041 function save_syscache($cachename, $data) { 1042 static $isfilecache, $allowmem; 1043 if(!isset($isfilecache)) { 1044 $isfilecache = getglobal('config/cache/type') == 'file'; 1045 $allowmem = memory('check'); 1046 } 1047 1048 if(is_array($data)) { 1049 $ctype = 1; 1050 $data = addslashes(serialize($data)); 1051 } else { 1052 $ctype = 0; 1053 } 1054 1055 DB::query("REPLACE INTO ".DB::table('common_syscache')." (cname, ctype, dateline, data) VALUES ('$cachename', '$ctype', '".TIMESTAMP."', '$data')"); 1056 1057 $allowmem && memory('rm', $cachename); 1058 $isfilecache && @unlink(DISCUZ_ROOT.'./data/cache/cache_'.$cachename.'.php'); 1059 } 1060 1061 /** 1062 * Portal模块 1063 * @param $parameter - 参数集合 1064 */ 1065 function block_get($parameter) { 1066 global $_G; 1067 static $allowmem; 1068 if($allowmem === null) { 1069 include_once libfile('function/block'); 1070 $allowmem = getglobal('setting/memory/diyblock/enable') && memory('check'); 1071 } 1072 if(!$allowmem) { 1073 block_get_batch($parameter); 1074 return true; 1075 } 1076 $blockids = explode(',', $parameter); 1077 $lostbids = array(); 1078 foreach ($blockids as $bid) { 1079 $bid = intval($bid); 1080 if($bid) { 1081 $_G['block'][$bid] = memory('get', 'blockcache_'.$bid); 1082 if($_G['block'][$bid] === null) { 1083 $lostbids[] = $bid; 1084 } else { 1085 $styleid = $_G['block'][$bid]['styleid']; 1086 if($styleid && !isset($_G['blockstyle_'.$styleid])) { 1087 $_G['blockstyle_'.$styleid] = memory('get', 'blockstylecache_'.$styleid); 1088 } 1089 } 1090 } 1091 } 1092 1093 if($lostbids) { 1094 block_get_batch(implode(',', $lostbids)); 1095 foreach ($lostbids as $bid) { 1096 if(isset($_G['block'][$bid])) { 1097 memory('set', 'blockcache_'.$bid, $_G['block'][$bid], getglobal('setting/memory/diyblock/ttl')); 1098 $styleid = $_G['block'][$bid]['styleid']; 1099 if($styleid && $_G['blockstyle_'.$styleid]) { 1100 memory('set', 'blockstylecache_'.$styleid, $_G['blockstyle_'.$styleid], getglobal('setting/memory/diyblock/ttl')); 1101 } 1102 } 1103 } 1104 } 1105 } 1106 1107 /** 1108 * Portal 模块显示 1109 * 1110 * @param $parameter - 参数集合 1111 */ 1112 function block_display($bid) { 1113 include_once libfile('function/block'); 1114 block_display_batch($bid); 1115 } 1116 1117 //连接字符 1118 function dimplode($array) { 1119 if(!empty($array)) { 1120 return "'".implode("','", is_array($array) ? $array : array($array))."'"; 1121 } else { 1122 return 0; 1123 } 1124 } 1125 1126 /** 1127 * 返回库文件的全路径 1128 * 1129 * @param string $libname 库文件分类及名称 1130 * @param string $folder 模块目录'module','include','class' 1131 * @return string 1132 * 1133 * @example require DISCUZ_ROOT.'./source/function/function_cache.php' 1134 * @example 我们可以利用此函数简写为:require libfile('function/cache'); 1135 * 1136 */ 1137 function libfile($libname, $folder = '') { 1138 $libpath = DISCUZ_ROOT.'/source/'.$folder; 1139 if(strstr($libname, '/')) { 1140 list($pre, $name) = explode('/', $libname); 1141 return realpath("{$libpath}/{$pre}/{$pre}_{$name}.php"); 1142 } else { 1143 return realpath("{$libpath}/{$libname}.php"); 1144 } 1145 } 1146 1147 /** 1148 * 针对uft-8进行特殊处理的strlen 1149 * @param string $str 1150 * @return int 1151 */ 1152 function dstrlen($str) { 1153 if(strtolower(CHARSET) != 'utf-8') { 1154 return strlen($str); 1155 } 1156 $count = 0; 1157 for($i = 0; $i < strlen($str); $i++){ 1158 $value = ord($str[$i]); 1159 if($value > 127) { 1160 $count++; 1161 if($value >= 192 && $value <= 223) $i++; 1162 elseif($value >= 224 && $value <= 239) $i = $i + 2; 1163 elseif($value >= 240 && $value <= 247) $i = $i + 3; 1164 } 1165 $count++; 1166 } 1167 return $count; 1168 } 1169 1170 /** 1171 * 根据中文裁减字符串 1172 * @param $string - 字符串 1173 * @param $length - 长度 1174 * @param $doc - 缩略后缀 1175 * @return 返回带省略号被裁减好的字符串 1176 */ 1177 function cutstr($string, $length, $dot = ' ...') { 1178 if(strlen($string) <= $length) { 1179 return $string; 1180 } 1181 1182 $pre = chr(1); 1183 $end = chr(1); 1184 //保护特殊字符串 1185 $string = str_replace(array('&', '"', '<', '>'), array($pre.'&'.$end, $pre.'"'.$end, $pre.'<'.$end, $pre.'>'.$end), $string); 1186 1187 $strcut = ''; 1188 if(strtolower(CHARSET) == 'utf-8') { 1189 1190 $n = $tn = $noc = 0; 1191 while($n < strlen($string)) { 1192 1193 $t = ord($string[$n]); 1194 if($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) { 1195 $tn = 1; $n++; $noc++; 1196 } elseif(194 <= $t && $t <= 223) { 1197 $tn = 2; $n += 2; $noc += 2; 1198 } elseif(224 <= $t && $t <= 239) { 1199 $tn = 3; $n += 3; $noc += 2; 1200 } elseif(240 <= $t && $t <= 247) { 1201 $tn = 4; $n += 4; $noc += 2; 1202 } elseif(248 <= $t && $t <= 251) { 1203 $tn = 5; $n += 5; $noc += 2; 1204 } elseif($t == 252 || $t == 253) { 1205 $tn = 6; $n += 6; $noc += 2; 1206 } else { 1207 $n++; 1208 } 1209 1210 if($noc >= $length) { 1211 break; 1212 } 1213 1214 } 1215 if($noc > $length) { 1216 $n -= $tn; 1217 } 1218 1219 $strcut = substr($string, 0, $n); 1220 1221 } else { 1222 for($i = 0; $i < $length; $i++) { 1223 $strcut .= ord($string[$i]) > 127 ? $string[$i].$string[++$i] : $string[$i]; 1224 } 1225 } 1226 1227 //还原特殊字符串 1228 $strcut = str_replace(array($pre.'&'.$end, $pre.'"'.$end, $pre.'<'.$end, $pre.'>'.$end), array('&', '"', '<', '>'), $strcut); 1229 1230 //修复出现特殊字符串截段的问题 1231 $pos = strrpos($strcut, chr(1)); 1232 if($pos !== false) { 1233 $strcut = substr($strcut,0,$pos); 1234 } 1235 return $strcut.$dot; 1236 } 1237 1238 //去掉slassh 1239 function dstripslashes($string) { 1240 if(empty($string)) return $string; 1241 if(is_array($string)) { 1242 foreach($string as $key => $val) { 1243 $string[$key] = dstripslashes($val); 1244 } 1245 } else { 1246 $string = stripslashes($string); 1247 } 1248 return $string; 1249 } 1250 1251 /** 1252 * 论坛 aid url 生成 1253 */ 1254 function aidencode($aid, $type = 0, $tid = 0) { 1255 global $_G; 1256 $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; 1257 return rawurlencode(base64_encode($s)); 1258 } 1259 1260 /** 1261 * 返回论坛缩放附件图片的地址 url 1262 */ 1263 function getforumimg($aid, $nocache = 0, $w = 140, $h = 140, $type = '') { 1264 global $_G; 1265 $key = md5($aid.'|'.$w.'|'.$h); 1266 return 'forum.php?mod=image&aid='.$aid.'&size='.$w.'x'.$h.'&key='.rawurlencode($key).($nocache ? '&nocache=yes' : '').($type ? '&type='.$type : ''); 1267 } 1268 1269 /** 1270 * 获取rewrite字符串 1271 * @param string $type 需要获取的rewite 1272 * @param boolean $returntype true:直接返回href, false:返回a标签 1273 * @param string $host 可选网站域名 1274 * @return string 1275 */ 1276 function rewriteoutput($type, $returntype, $host) { 1277 global $_G; 1278 $fextra = ''; 1279 if($type == 'forum_forumdisplay') { 1280 list(,,, $fid, $page, $extra) = func_get_args(); 1281 $r = array( 1282 '{fid}' => empty($_G['setting']['forumkeys'][$fid]) ? $fid : $_G['setting']['forumkeys'][$fid], 1283 '{page}' => $page ? $page : 1, 1284 ); 1285 } elseif($type == 'forum_viewthread') { 1286 list(,,, $tid, $page, $prevpage, $extra) = func_get_args(); 1287 $r = array( 1288 '{tid}' => $tid, 1289 '{page}' => $page ? $page : 1, 1290 '{prevpage}' => $prevpage && !IS_ROBOT ? $prevpage : 1, 1291 ); 1292 } elseif($type == 'home_space') { 1293 list(,,, $uid, $username, $extra) = func_get_args(); 1294 $_G['setting']['rewritecompatible'] && $username = rawurlencode($username); 1295 $r = array( 1296 '{user}' => $uid ? 'uid' : 'username', 1297 '{value}' => $uid ? $uid : $username, 1298 ); 1299 } elseif($type == 'home_blog') { 1300 list(,,, $uid, $blogid, $extra) = func_get_args(); 1301 $r = array( 1302 '{uid}' => $uid, 1303 '{blogid}' => $blogid, 1304 ); 1305 } elseif($type == 'group_group') { 1306 list(,,, $fid, $page, $extra) = func_get_args(); 1307 $r = array( 1308 '{fid}' => $fid, 1309 '{page}' => $page ? $page : 1, 1310 ); 1311 } elseif($type == 'portal_topic') { 1312 list(,,, $name, $extra) = func_get_args(); 1313 $r = array( 1314 '{name}' => $name, 1315 ); 1316 } elseif($type == 'portal_article') { 1317 list(,,, $id, $page, $extra) = func_get_args(); 1318 $r = array( 1319 '{id}' => $id, 1320 '{page}' => $page ? $page : 1, 1321 ); 1322 } elseif($type == 'forum_archiver') { 1323 list(,, $action, $value, $page, $extra) = func_get_args(); 1324 $host = ''; 1325 $r = array( 1326 '{action}' => $action, 1327 '{value}' => $value, 1328 ); 1329 if($page) { 1330 $fextra = '?page='.$page; 1331 } 1332 } 1333 $href = str_replace(array_keys($r), $r, $_G['setting']['rewriterule'][$type]).$fextra; 1334 if(!$returntype) { 1335 return '<a href="'.$host.$href.'"'.(!empty($extra) ? stripslashes($extra) : '').'>'; 1336 } else { 1337 return $host.$href; 1338 } 1339 } 1340 1341 /** 1342 * 手机模式下替换所有链接为mobile=yes形式 1343 * @param $file - 正则匹配到的文件字符串 1344 * @param $file - 要被替换的字符串 1345 * @$replace 替换后字符串 1346 */ 1347 function mobilereplace($file, $replace) { 1348 global $_G; 1349 if(strpos($replace, 'mobile=') === false) { 1350 if(strpos($replace, '?') === false) { 1351 $replace = 'href="'.$file.$replace.'?mobile=yes"'; 1352 } else { 1353 $replace = 'href="'.$file.$replace.'&mobile=yes"'; 1354 } 1355 return $replace; 1356 } else { 1357 return 'href="'.$file.$replace.'"'; 1358 } 1359 } 1360 1361 /** 1362 * 手机的output函数 1363 */ 1364 function mobileoutput() { 1365 global $_G; 1366 if(!defined('TPL_DEFAULT')) { 1367 $content = ob_get_contents(); 1368 ob_end_clean(); 1369 $content = preg_replace("/href=\"(\w+\.php)(.*?)\"/e", "mobilereplace('\\1', '\\2')", $content); 1370 1371 ob_start(); 1372 $content = '<?xml version="1.0" encoding="utf-8"?>'.$content; 1373 if('utf-8' != CHARSET) { 1374 @header('Content-Type: text/html; charset=utf-8'); 1375 $content = diconv($content, CHARSET, 'utf-8'); 1376 } 1377 echo $content; 1378 exit(); 1379 1380 } elseif (defined('TPL_DEFAULT') && !$_G['cookie']['dismobilemessage'] && $_G['mobile']) { 1381 //noteX 当检测到手机浏览器,但又没有某个页面的模板时,需要进行此操作 1382 ob_end_clean(); 1383 ob_start(); 1384 $_G['forcemobilemessage'] = true; 1385 $query_sting_tmp = str_replace(array('&mobile=yes', 'mobile=yes'), array(''), $_SERVER['QUERY_STRING']); 1386 $_G['setting']['mobile']['pageurl'] = $_G['siteurl'].substr($_G['PHP_SELF'], 1).($query_sting_tmp ? '?'.$query_sting_tmp.'&mobile=no' : '?mobile=no' ); 1387 unset($query_sting_tmp); 1388 dsetcookie('dismobilemessage', '1', 3600); 1389 showmessage('not_in_mobile'); 1390 exit; 1391 } 1392 } 1393 1394 /** 1395 * 系统输出 1396 * @return 返回内容 1397 */ 1398 function output() { 1399 1400 global $_G; 1401 1402 //=================================== 1403 //判断写入页面缓存 1404 //=================================== 1405 //writepagecache(); 1406 1407 if(defined('DISCUZ_OUTPUTED')) { 1408 return; 1409 } else { 1410 define('DISCUZ_OUTPUTED', 1); 1411 } 1412 1413 // 更新模块 1414 if(!empty($_G['blockupdate'])) { 1415 block_updatecache($_G['blockupdate']['bid']); 1416 } 1417 1418 //noteX 手机模式下重新制作页面输出(IN_MOBILE) 1419 if(defined('IN_MOBILE')) { 1420 mobileoutput(); 1421 } 1422 include_once libfile('function/cloud'); 1423 show(); 1424 $havedomain = implode('', $_G['setting']['domain']['app']); 1425 if($_G['setting']['rewritestatus'] || !empty($havedomain)) { 1426 $content = ob_get_contents(); 1427 $content = output_replace($content); 1428 1429 1430 ob_end_clean(); 1431 $_G['gzipcompress'] ? ob_start('ob_gzhandler') : ob_start();//note X:待调整 1432 1433 echo $content; 1434 } 1435 if($_G['setting']['ftp']['connid']) { 1436 @ftp_close($_G['setting']['ftp']['connid']); 1437 } 1438 $_G['setting']['ftp'] = array(); 1439 1440 //debug Module:HTML_CACHE 如果定义了缓存常量,则此处将缓冲区的内容写入文件。如果为 index 缓存,则直接写入 data/index.cache ,如果为 viewthread 缓存,则根据md5(tid,等参数)取前三位为目录加上$tid_$page,做文件名。 1441 //debug $threadcacheinfo, $indexcachefile 为全局变量 1442 if(defined('CACHE_FILE') && CACHE_FILE && !defined('CACHE_FORBIDDEN') && !defined('IN_MOBILE')) { 1443 if(diskfreespace(DISCUZ_ROOT.'./'.$_G['setting']['cachethreaddir']) > 1000000) { 1444 if($fp = @fopen(CACHE_FILE, 'w')) { 1445 flock($fp, LOCK_EX); 1446 fwrite($fp, empty($content) ? ob_get_contents() : $content); 1447 } 1448 @fclose($fp); 1449 chmod(CACHE_FILE, 0777); 1450 } 1451 } 1452 1453 if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG && @include(libfile('function/debug'))) { 1454 function_exists('debugmessage') && debugmessage(); 1455 } 1456 } 1457 1458 function output_replace($content) { 1459 global $_G; 1460 if(defined('IN_MODCP') || defined('IN_ADMINCP')) return $content; 1461 if(!empty($_G['setting']['output']['str']['search'])) { 1462 if(empty($_G['setting']['domain']['app']['default'])) { 1463 $_G['setting']['output']['str']['replace'] = str_replace('{CURHOST}', $_G['siteurl'], $_G['setting']['output']['str']['replace']); 1464 } 1465 $content = str_replace($_G['setting']['output']['str']['search'], $_G['setting']['output']['str']['replace'], $content); 1466 } 1467 if(!empty($_G['setting']['output']['preg']['search'])) { 1468 if(empty($_G['setting']['domain']['app']['default'])) { 1469 $_G['setting']['output']['preg']['search'] = str_replace('\{CURHOST\}', preg_quote($_G['siteurl'], '/'), $_G['setting']['output']['preg']['search']); 1470 $_G['setting']['output']['preg']['replace'] = str_replace('{CURHOST}', $_G['siteurl'], $_G['setting']['output']['preg']['replace']); 1471 } 1472 1473 $content = preg_replace($_G['setting']['output']['preg']['search'], $_G['setting']['output']['preg']['replace'], $content); 1474 } 1475 1476 return $content; 1477 } 1478 1479 /** 1480 * ajax footer使用输出页面内容 1481 */ 1482 function output_ajax() { 1483 global $_G; 1484 $s = ob_get_contents(); 1485 ob_end_clean(); 1486 $s = preg_replace("/([\\x01-\\x08\\x0b-\\x0c\\x0e-\\x1f])+/", ' ', $s); 1487 $s = str_replace(array(chr(0), ']]>'), array(' ', ']]>'), $s); 1488 if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG && @include(libfile('function/debug'))) { 1489 function_exists('debugmessage') && $s .= debugmessage(1); 1490 } 1491 $havedomain = implode('', $_G['setting']['domain']['app']); 1492 if($_G['setting']['rewritestatus'] || !empty($havedomain)) { 1493 $s = output_replace($s); 1494 } 1495 return $s; 1496 } 1497 1498 /** 1499 * 运行钩子 1500 */ 1501 function runhooks() { 1502 if(!defined('HOOKTYPE')) { 1503 define('HOOKTYPE', !defined('IN_MOBILE') ? 'hookscript' : 'hookscriptmobile'); 1504 } 1505 if(defined('CURMODULE')) { 1506 global $_G; 1507 if($_G['setting']['plugins'][HOOKTYPE.'_common']) { 1508 hookscript('common', 'global', 'funcs', array(), 'common'); 1509 } 1510 hookscript(CURMODULE, $_G['basescript']); 1511 } 1512 } 1513 1514 /** 1515 * 执行插件脚本 1516 */ 1517 function hookscript($script, $hscript, $type = 'funcs', $param = array(), $func = '') { 1518 global $_G; 1519 static $pluginclasses; 1520 if($hscript == 'home') { 1521 if($script != 'spacecp') { 1522 $script = 'space_'.(!empty($_G['gp_do']) ? $_G['gp_do'] : (!empty($_GET['do']) ? $_GET['do'] : '')); 1523 } else { 1524 $script .= !empty($_G['gp_ac']) ? '_'.$_G['gp_ac'] : (!empty($_GET['ac']) ? '_'.$_GET['ac'] : ''); 1525 } 1526 } 1527 if(!isset($_G['setting'][HOOKTYPE][$hscript][$script][$type])) { 1528 return; 1529 } 1530 if(!isset($_G['cache']['plugin'])) { 1531 loadcache('plugin'); 1532 } 1533 foreach((array)$_G['setting'][HOOKTYPE][$hscript][$script]['module'] as $identifier => $include) { 1534 $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']); 1535 if($hooksadminid[$identifier]) { 1536 @include_once DISCUZ_ROOT.'./source/plugin/'.$include.'.class.php'; 1537 } 1538 } 1539 if(@is_array($_G['setting'][HOOKTYPE][$hscript][$script][$type])) { 1540 $_G['inhookscript'] = true; 1541 $funcs = !$func ? $_G['setting'][HOOKTYPE][$hscript][$script][$type] : array($func => $_G['setting'][HOOKTYPE][$hscript][$script][$type][$func]); 1542 foreach($funcs as $hookkey => $hookfuncs) { 1543 foreach($hookfuncs as $hookfunc) { 1544 if($hooksadminid[$hookfunc[0]]) { 1545 $classkey = (HOOKTYPE != 'hookscriptmobile' ? '' : 'mobile').'plugin_'.($hookfunc[0].($hscript != 'global' ? '_'.$hscript : '')); 1546 if(!class_exists($classkey)) { 1547 continue; 1548 } 1549 if(!isset($pluginclasses[$classkey])) { 1550 $pluginclasses[$classkey] = new $classkey; 1551 } 1552 if(!method_exists($pluginclasses[$classkey], $hookfunc[1])) { 1553 continue; 1554 } 1555 $return = $pluginclasses[$classkey]->$hookfunc[1]($param); 1556 1557 if(is_array($return)) { 1558 if(!isset($_G['setting']['pluginhooks'][$hookkey]) || is_array($_G['setting']['pluginhooks'][$hookkey])) { 1559 foreach($return as $k => $v) { 1560 $_G['setting']['pluginhooks'][$hookkey][$k] .= $v; 1561 } 1562 } 1563 } else { 1564 if(!is_array($_G['setting']['pluginhooks'][$hookkey])) { 1565 $_G['setting']['pluginhooks'][$hookkey] .= $return; 1566 } else { 1567 foreach($_G['setting']['pluginhooks'][$hookkey] as $k => $v) { 1568 $_G['setting']['pluginhooks'][$hookkey][$k] .= $return; 1569 } 1570 } 1571 } 1572 } 1573 } 1574 } 1575 } 1576 $_G['inhookscript'] = false; 1577 } 1578 1579 function hookscriptoutput($tplfile) { 1580 global $_G; 1581 if(!empty($_G['hookscriptoutput'])) { 1582 return; 1583 } 1584 //note mobiledata 1585 if(!empty($_G['gp_mobiledata'])) { 1586 require_once libfile('class/mobiledata'); 1587 $mobiledata = new mobiledata(); 1588 if($mobiledata->validator()) { 1589 $mobiledata->outputvariables(); 1590 } 1591 } 1592 hookscript('global', 'global'); 1593 if(defined('CURMODULE')) { 1594 $param = array('template' => $tplfile, 'message' => $_G['hookscriptmessage'], 'values' => $_G['hookscriptvalues']); 1595 hookscript(CURMODULE, $_G['basescript'], 'outputfuncs', $param); 1596 } 1597 $_G['hookscriptoutput'] = true; 1598 } 1599 1600 /** 1601 * 获取插件模块 1602 */ 1603 function pluginmodule($pluginid, $type) { 1604 global $_G; 1605 if(!isset($_G['cache']['plugin'])) { 1606 loadcache('plugin'); 1607 } 1608 list($identifier, $module) = explode(':', $pluginid); 1609 if(!is_array($_G['setting']['plugins'][$type]) || !array_key_exists($pluginid, $_G['setting']['plugins'][$type])) { 1610 showmessage('plugin_nonexistence'); 1611 } 1612 if(!empty($_G['setting']['plugins'][$type][$pluginid]['url'])) { 1613 dheader('location: '.$_G['setting']['plugins'][$type][$pluginid]['url']); 1614 } 1615 $directory = $_G['setting']['plugins'][$type][$pluginid]['directory']; 1616 if(empty($identifier) || !preg_match("/^[a-z]+[a-z0-9_]*\/$/i", $directory) || !preg_match("/^[a-z0-9_\-]+$/i", $module)) { 1617 showmessage('undefined_action'); 1618 } 1619 if(@!file_exists(DISCUZ_ROOT.($modfile = './source/plugin/'.$directory.$module.'.inc.php'))) { 1620 showmessage('plugin_module_nonexistence', '', array('mod' => $modfile)); 1621 } 1622 return DISCUZ_ROOT.$modfile; 1623 } 1624 /** 1625 * 执行积分规则 1626 * @param String $action: 规则action名称 1627 * @param Integer $uid: 操作用户 1628 * @param array $extrasql: common_member_count的额外操作字段数组格式为 array('extcredits1' => '1') 1629 * @param String $needle: 防重字符串 1630 * @param Integer $coef: 积分放大倍数 1631 * @param Integer $update: 是否执行更新操作 1632 * @param Integer $fid: 版块ID 1633 * @return 返回积分策略 1634 */ 1635 function updatecreditbyaction($action, $uid = 0, $extrasql = array(), $needle = '', $coef = 1, $update = 1, $fid = 0) { 1636 1637 include_once libfile('class/credit'); 1638 $credit = & credit::instance(); 1639 if($extrasql) { 1640 $credit->extrasql = $extrasql; 1641 } 1642 return $credit->execrule($action, $uid, $needle, $coef, $update, $fid); 1643 } 1644 1645 /** 1646 * 检查积分下限 1647 * @param string $action: 策略动作Action或者需要检测的操作积分值使如extcredits1积分进行减1操作检测array('extcredits1' => -1) 1648 * @param Integer $uid: 用户UID 1649 * @param Integer $coef: 积分放大倍数/负数为减分操作 1650 * @param Integer $returnonly: 只要返回结果,不用中断程序运行 1651 */ 1652 function checklowerlimit($action, $uid = 0, $coef = 1, $fid = 0, $returnonly = 0) { 1653 require_once libfile('function/credit'); 1654 return _checklowerlimit($action, $uid, $coef, $fid, $returnonly); 1655 } 1656 1657 /** 1658 * 批量执行某一条策略规则 1659 * @param String $action: 规则action名称 1660 * @param Integer $uids: 操作用户可以为单个uid或uid数组 1661 * @param array $extrasql: common_member_count的额外操作字段数组格式为 array('extcredits1' => '1') 1662 * @param Integer $coef: 积分放大倍数,当为负数时为反转操作 1663 * @param Integer $fid: 版块ID 1664 */ 1665 function batchupdatecredit($action, $uids = 0, $extrasql = array(), $coef = 1, $fid = 0) { 1666 1667 include_once libfile('class/credit'); 1668 $credit = & credit::instance(); 1669 if($extrasql) { 1670 $credit->extrasql = $extrasql; 1671 } 1672 return $credit->updatecreditbyrule($action, $uids, $coef, $fid); 1673 } 1674 1675 /** 1676 * 添加积分 1677 * @param Integer $uids: 用户uid或者uid数组 1678 * @param String $dataarr: member count相关操作数组,例: array('threads' => 1, 'doings' => -1) 1679 * @param Boolean $checkgroup: 是否检查用户组 true or false 1680 * @param String $operation: 操作类型 1681 * @param Integer $relatedid: 1682 * @param String $ruletxt: 积分规则文本 1683 */ 1684 1685 function updatemembercount($uids, $dataarr = array(), $checkgroup = true, $operation = '', $relatedid = 0, $ruletxt = '') { 1686 if(!empty($uids) && (is_array($dataarr) && $dataarr)) { 1687 require_once libfile('function/credit'); 1688 return _updatemembercount($uids, $dataarr, $checkgroup, $operation, $relatedid, $ruletxt); 1689 } 1690 return true; 1691 } 1692 1693 /** 1694 * 校验用户组 1695 * @param $uid 1696 */ 1697 function checkusergroup($uid = 0) { 1698 require_once libfile('class/credit'); 1699 $credit = & credit::instance(); 1700 $credit->checkusergroup($uid); 1701 } 1702 1703 function checkformulasyntax($formula, $operators, $tokens) { 1704 $var = implode('|', $tokens); 1705 $operator = implode('', $operators); 1706 1707 $operator = str_replace( 1708 array('+', '-', '*', '/', '(', ')', '{', '}', '\''), 1709 array('\+', '\-', '\*', '\/', '\(', '\)', '\{', '\}', '\\\''), 1710 $operator 1711 ); 1712 1713 if(!empty($formula)) { 1714 if(!preg_match("/^([$operator\.\d\(\)]|(($var)([$operator\(\)]|$)+))+$/", $formula) || !is_null(eval(preg_replace("/($var)/", "\$\\1", $formula).';'))){ 1715 return false; 1716 } 1717 } 1718 return true; 1719 } 1720 1721 //检验积分公式语法 1722 function checkformulacredits($formula) { 1723 return checkformulasyntax( 1724 $formula, 1725 array('+', '-', '*', '/', ' '), 1726 array('extcredits[1-8]', 'digestposts', 'posts', 'threads', 'oltime', 'friends', 'doings', 'polls', 'blogs', 'albums', 'sharings') 1727 ); 1728 } 1729 1730 //临时调试通用 1731 function debug($var = null, $vardump = false) { 1732 echo '<pre>'; 1733 if($var === null) { 1734 print_r($GLOBALS); 1735 } else { 1736 if($vardump) { 1737 var_dump($var); 1738 } else { 1739 print_r($var); 1740 } 1741 } 1742 exit(); 1743 } 1744 1745 /** 1746 * 调试信息 1747 */ 1748 function debuginfo() { 1749 global $_G; 1750 if(getglobal('setting/debug')) { 1751 $db = & DB::object(); 1752 $_G['debuginfo'] = array( 1753 'time' => number_format((dmicrotime() - $_G['starttime']), 6), 1754 'queries' => $db->querynum, 1755 'memory' => ucwords($_G['memory']) 1756 ); 1757 if($db->slaveid) { 1758 $_G['debuginfo']['queries'] = 'Total '.$db->querynum.', Slave '.$db->slavequery; 1759 } 1760 return TRUE; 1761 } else { 1762 return FALSE; 1763 } 1764 } 1765 1766 /** 1767 * 随机取出一个站长推荐的条目 1768 * @param $module 当前模块 1769 * @return array 1770 */ 1771 function getfocus_rand($module) { 1772 global $_G; 1773 1774 if(empty($_G['setting']['focus']) || !array_key_exists($module, $_G['setting']['focus'])) { 1775 return null; 1776 } 1777 do { 1778 $focusid = $_G['setting']['focus'][$module][array_rand($_G['setting']['focus'][$module])]; 1779 if(!empty($_G['cookie']['nofocus_'.$focusid])) { 1780 unset($_G['setting']['focus'][$module][$focusid]); 1781 $continue = 1; 1782 } else { 1783 $continue = 0; 1784 } 1785 } while(!empty($_G['setting']['focus'][$module]) && $continue); 1786 if(!$_G['setting']['focus'][$module]) { 1787 return null; 1788 } 1789 loadcache('focus'); 1790 if(empty($_G['cache']['focus']['data']) || !is_array($_G['cache']['focus']['data'])) { 1791 return null; 1792 } 1793 return $focusid; 1794 } 1795 1796 /** 1797 * 检查验证码正确性 1798 * @param $value 验证码变量值 1799 */ 1800 function check_seccode($value, $idhash) { 1801 global $_G; 1802 if(!$_G['setting']['seccodestatus']) { 1803 return true; 1804 } 1805 if(!isset($_G['cookie']['seccode'.$idhash])) { 1806 return false; 1807 } 1808 list($checkvalue, $checktime, $checkidhash, $checkformhash) = explode("\t", authcode($_G['cookie']['seccode'.$idhash], 'DECODE', $_G['config']['security']['authkey'])); 1809 return $checkvalue == strtoupper($value) && TIMESTAMP - 180 > $checktime && $checkidhash == $idhash && FORMHASH == $checkformhash; 1810 } 1811 1812 /** 1813 * 检查验证问答正确性 1814 * @param $value 验证问答变量值 1815 */ 1816 function check_secqaa($value, $idhash) { 1817 global $_G; 1818 if(!$_G['setting']['secqaa']) { 1819 return true; 1820 } 1821 if(!isset($_G['cookie']['secqaa'.$idhash])) { 1822 return false; 1823 } 1824 loadcache('secqaa'); 1825 list($checkvalue, $checktime, $checkidhash, $checkformhash) = explode("\t", authcode($_G['cookie']['secqaa'.$idhash], 'DECODE', $_G['config']['security']['authkey'])); 1826 return $checkvalue == md5($value) && TIMESTAMP - 180 > $checktime && $checkidhash == $idhash && FORMHASH == $checkformhash; 1827 } 1828 1829 /** 1830 * 获取广告 1831 */ 1832 function adshow($parameter) { 1833 global $_G; 1834 if($_G['inajax']) { 1835 return; 1836 } 1837 $params = explode('/', $parameter); 1838 $customid = 0; 1839 $customc = explode('_', $params[0]); 1840 if($customc[0] == 'custom') { 1841 $params[0] = $customc[0]; 1842 $customid = $customc[1]; 1843 } 1844 $adcontent = null; 1845 if(empty($_G['setting']['advtype']) || !in_array($params[0], $_G['setting']['advtype'])) { 1846 $adcontent = ''; 1847 } 1848 if($adcontent === null) { 1849 loadcache('advs'); 1850 $adids = array(); 1851 $evalcode = &$_G['cache']['advs']['evalcode'][$params[0]]; 1852 $parameters = &$_G['cache']['advs']['parameters'][$params[0]]; 1853 $codes = &$_G['cache']['advs']['code'][$_G['basescript']][$params[0]]; 1854 if(!empty($codes)) { 1855 foreach($codes as $adid => $code) { 1856 $parameter = &$parameters[$adid]; 1857 $checked = true; 1858 @eval($evalcode['check']); 1859 if($checked) { 1860 $adids[] = $adid; 1861 } 1862 } 1863 if(!empty($adids)) { 1864 $adcode = $extra = ''; 1865 @eval($evalcode['create']); 1866 if(empty($notag)) { 1867 $adcontent = '<div'.($params[1] != '' ? ' class="'.$params[1].'"' : '').$extra.'>'.$adcode.'</div>'; 1868 } else { 1869 $adcontent = $adcode; 1870 } 1871 } 1872 } 1873 } 1874 $adfunc = 'ad_'.$params[0]; 1875 $_G['setting']['pluginhooks'][$adfunc] = null; 1876 hookscript('ad', 'global', 'funcs', array('params' => $params, 'content' => $adcontent), $adfunc); 1877 hookscript('ad', $_G['basescript'], 'funcs', array('params' => $params, 'content' => $adcontent), $adfunc); 1878 return $_G['setting']['pluginhooks'][$adfunc] === null ? $adcontent : $_G['setting']['pluginhooks'][$adfunc]; 1879 } 1880 1881 /** 1882 * 显示提示信息 1883 * @param $message - 提示信息,可中文也可以是 lang_message.php 中的数组 key 值 1884 * @param $url_forward - 提示后跳转的 url 1885 * @param $values - 提示信息中可替换的变量值 array(key => value ...) 形式 1886 * @param $extraparam - 扩展参数 array(key => value ...) 形式 1887 * 跳转控制 1888 header header跳转 1889 location location JS 跳转,限于 msgtype = 2、3 1890 timeout 定时跳转 1891 refreshtime 自定义跳转时间 1892 closetime 自定义关闭时间,限于 msgtype = 2,值为 true 时为默认 1893 locationtime 自定义跳转时间,限于 msgtype = 2,值为 true 时为默认 1894 内容控制 1895 alert alert 图标样式 right/info/error 1896 return 显示请返回 1897 redirectmsg 下载时用的提示信息,当跳转时显示的信息样式 1898 0:如果您的浏览器没有自动跳转,请点击此链接 1899 1:如果 n 秒后下载仍未开始,请点击此链接 1900 msgtype 信息样式 1901 1:非 Ajax 1902 2:Ajax 弹出框 1903 3:Ajax 只显示信息文本 1904 showmsg 显示信息文本 1905 showdialog 关闭原弹出框显示 showDialog 信息,限于 msgtype = 2 1906 login 未登录时显示登录链接 1907 extrajs 扩展 js 1908 striptags 过滤 HTML 标记 1909 Ajax 控制 1910 handle 执行 js 回调函数 1911 showid 控制显示的对象 ID 1912 */ 1913 function showmessage($message, $url_forward = '', $values = array(), $extraparam = array(), $custom = 0) { 1914 require_once libfile('function/message'); 1915 return dshowmessage($message, $url_forward, $values, $extraparam, $custom); 1916 } 1917 1918 /** 1919 * 检查是否正确提交了表单 1920 * @param $var 需要检查的变量 1921 * @param $allowget 是否允许GET方式 1922 * @param $seccodecheck 验证码检测是否开启 1923 * @return 返回是否正确提交了表单 1924 */ 1925 function submitcheck($var, $allowget = 0, $seccodecheck = 0, $secqaacheck = 0) { 1926 if(!getgpc($var)) { 1927 return FALSE; 1928 } else { 1929 global $_G; 1930 //note mobiledata 1931 if(!empty($_G['gp_mobiledata'])) { 1932 require_once libfile('class/mobiledata'); 1933 $mobiledata = new mobiledata(); 1934 if($mobiledata->validator()) { 1935 return TRUE; 1936 } 1937 } 1938 if($allowget || ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_G['gp_formhash']) && $_G['gp_formhash'] == formhash() && empty($_SERVER['HTTP_X_FLASH_VERSION']) && (empty($_SERVER['HTTP_REFERER']) || 1939 preg_replace("/https?:\/\/([^\:\/]+).*/i", "\\1", $_SERVER['HTTP_REFERER']) == preg_replace("/([^\:]+).*/", "\\1", $_SERVER['HTTP_HOST'])))) { 1940 if(checkperm('seccode')) { 1941 if($secqaacheck && !check_secqaa($_G['gp_secanswer'], $_G['gp_sechash'])) { 1942 showmessage('submit_secqaa_invalid'); 1943 } 1944 if($seccodecheck && !check_seccode($_G['gp_seccodeverify'], $_G['gp_sechash'])) { 1945 showmessage('submit_seccode_invalid'); 1946 } 1947 } 1948 return TRUE; 1949 } else { 1950 showmessage('submit_invalid'); 1951 } 1952 } 1953 } 1954 1955 /** 1956 * 分页 1957 * @param $num - 总数 1958 * @param $perpage - 每页数 1959 * @param $curpage - 当前页 1960 * @param $mpurl - 跳转的路径 1961 * @param $maxpages - 允许显示的最大页数 1962 * @param $page - 最多显示多少页码 1963 * @param $autogoto - 最后一页,自动跳转 1964 * @param $simple - 是否简洁模式(简洁模式不显示上一页、下一页和页码跳转) 1965 * @return 返回分页代码 1966 */ 1967 function multi($num, $perpage, $curpage, $mpurl, $maxpages = 0, $page = 10, $autogoto = FALSE, $simple = FALSE) { 1968 global $_G; 1969 //debug 加入 ajaxtarget 属性 1970 $ajaxtarget = !empty($_G['gp_ajaxtarget']) ? " ajaxtarget=\"".htmlspecialchars($_G['gp_ajaxtarget'])."\" " : ''; 1971 1972 //note 处理#描点 1973 $a_name = ''; 1974 if(strpos($mpurl, '#') !== FALSE) { 1975 $a_strs = explode('#', $mpurl); 1976 $mpurl = $a_strs[0]; 1977 $a_name = '#'.$a_strs[1]; 1978 } 1979 1980 if(defined('IN_ADMINCP')) { 1981 $shownum = $showkbd = TRUE; 1982 $lang['prev'] = '‹‹'; 1983 $lang['next'] = '››'; 1984 } else { 1985 $shownum = $showkbd = FALSE; 1986 //noteX 手机模式下使用语言包的上下翻页(IN_MOBILE) 1987 if(defined('IN_MOBILE') && !defined('TPL_DEFAULT')) { 1988 $lang['prev'] = lang('core', 'prevpage'); 1989 $lang['next'] = lang('core', 'nextpage'); 1990 } else { 1991 $lang['prev'] = ' '; 1992 $lang['next'] = lang('core', 'nextpage'); 1993 } 1994 } 1995 //noteX 手机模式下使用较小的页数和小点(IN_MOBILE) 1996 if(defined('IN_MOBILE') && !defined('TPL_DEFAULT')) { 1997 $dot = '..'; 1998 $page = intval($page) < 10 && intval($page) > 0 ? $page : 4 ; 1999 } else { 2000 $dot = '...'; 2001 } 2002 $multipage = ''; 2003 $mpurl .= strpos($mpurl, '?') !== FALSE ? '&' : '?'; 2004 2005 $realpages = 1; 2006 $_G['page_next'] = 0; 2007 $page -= strlen($curpage) - 1; 2008 if($page <= 0) { 2009 $page = 1; 2010 } 2011 if($num > $perpage) { 2012 2013 $offset = floor($page * 0.5); 2014 2015 $realpages = @ceil($num / $perpage); 2016 $pages = $maxpages && $maxpages < $realpages ? $maxpages : $realpages; 2017 2018 if($page > $pages) { 2019 $from = 1; 2020 $to = $pages; 2021 } else { 2022 $from = $curpage - $offset; 2023 $to = $from + $page - 1; 2024 if($from < 1) { 2025 $to = $curpage + 1 - $from; 2026 $from = 1; 2027 if($to - $from < $page) { 2028 $to = $page; 2029 } 2030 } elseif($to > $pages) { 2031 $from = $pages - $page + 1; 2032 $to = $pages; 2033 } 2034 } 2035 $_G['page_next'] = $to; 2036 //noteX 替换小点为$dot变量(IN_MOBILE) 2037 $multipage = ($curpage - $offset > 1 && $pages > $page ? '<a href="'.$mpurl.'page=1'.$a_name.'" class="first"'.$ajaxtarget.'>1 '.$dot.'</a>' : ''). 2038 ($curpage > 1 && !$simple ? '<a href="'.$mpurl.'page='.($curpage - 1).$a_name.'" class="prev"'.$ajaxtarget.'>'.$lang['prev'].'</a>' : ''); 2039 for($i = $from; $i <= $to; $i++) { 2040 $multipage .= $i == $curpage ? '<strong>'.$i.'</strong>' : 2041 '<a href="'.$mpurl.'page='.$i.($ajaxtarget && $i == $pages && $autogoto ? '#' : $a_name).'"'.$ajaxtarget.'>'.$i.'</a>'; 2042 } 2043 //noteX 替换小点为$dot变量(IN_MOBILE) 2044 $multipage .= ($to < $pages ? '<a href="'.$mpurl.'page='.$pages.$a_name.'" class="last"'.$ajaxtarget.'>'.$dot.' '.$realpages.'</a>' : ''). 2045 ($curpage < $pages && !$simple ? '<a href="'.$mpurl.'page='.($curpage + 1).$a_name.'" class="nxt"'.$ajaxtarget.'>'.$lang['next'].'</a>' : ''). 2046 ($showkbd && !$simple && $pages > $page && !$ajaxtarget ? '<kbd><input type="text" name="custompage" size="3" onkeydown="if(event.keyCode==13) {window.location=\''.$mpurl.'page=\'+this.value; doane(event);}" /></kbd>' : ''); 2047 2048 $multipage = $multipage ? '<div class="pg">'.($shownum && !$simple ? '<em> '.$num.' </em>' : '').$multipage.'</div>' : ''; 2049 } 2050 $maxpage = $realpages; 2051 return $multipage; 2052 } 2053 2054 /** 2055 * 只有上一页下一页的分页(无需知道数据总数) 2056 * @param $num - 本次所取数据条数 2057 * @param $perpage - 每页数 2058 * @param $curpage - 当前页 2059 * @param $mpurl - 跳转的路径 2060 * @return 返回分页代码 2061 */ 2062 function simplepage($num, $perpage, $curpage, $mpurl) { 2063 $return = ''; 2064 $lang['next'] = lang('core', 'nextpage'); 2065 $lang['prev'] = lang('core', 'prevpage'); 2066 $next = $num == $perpage ? '<a href="'.$mpurl.'&page='.($curpage + 1).'" class="nxt">'.$lang['next'].'</a>' : ''; 2067 $prev = $curpage > 1 ? '<span class="pgb"><a href="'.$mpurl.'&page='.($curpage - 1).'">'.$lang['prev'].'</a></span>' : ''; 2068 if($next || $prev) { 2069 $return = '<div class="pg">'.$prev.$next.'</div>'; 2070 } 2071 return $return; 2072 } 2073 2074 /** 2075 * 词语过滤 2076 * @param $message - 词语过滤文本 2077 * @return 成功返回原始文本,否则提示错误或被替换 2078 */ 2079 function censor($message, $modword = NULL, $return = FALSE) { 2080 global $_G; 2081 require_once libfile('class/censor'); 2082 $censor = discuz_censor::instance(); 2083 $censor->check($message, $modword); 2084 if($censor->modbanned() && !$_G['group']['ignorecensor']) { 2085 $wordbanned = implode(', ', $censor->words_found); 2086 if($return) { 2087 return array('message' => lang('message', 'word_banned', array('wordbanned' => $wordbanned))); 2088 } 2089 if(!defined('IN_ADMINCP')) { 2090 showmessage('word_banned', '', array('wordbanned' => $wordbanned)); 2091 } else { 2092 cpmsg(lang('message', 'word_banned'), '', 'error', array('wordbanned' => $wordbanned)); 2093 } 2094 } 2095 if($_G['group']['allowposturl'] == 0 || $_G['group']['allowposturl'] == 2) { 2096 $urllist = get_url_list($message); 2097 if(is_array($urllist[1])) foreach($urllist[1] as $key => $val) { 2098 if(!$val = trim($val)) continue; 2099 if(!iswhitelist($val)) { 2100 if($_G['group']['allowposturl'] == 0) { 2101 showmessage('post_url_nopermission'); 2102 } elseif($_G['group']['allowposturl'] == 2) { 2103 $message = str_replace('[url]'.$urllist[0][$key].'[/url]', $urllist[0][$key], $message); 2104 $message = preg_replace( 2105 array( 2106 "@\[url=.*?".preg_quote($urllist[0][$key],'@').".*?\](.*?)\[/url\]@is", 2107 "@href=('|\")".preg_quote($urllist[0][$key],'@')."\\1@is", 2108 "@\[url\](.*?".preg_quote($urllist[0][$key],'@').".*?)\[/url\]@is", 2109 ), 2110 array( 2111 '\\1', 2112 '', 2113 '\\1', 2114 ), 2115 $message); 2116 } 2117 } 2118 } 2119 } 2120 return $message; 2121 } 2122 2123 /** 2124 词语过滤,检测是否含有需要审核的词 2125 */ 2126 function censormod($message) { 2127 global $_G; 2128 if($_G['group']['ignorecensor']) { 2129 return false; 2130 } 2131 $modposturl = false; 2132 if($_G['group']['allowposturl'] == 1) { 2133 $urllist = get_url_list($message); 2134 if(is_array($urllist[1])) foreach($urllist[1] as $key => $val) { 2135 if(!$val = trim($val)) continue; 2136 if(!iswhitelist($val)) { 2137 $modposturl = true; 2138 } 2139 } 2140 } 2141 if($modposturl) { 2142 return true; 2143 } 2144 2145 require_once libfile('class/censor'); 2146 $censor = discuz_censor::instance(); 2147 $censor->check($message); 2148 return $censor->modmoderated(); 2149 } 2150 2151 //获取用户附属表信息,累加到第一个变量$values 2152 function space_merge(&$values, $tablename) { 2153 global $_G; 2154 2155 $uid = empty($values['uid'])?$_G['uid']:$values['uid'];//默认当前用户 2156 $var = "member_{$uid}_{$tablename}"; 2157 if($uid) { 2158 if(!isset($_G[$var])) { 2159 $query = DB::query("SELECT * FROM ".DB::table('common_member_'.$tablename)." WHERE uid='$uid'"); 2160 if($_G[$var] = DB::fetch($query)) { 2161 if($tablename == 'field_home') { 2162 //隐私设置 2163 $_G['setting']['privacy'] = empty($_G['setting']['privacy']) ? array() : (is_array($_G['setting']['privacy']) ? $_G['setting']['privacy'] : unserialize($_G['setting']['privacy'])); 2164 $_G[$var]['privacy'] = empty($_G[$var]['privacy'])? array() : is_array($_G[$var]['privacy']) ? $_G[$var]['privacy'] : unserialize($_G[$var]['privacy']); 2165 foreach (array('feed','view','profile') as $pkey) { 2166 if(empty($_G[$var]['privacy'][$pkey]) && !isset($_G[$var]['privacy'][$pkey])) { 2167 $_G[$var]['privacy'][$pkey] = isset($_G['setting']['privacy'][$pkey]) ? $_G['setting']['privacy'][$pkey] : array();//取站点默认设置 2168 } 2169 } 2170 //邮件提醒 2171 $_G[$var]['acceptemail'] = empty($_G[$var]['acceptemail'])? array() : unserialize($_G[$var]['acceptemail']); 2172 if(empty($_G[$var]['acceptemail'])) { 2173 $_G[$var]['acceptemail'] = empty($_G['setting']['acceptemail'])?array():unserialize($_G['setting']['acceptemail']); 2174 } 2175 } 2176 } else { 2177 //插入默认数据 2178 DB::insert('common_member_'.$tablename, array('uid'=>$uid)); 2179 $_G[$var] = array(); 2180 } 2181 } 2182 $values = array_merge($values, $_G[$var]); 2183 } 2184 } 2185 2186 /* 2187 * 运行log记录 2188 */ 2189 function runlog($file, $message, $halt=0) { 2190 global $_G; 2191 2192 $nowurl = $_SERVER['REQUEST_URI']?$_SERVER['REQUEST_URI']:($_SERVER['PHP_SELF']?$_SERVER['PHP_SELF']:$_SERVER['SCRIPT_NAME']); 2193 $log = dgmdate($_G['timestamp'], 'Y-m-d H:i:s')."\t".$_G['clientip']."\t$_G[uid]\t{$nowurl}\t".str_replace(array("\r", "\n"), array(' ', ' '), trim($message))."\n"; 2194 writelog($file, $log); 2195 if($halt) { 2196 exit(); 2197 } 2198 } 2199 2200 /* 2201 * 处理搜索关键字 2202 */ 2203 function stripsearchkey($string) { 2204 $string = trim($string); 2205 $string = str_replace('*', '%', addcslashes($string, '%_')); 2206 $string = str_replace('_', '\_', $string); 2207 return $string; 2208 } 2209 2210 /* 2211 * 递归创建目录 2212 */ 2213 function dmkdir($dir, $mode = 0777, $makeindex = TRUE){ 2214 if(!is_dir($dir)) { 2215 dmkdir(dirname($dir), $mode, $makeindex); 2216 @mkdir($dir, $mode); 2217 if(!empty($makeindex)) { 2218 @touch($dir.'/index.html'); @chmod($dir.'/index.html', 0777); 2219 } 2220 } 2221 return true; 2222 } 2223 2224 /** 2225 * 刷新重定向 2226 */ 2227 function dreferer($default = '') { 2228 global $_G; 2229 2230 $default = empty($default) ? $GLOBALS['_t_curapp'] : ''; 2231 $_G['referer'] = !empty($_G['gp_referer']) ? $_G['gp_referer'] : $_SERVER['HTTP_REFERER']; 2232 $_G['referer'] = substr($_G['referer'], -1) == '?' ? substr($_G['referer'], 0, -1) : $_G['referer']; 2233 2234 if(strpos($_G['referer'], 'member.php?mod=logging')) { 2235 $_G['referer'] = $default; 2236 } 2237 $_G['referer'] = htmlspecialchars($_G['referer'], ENT_QUOTES); 2238 $_G['referer'] = str_replace('&', '&', $_G['referer']); 2239 $reurl = parse_url($_G['referer']); 2240 //判断host是否相同,不同时做进步的校验 2241 if(!empty($reurl['host']) && !in_array($reurl['host'], array($_SERVER['HTTP_HOST'], 'www.'.$_SERVER['HTTP_HOST'])) && !in_array($_SERVER['HTTP_HOST'], array($reurl['host'], 'www.'.$reurl['host']))) { 2242 //校验是否在应用域名或版块域名配置中 2243 if(!in_array($reurl['host'], $_G['setting']['domain']['app']) && !isset($_G['setting']['domain']['list'][$reurl['host']])) { 2244 $domainroot = substr($reurl['host'], strpos($reurl['host'], '.')+1); 2245 //是否为子域名,如果不为子域名则跳到index.php 2246 if(empty($_G['setting']['domain']['root']) || (is_array($_G['setting']['domain']['root']) && !in_array($domainroot, $_G['setting']['domain']['root']))) { 2247 $_G['referer'] = $_G['setting']['domain']['defaultindex'] ? $_G['setting']['domain']['defaultindex'] : 'index.php'; 2248 } 2249 } 2250 } elseif(empty($reurl['host'])) { 2251 $_G['referer'] = $_G['siteurl'].'./'.$_G['referer']; 2252 } 2253 return strip_tags($_G['referer']); 2254 } 2255 2256 /** 2257 * 远程FTP使用 2258 */ 2259 function ftpcmd($cmd, $arg1 = '') { 2260 static $ftp; 2261 $ftpon = getglobal('setting/ftp/on'); 2262 if(!$ftpon) { 2263 return $cmd == 'error' ? -101 : 0; 2264 } elseif($ftp == null) { 2265 require_once libfile('class/ftp'); 2266 $ftp = & discuz_ftp::instance(); 2267 } 2268 if(!$ftp->enabled) { 2269 return $ftp->error(); 2270 } elseif($ftp->enabled && !$ftp->connectid) { 2271 $ftp->connect(); 2272 } 2273 switch ($cmd) { 2274 case 'upload' : return $ftp->upload(getglobal('setting/attachdir').'/'.$arg1, $arg1); break; 2275 case 'delete' : return $ftp->ftp_delete($arg1); break; 2276 case 'close' : return $ftp->ftp_close(); break; 2277 case 'error' : return $ftp->error(); break; 2278 case 'object' : return $ftp; break; 2279 default : return false; 2280 } 2281 2282 } 2283 2284 /** 2285 * 编码转换 2286 * @param <string> $str 要转码的字符 2287 * @param <string> $in_charset 输入字符集 2288 * @param <string> $out_charset 输出字符集(默认当前) 2289 * @param <boolean> $ForceTable 强制使用码表(默认不强制) 2290 * 2291 */ 2292 function diconv($str, $in_charset, $out_charset = CHARSET, $ForceTable = FALSE) { 2293 global $_G; 2294 2295 $in_charset = strtoupper($in_charset); 2296 $out_charset = strtoupper($out_charset); 2297 2298 if(empty($str) || $in_charset == $out_charset) { 2299 return $str; 2300 } 2301 2302 $out = ''; 2303 2304 if(!$ForceTable) { 2305 if(function_exists('iconv')) { 2306 $out = iconv($in_charset, $out_charset.'//IGNORE', $str); 2307 } elseif(function_exists('mb_convert_encoding')) { 2308 $out = mb_convert_encoding($str, $out_charset, $in_charset); 2309 } 2310 } 2311 2312 if($out == '') { 2313 require_once libfile('class/chinese'); 2314 $chinese = new Chinese($in_charset, $out_charset, true); 2315 $out = $chinese->Convert($str); 2316 } 2317 2318 return $out; 2319 } 2320 2321 /** 2322 * 重建数组 2323 * @param <string> $array 需要反转的数组 2324 * @return array 原数组与的反转后的数组 2325 */ 2326 function renum($array) { 2327 $newnums = $nums = array(); 2328 foreach ($array as $id => $num) { 2329 $newnums[$num][] = $id; 2330 $nums[$num] = $num; 2331 } 2332 return array($nums, $newnums); 2333 } 2334 2335 /** 2336 * 获取当前脚本在线人数 2337 * @param <int> $fid 分类 ID,版块、群组 的 id, 2338 * @param <int> $tid 内容 ID,帖子 的 id 2339 */ 2340 function getonlinenum($fid = 0, $tid = 0) { 2341 if($fid) { 2342 $sql = " AND fid='$fid'"; 2343 } 2344 if($tid) { 2345 $sql = " AND tid='$tid'"; 2346 } 2347 return DB::result_first('SELECT count(*) FROM '.DB::table("common_session")." WHERE 1 $sql"); 2348 } 2349 2350 /** 2351 * 字节格式化单位 2352 * @param $filesize - 大小(字节) 2353 * @return 返回格式化后的文本 2354 */ 2355 function sizecount($size) { 2356 if($size >= 1073741824) { 2357 $size = round($size / 1073741824 * 100) / 100 . ' GB'; 2358 } elseif($size >= 1048576) { 2359 $size = round($size / 1048576 * 100) / 100 . ' MB'; 2360 } elseif($size >= 1024) { 2361 $size = round($size / 1024 * 100) / 100 . ' KB'; 2362 } else { 2363 $size = $size . ' Bytes'; 2364 } 2365 return $size; 2366 } 2367 2368 function swapclass($class1, $class2 = '') { 2369 static $swapc = null; 2370 $swapc = isset($swapc) && $swapc != $class1 ? $class1 : $class2; 2371 return $swapc; 2372 } 2373 2374 /** 2375 * 写入运行日志 2376 */ 2377 function writelog($file, $log) { 2378 global $_G; 2379 $yearmonth = dgmdate(TIMESTAMP, 'Ym', $_G['setting']['timeoffset']); 2380 $logdir = DISCUZ_ROOT.'./data/log/'; 2381 $logfile = $logdir.$yearmonth.'_'.$file.'.php'; 2382 if(@filesize($logfile) > 2048000) { 2383 $dir = opendir($logdir); 2384 $length = strlen($file); 2385 $maxid = $id = 0; 2386 while($entry = readdir($dir)) { 2387 if(strpos($entry, $yearmonth.'_'.$file) !== false) { 2388 $id = intval(substr($entry, $length + 8, -4)); 2389 $id > $maxid && $maxid = $id; 2390 } 2391 } 2392 closedir($dir); 2393 2394 $logfilebak = $logdir.$yearmonth.'_'.$file.'_'.($maxid + 1).'.php'; 2395 @rename($logfile, $logfilebak); 2396 } 2397 if($fp = @fopen($logfile, 'a')) { 2398 @flock($fp, 2); 2399 $log = is_array($log) ? $log : array($log); 2400 foreach($log as $tmp) { 2401 fwrite($fp, "<?PHP exit;?>\t".str_replace(array('<?', '?>'), '', $tmp)."\n"); 2402 } 2403 fclose($fp); 2404 } 2405 } 2406 /** 2407 * 调色板 2408 * @param <type> $colorid 2409 * @param <type> $id 2410 * @param <type> $background 2411 * @return <type> 2412 */ 2413 function getcolorpalette($colorid, $id, $background, $fun = '') { 2414 return "<input id=\"c$colorid\" onclick=\"c{$colorid}_frame.location='static/image/admincp/getcolor.htm?c{$colorid}|{$id}|{$fun}';showMenu({'ctrlid':'c$colorid'})\" type=\"button\" class=\"colorwd\" value=\"\" style=\"background: $background\"><span id=\"c{$colorid}_menu\" style=\"display: none\"><iframe name=\"c{$colorid}_frame\" src=\"\" frameborder=\"0\" width=\"210\" height=\"148\" scrolling=\"no\"></iframe></span>"; 2415 } 2416 2417 /** 2418 * 取得某标志位的数值 (0|1) 2419 * 2420 * @param 数值 $status 2421 * @param 位置 $position 2422 * @return 0 | 1 2423 */ 2424 function getstatus($status, $position) { 2425 $t = $status & pow(2, $position - 1) ? 1 : 0; 2426 return $t; 2427 } 2428 2429 /** 2430 * 设置某一bit位的数值 0 or 1 2431 * 2432 * @param int $position 1-16 2433 * @param int $value 0|1 2434 * @param 原始数值 $baseon 0x0000-0xffff 2435 * @return int 2436 */ 2437 function setstatus($position, $value, $baseon = null) { 2438 $t = pow(2, $position - 1); 2439 if($value) { 2440 $t = $baseon | $t; 2441 } elseif ($baseon !== null) { 2442 $t = $baseon & ~$t; 2443 } else { 2444 $t = ~$t; 2445 } 2446 return $t & 0xFFFF; 2447 } 2448 2449 /** 2450 * 通知 2451 * @param Integer $touid: 通知给谁 2452 * @param String $type: 通知类型 2453 * @param String $note: 语言key 2454 * @param Array $notevars: 语言变量对应的值 2455 * @param Integer $system: 是否为系统通知 0:非系统通知; 1:系统通知 2456 */ 2457 function notification_add($touid, $type, $note, $notevars = array(), $system = 0) { 2458 global $_G; 2459 2460 $tospace = array('uid'=>$touid); 2461 space_merge($tospace, 'field_home'); 2462 $filter = empty($tospace['privacy']['filter_note'])?array():array_keys($tospace['privacy']['filter_note']); 2463 2464 //检查用户屏蔽 2465 if($filter && (in_array($type.'|0', $filter) || in_array($type.'|'.$_G['uid'], $filter))) { 2466 return false; 2467 } 2468 2469 //获取note的语言 2470 $notevars['actor'] = "<a href=\"home.php?mod=space&uid=$_G[uid]\">".$_G['member']['username']."</a>"; 2471 //非漫游通知 2472 if(!is_numeric($type)) { 2473 $vars = explode(':', $note); 2474 if(count($vars) == 2) { 2475 $notestring = lang('plugin/'.$vars[0], $vars[1], $notevars); 2476 } else { 2477 $notestring = lang('notification', $note, $notevars); 2478 } 2479 $frommyapp = false; 2480 } else { 2481 $frommyapp = true; 2482 $notestring = $note; 2483 } 2484 2485 //note去重 2486 $oldnote = array(); 2487 if($notevars['from_id'] && $notevars['from_idtype']) { 2488 $oldnote = DB::fetch_first("SELECT * FROM ".DB::table('home_notification')." 2489 WHERE from_id='$notevars[from_id]' AND from_idtype='$notevars[from_idtype]' AND uid='$touid'"); 2490 } 2491 if(empty($oldnote['from_num'])) $oldnote['from_num'] = 0; 2492 $notevars['from_num'] = $notevars['from_num'] ? $notevars['from_num'] : 1; 2493 $setarr = array( 2494 'uid' => $touid, 2495 'type' => $type, 2496 'new' => 1, 2497 'authorid' => $_G['uid'], 2498 'author' => $_G['username'], 2499 'note' => addslashes($notestring), 2500 'dateline' => $_G['timestamp'], 2501 'from_id' => $notevars['from_id'], 2502 'from_idtype' => $notevars['from_idtype'], 2503 'from_num' => ($oldnote['from_num']+$notevars['from_num']) 2504 ); 2505 if($system) { 2506 $setarr['authorid'] = 0; 2507 $setarr['author'] = ''; 2508 } 2509 2510 if($oldnote['id']) { 2511 DB::update('home_notification', $setarr, array('id'=>$oldnote['id'])); 2512 } else { 2513 $oldnote['new'] = 0; 2514 DB::insert('home_notification', $setarr); 2515 } 2516 2517 //更新用户通知 2518 if(empty($oldnote['new'])) { 2519 DB::query("UPDATE ".DB::table('common_member')." SET newprompt=newprompt+1 WHERE uid='$touid'"); 2520 2521 //给用户发送邮件通知 2522 require_once libfile('function/mail'); 2523 $mail_subject = lang('notification', 'mail_to_user'); 2524 sendmail_touser($touid, $mail_subject, $notestring, $frommyapp ? 'myapp' : $type); 2525 } 2526 2527 //更新我的好友关系热度 2528 if(!$system && $_G['uid'] && $touid != $_G['uid']) { 2529 DB::query("UPDATE ".DB::table('home_friend')." SET num=num+1 WHERE uid='$_G[uid]' AND fuid='$touid'"); 2530 } 2531 } 2532 2533 /** 2534 * 发送管理通知 2535 * @param $type - 通知类型 2536 */ 2537 function manage_addnotify($type, $from_num = 0, $langvar = array()) { 2538 global $_G; 2539 $notifyusers = unserialize($_G['setting']['notifyusers']); 2540 $notifytypes = explode(',', $_G['setting']['adminnotifytypes']); 2541 $notifytypes = array_flip($notifytypes); 2542 $notearr = array('from_id' => 1,'from_idtype' => $type, 'from_num' => $from_num); 2543 if($langvar) { 2544 $langkey = $langvar['langkey']; 2545 $notearr = array_merge($notearr, $langvar); 2546 } else { 2547 $langkey = 'manage_'.$type; 2548 } 2549 foreach($notifyusers as $uid => $user) { 2550 if($user['types'][$notifytypes[$type]]) { 2551 notification_add($uid, $type, $langkey, $notearr, 1); 2552 } 2553 } 2554 } 2555 2556 /** 2557 * 发送短消息(兼容提醒) 2558 * @param $toid - 接收方id 2559 * @param $subject - 标题 2560 * @param $message - 内容 2561 * @param $fromid - 发送方id 2562 */ 2563 function sendpm($toid, $subject, $message, $fromid = '', $replypmid = 0, $isusername = 0, $type = 0) { 2564 global $_G; 2565 if($fromid === '') { 2566 $fromid = $_G['uid']; 2567 } 2568 loaducenter(); 2569 return uc_pm_send($fromid, $toid, $subject, $message, 1, $replypmid, $isusername, $type); 2570 } 2571 2572 //获得用户组图标 2573 function g_icon($groupid, $return = 0) { 2574 global $_G; 2575 if(empty($_G['cache']['usergroups'][$groupid]['icon'])) { 2576 $s = ''; 2577 } else { 2578 if(substr($_G['cache']['usergroups'][$groupid]['icon'], 0, 5) == 'http:') { 2579 $s = '<img src="'.$_G['cache']['usergroups'][$groupid]['icon'].'" alt="" class="vm" />'; 2580 } else { 2581 $s = '<img src="'.$_G['setting']['attachurl'].'common/'.$_G['cache']['usergroups'][$groupid]['icon'].'" alt="" class="vm" />'; 2582 } 2583 } 2584 if($return) { 2585 return $s; 2586 } else { 2587 echo $s; 2588 } 2589 } 2590 //从数据库中更新DIY模板文件 2591 function updatediytemplate($targettplname = '') { 2592 global $_G; 2593 $r = false; 2594 $where = empty($targettplname) ? '' : " WHERE targettplname='$targettplname'"; 2595 $query = DB::query("SELECT * FROM ".DB::table('common_diy_data')."$where"); 2596 require_once libfile('function/portalcp'); 2597 while($value = DB::fetch($query)) { 2598 $r = save_diy_data($value['primaltplname'], $value['targettplname'], unserialize($value['diycontent'])); 2599 } 2600 return $r; 2601 } 2602 2603 //获得用户唯一串 2604 function space_key($uid, $appid=0) { 2605 global $_G; 2606 2607 $siteuniqueid = DB::result_first("SELECT svalue FROM ".DB::table('common_setting')." WHERE skey='siteuniqueid'"); 2608 return substr(md5($siteuniqueid.'|'.$uid.(empty($appid)?'':'|'.$appid)), 8, 16); 2609 } 2610 2611 2612 //note post分表相关函数 2613 /** 2614 * 2615 * 通过tid得到相应的单一post表名或post表集合 2616 * @param <mix> $tids: 允许传进单个tid,也可以是tid集合 2617 * @param $primary: 是否只查主题表 0:遍历所有表;1:只查主表 2618 * @return 当传进来的是单一的tid将直接返回表名,否则返回表集合的二维数组例:array('forum_post' => array(tids),'forum_post_1' => array(tids)) 2619 * @TODO tid传进来的是字符串的,返回单个表名,传进来的是数组的,不管是不是一个数组,返回的还是数组,保证进出值对应 2620 */ 2621 function getposttablebytid($tids, $primary = 0) { 2622 global $_G; 2623 2624 $isstring = false; 2625 if(!is_array($tids)) { 2626 $tids = array(intval($tids)); 2627 $isstring = true; 2628 } 2629 //note 过滤重复的tid 2630 $tids = array_unique($tids); 2631 //note 反转数组、便于下面的踢除操作 2632 $tids = array_flip($tids); 2633 if(!$primary) { 2634 loadcache('threadtableids'); 2635 $threadtableids = !empty($_G['cache']['threadtableids']) ? $_G['cache']['threadtableids'] : array(); 2636 if(!in_array(0, $threadtableids)) { 2637 $threadtableids = array_merge(array(0), $threadtableids); 2638 } 2639 } else { 2640 $threadtableids = array(0); 2641 } 2642 $tables = array(); 2643 $posttable = ''; 2644 $singletable = count($tids) > 1 ? false : true; 2645 //note 遍历存档表 2646 foreach($threadtableids as $tableid) { 2647 $threadtable = $tableid ? "forum_thread_$tableid" : 'forum_thread'; 2648 $query = DB::query("SELECT tid, posttableid FROM ".DB::table($threadtable)." WHERE tid IN(".dimplode(array_keys($tids)).")"); 2649 while ($value = DB::fetch($query)) { 2650 $posttable = 'forum_post'.($value['posttableid'] ? "_$value[posttableid]" : ''); 2651 $tables[$posttable][$value['tid']] = $value['tid']; 2652 unset($tids[$value['tid']]); 2653 } 2654 if(!count($tids)) { 2655 break; 2656 } 2657 } 2658 if(empty($posttable)) { 2659 $posttable = 'forum_post'; 2660 $tables[$posttable] = array_flip($tids); 2661 } 2662 return $isstring ? $posttable : $tables; 2663 } 2664 2665 /** 2666 * 获取论坛帖子表名 2667 * @param <int> $tableid: 分表ID,默认为:fourm_post表 2668 * @param <boolean> $prefix: 是否默认带有表前缀 2669 * @return forum_post or forum_post_* 2670 */ 2671 function getposttable($tableid = 0, $prefix = false) { 2672 global $_G; 2673 $tableid = intval($tableid); 2674 if($tableid) { 2675 //TODO 可以考虑在此加入验证表名 2676 loadcache('posttableids'); 2677 $tableid = $_G['cache']['posttableids'] && in_array($tableid, $_G['cache']['posttableids']) ? $tableid : 0; 2678 $tablename = 'forum_post'.($tableid ? "_$tableid" : ''); 2679 } else { 2680 $tablename = 'forum_post'; 2681 } 2682 if($prefix) { 2683 $tablename = DB::table($tablename); 2684 } 2685 return $tablename; 2686 } 2687 2688 /** 2689 * 内存读写接口函数 2690 * 2691 * @param 命令 $cmd (set|get|rm|check) 2692 * @param 键值 $key 2693 * @param 数据 $value 2694 * @param 有效期 $ttl 2695 * @return mix 2696 * 2697 * @example set : 写入内存 $ret = memory('set', 'test', 'ok') 2698 * @example get : 读取内存 $data = memory('get', 'test') 2699 * @example rm : 删除内存 $ret = memory('rm', 'test') 2700 * @example check : 检查内存功能是否可用 $allow = memory('check') 2701 */ 2702 function memory($cmd, $key='', $value='', $ttl = 0) { 2703 $discuz = & discuz_core::instance(); 2704 if($cmd == 'check') { 2705 return $discuz->mem->enable ? $discuz->mem->type : ''; 2706 } elseif($discuz->mem->enable && in_array($cmd, array('set', 'get', 'rm'))) { 2707 switch ($cmd) { 2708 case 'set': return $discuz->mem->set($key, $value, $ttl); break; 2709 case 'get': return $discuz->mem->get($key); break; 2710 case 'rm': return $discuz->mem->rm($key); break; 2711 } 2712 } 2713 return null; 2714 } 2715 2716 /** 2717 * ip允许访问 2718 * @param $ip 要检查的ip地址 2719 * @param - $accesslist 允许访问的ip地址 2720 * @param 返回结果 2721 */ 2722 function ipaccess($ip, $accesslist) { 2723 return preg_match("/^(".str_replace(array("\r\n", ' '), array('|', ''), preg_quote($accesslist, '/')).")/", $ip); 2724 } 2725 2726 /** 2727 * ip限制访问 2728 * @param $ip 要检查的ip地址 2729 * @param - $accesslist 允许访问的ip地址 2730 * @param 返回结果 2731 */ 2732 function ipbanned($onlineip) { 2733 global $_G; 2734 2735 if($_G['setting']['ipaccess'] && !ipaccess($onlineip, $_G['setting']['ipaccess'])) { 2736 return TRUE; 2737 } 2738 2739 loadcache('ipbanned'); 2740 if(empty($_G['cache']['ipbanned'])) { 2741 return FALSE; 2742 } else { 2743 if($_G['cache']['ipbanned']['expiration'] < TIMESTAMP) { 2744 require_once libfile('function/cache'); 2745 updatecache('ipbanned'); 2746 } 2747 return preg_match("/^(".$_G['cache']['ipbanned']['regexp'].")$/", $onlineip); 2748 } 2749 } 2750 2751 //获得统计数 2752 function getcount($tablename, $condition) { 2753 if(empty($condition)) { 2754 $where = '1'; 2755 } elseif(is_array($condition)) { 2756 $where = DB::implode_field_value($condition, ' AND '); 2757 } else { 2758 $where = $condition; 2759 } 2760 $ret = intval(DB::result_first("SELECT COUNT(*) AS num FROM ".DB::table($tablename)." WHERE $where")); 2761 return $ret; 2762 } 2763 2764 /** 2765 * 系统级消息 2766 */ 2767 function sysmessage($message) { 2768 require libfile('function/sysmessage'); 2769 show_system_message($message); 2770 } 2771 2772 /** 2773 * 论坛权限 2774 * @param $permstr - 权限信息 2775 * @param $groupid - 只判断用户组 2776 * @return 0 无权限 > 0 有权限 2777 */ 2778 function forumperm($permstr, $groupid = 0) { 2779 global $_G; 2780 2781 $groupidarray = array($_G['groupid']); 2782 if($groupid) { 2783 return preg_match("/(^|\t)(".$groupid.")(\t|$)/", $permstr); 2784 } 2785 foreach(explode("\t", $_G['member']['extgroupids']) as $extgroupid) { 2786 if($extgroupid = intval(trim($extgroupid))) { 2787 $groupidarray[] = $extgroupid; 2788 } 2789 } 2790 if($_G['setting']['verify']['enabled']) { 2791 getuserprofile('verify1'); 2792 foreach($_G['setting']['verify'] as $vid => $verify) { 2793 if($verify['available'] && $_G['member']['verify'.$vid] == 1) { 2794 $groupidarray[] = 'v'.$vid; 2795 } 2796 } 2797 } 2798 return preg_match("/(^|\t)(".implode('|', $groupidarray).")(\t|$)/", $permstr); 2799 } 2800 2801 /** 2802 * PHP 兼容性函数 2803 */ 2804 if(!function_exists('file_put_contents')) { 2805 if(!defined('FILE_APPEND')) define('FILE_APPEND', 8); 2806 function file_put_contents($filename, $data, $flag = 0) { 2807 $return = false; 2808 if($fp = @fopen($filename, $flag != FILE_APPEND ? 'w' : 'a')) { 2809 if($flag == LOCK_EX) @flock($fp, LOCK_EX); 2810 $return = fwrite($fp, is_array($data) ? implode('', $data) : $data); 2811 fclose($fp); 2812 } 2813 return $return; 2814 } 2815 } 2816 2817 //检查权限 2818 function checkperm($perm) { 2819 global $_G; 2820 return (empty($_G['group'][$perm])?'':$_G['group'][$perm]); 2821 } 2822 2823 /** 2824 * 时间段设置检测 2825 * @param $periods - 那种时间段 $settings[$periods] $settings['postbanperiods'] $settings['postmodperiods'] 2826 * @param $showmessage - 是否提示信息 2827 * @return 返回检查结果 2828 */ 2829 function periodscheck($periods, $showmessage = 1) { 2830 global $_G; 2831 2832 if(!$_G['group']['disableperiodctrl'] && $_G['setting'][$periods]) { 2833 $now = dgmdate(TIMESTAMP, 'G.i', $_G['setting']['timeoffset']); 2834 foreach(explode("\r\n", str_replace(':', '.', $_G['setting'][$periods])) as $period) { 2835 list($periodbegin, $periodend) = explode('-', $period); 2836 if(($periodbegin > $periodend && ($now >= $periodbegin || $now < $periodend)) || ($periodbegin < $periodend && $now >= $periodbegin && $now < $periodend)) { 2837 $banperiods = str_replace("\r\n", ', ', $_G['setting'][$periods]); 2838 if($showmessage) { 2839 showmessage('period_nopermission', NULL, array('banperiods' => $banperiods), array('login' => 1)); 2840 } else { 2841 return TRUE; 2842 } 2843 } 2844 } 2845 } 2846 return FALSE; 2847 } 2848 2849 //新用户发言 2850 function cknewuser($return=0) { 2851 global $_G; 2852 2853 $result = true; 2854 2855 if(!$_G['uid']) return true; 2856 2857 //不受防灌水限制 2858 if(checkperm('disablepostctrl')) { 2859 return $result; 2860 } 2861 $ckuser = $_G['member']; 2862 2863 //见习时间 2864 if($_G['setting']['newbiespan'] && $_G['timestamp']-$ckuser['regdate']<$_G['setting']['newbiespan']*60) { 2865 if(empty($return)) showmessage('no_privilege_newbiespan', '', array('newbiespan' => $_G['setting']['newbiespan']), array('return' => true)); 2866 $result = false; 2867 } 2868 //需要上传头像 2869 if($_G['setting']['need_avatar'] && empty($ckuser['avatarstatus'])) { 2870 if(empty($return)) showmessage('no_privilege_avatar', '', array(), array('return' => true)); 2871 $result = false; 2872 } 2873 //强制新用户激活邮箱 2874 if($_G['setting']['need_email'] && empty($ckuser['emailstatus'])) { 2875 if(empty($return)) showmessage('no_privilege_email', '', array(), array('return' => true)); 2876 $result = false; 2877 } 2878 //强制新用户好友个数 2879 if($_G['setting']['need_friendnum']) { 2880 space_merge($ckuser, 'count'); 2881 if($ckuser['friends'] < $_G['setting']['need_friendnum']) { 2882 if(empty($return)) showmessage('no_privilege_friendnum', '', array('friendnum' => $_G['setting']['need_friendnum']), array('return' => true)); 2883 $result = false; 2884 } 2885 } 2886 return $result; 2887 } 2888 2889 function manyoulog($logtype, $uids, $action, $fid = '') { 2890 global $_G; 2891 2892 if($_G['setting']['my_app_status'] && $logtype == 'user') { 2893 $action = daddslashes($action); 2894 $values = array(); 2895 $uids = is_array($uids) ? $uids : array($uids); 2896 foreach($uids as $uid) { 2897 $uid = intval($uid); 2898 $values[$uid] = "('$uid', '$action', '".TIMESTAMP."')"; 2899 } 2900 if($values) { 2901 DB::query("REPLACE INTO ".DB::table('common_member_log')." (`uid`, `action`, `dateline`) VALUES ".implode(',', $values)); 2902 } 2903 } 2904 } 2905 2906 /** 2907 * 用户操作日志 2908 * @param int $uid 用户ID 2909 * @param string $action 操作类型 tid=thread pid=post blogid=blog picid=picture doid=doing sid=share aid=article uid_cid/blogid_cid/sid_cid/picid_cid/aid_cid/topicid_cid=comment 2910 * @return bool 2911 */ 2912 function useractionlog($uid, $action) { 2913 $uid = intval($uid); 2914 if(empty($uid) || empty($action)) { 2915 return false; 2916 } 2917 $action = getuseraction($action); 2918 $timestamp = TIMESTAMP; 2919 DB::query("INSERT INTO ".DB::table('common_member_action_log')." (`uid`, `action`, `dateline`) VALUES ('$uid', '$action', '$timestamp')"); 2920 return true; 2921 } 2922 2923 /** 2924 * 得到用户操作的代码或代表字符,参数为数字返回字符串,参数为字符串返回数字 2925 * @param string/int $var 2926 * @return int/string 注意:如果失败返回false,请使用===判断,因为代码0代表tid 2927 */ 2928 function getuseraction($var) { 2929 $value = false; 2930 //操作代码 2931 $ops = array('tid', 'pid', 'blogid', 'picid', 'doid', 'sid', 'aid', 'uid_cid', 'blogid_cid', 'sid_cid', 'picid_cid', 'aid_cid', 'topicid_cid'); 2932 if(is_numeric($var)) { 2933 $value = isset($ops[$var]) ? $ops[$var] : false; 2934 } else { 2935 $value = array_search($var, $ops); 2936 } 2937 return $value; 2938 } 2939 2940 /** 2941 * 获取我的中心中展示的应用 2942 */ 2943 function getuserapp($panel = 0) { 2944 require_once libfile('function/manyou'); 2945 manyou_getuserapp($panel); 2946 return true; 2947 } 2948 2949 /** 2950 * 获取manyou应用本地图标路径 2951 * @param <type> $appid 2952 */ 2953 function getmyappiconpath($appid, $iconstatus=0) { 2954 if($iconstatus > 0) { 2955 return getglobal('setting/attachurl').'./'.'myapp/icon/'.$appid.'.jpg'; 2956 } 2957 return 'http://appicon.manyou.com/icons/'.$appid; 2958 } 2959 2960 //获取超时时间 2961 function getexpiration() { 2962 global $_G; 2963 $date = getdate($_G['timestamp']); 2964 return mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']) + 86400; 2965 } 2966 2967 function return_bytes($val) { 2968 $val = trim($val); 2969 $last = strtolower($val{strlen($val)-1}); 2970 switch($last) { 2971 case 'g': $val *= 1024; 2972 case 'm': $val *= 1024; 2973 case 'k': $val *= 1024; 2974 } 2975 return $val; 2976 } 2977 2978 /** 2979 * 获取文字内的url列表 2980 * 2981 * @param $message 文字 2982 * @return <array> url列表 2983 * 2984 */ 2985 function get_url_list($message) { 2986 $return = array(); 2987 2988 (strpos($message, '[/img]') || strpos($message, '[/flash]')) && $message = preg_replace("/\[img[^\]]*\]\s*([^\[\<\r\n]+?)\s*\[\/img\]|\[flash[^\]]*\]\s*([^\[\<\r\n]+?)\s*\[\/flash\]/is", '', $message); 2989 if(preg_match_all("/((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|thunder|qqdl|synacast){1}:\/\/|www\.)[^\[\]\"']+/i", $message, $urllist)) { 2990 foreach($urllist[0] as $key => $val) { 2991 $val = trim($val); 2992 $return[0][$key] = $val; 2993 if(!preg_match('/^http:\/\//is', $val)) $val = 'http://'.$val; 2994 $tmp = parse_url($val); 2995 $return[1][$key] = $tmp['host']; 2996 if($tmp['port']){ 2997 $return[1][$key] .= ":$tmp[port]"; 2998 } 2999 } 3000 } 3001 3002 return $return; 3003 } 3004 3005 function iswhitelist($host) { 3006 global $_G; 3007 static $iswhitelist = array(); 3008 3009 if(isset($iswhitelist[$host])) { 3010 return $iswhitelist[$host]; 3011 } 3012 $hostlen = strlen($host); 3013 $iswhitelist[$host] = false; 3014 if(is_array($_G['cache']['domainwhitelist'])) foreach($_G['cache']['domainwhitelist'] as $val) { 3015 $domainlen = strlen($val); 3016 if($domainlen > $hostlen) { 3017 continue; 3018 } 3019 if(substr($host, -$domainlen) == $val) { 3020 $iswhitelist[$host] = true; 3021 break; 3022 } 3023 } 3024 if($iswhitelist[$host] == false) { 3025 $iswhitelist[$host] = $host == $_SERVER['HTTP_HOST']; 3026 } 3027 return $iswhitelist[$host]; 3028 } 3029 3030 /** 3031 * 更新页面和模块的关系 3032 * @param string $targettplname 页面名称 3033 * @param array $blocks 模块IDS 3034 */ 3035 function update_template_block($targettplname, $blocks) { 3036 //更新模板中包含的模块(bid) 3037 if(!empty($targettplname)) { 3038 if(empty($blocks)) { 3039 DB::delete('common_template_block', array('targettplname'=>$targettplname)); 3040 } else { 3041 //原所有BIDS 3042 $oldbids = array(); 3043 $query = DB::query('SELECT bid FROM '.DB::table('common_template_block')." WHERE targettplname='$targettplname'"); 3044 while($value = DB::fetch($query)) { 3045 $oldbids[] = $value['bid']; 3046 } 3047 //新增加的BIDS 3048 $newaddbids = array_diff($blocks, $oldbids); 3049 //清空原关联关系 3050 DB::delete('common_template_block', array('targettplname'=>$targettplname)); 3051 //唯一性处理 3052 $blocks = array_unique($blocks); 3053 //保存新的关联关系 3054 $values = array(); 3055 foreach ($blocks as $bid) { 3056 $values[] = "('$targettplname','$bid')"; 3057 } 3058 if (!empty($values)) { 3059 DB::query("INSERT INTO ".DB::table('common_template_block')." (targettplname,bid) VALUES ".implode(',', $values)); 3060 } 3061 //更新模块的权限 3062 if(!empty($newaddbids)) { 3063 require_once libfile('class/blockpermission'); 3064 $tplpermission = & template_permission::instance(); 3065 $tplpermission->add_blocks($targettplname, $newaddbids); 3066 } 3067 } 3068 } 3069 } 3070 3071 if(!function_exists('http_build_query')) { 3072 function http_build_query($data, $numeric_prefix='', $arg_separator='', $prefix='') { 3073 $render = array(); 3074 if (empty($arg_separator)) { 3075 $arg_separator = ini_get('arg_separator.output'); 3076 empty($arg_separator) && $arg_separator = '&'; 3077 } 3078 foreach ((array) $data as $key => $val) { 3079 if (is_array($val) || is_object($val)) { 3080 $_key = empty($prefix) ? "{$key}[%s]" : sprintf($prefix, $key) . "[%s]"; 3081 $_render = http_build_query($val, '', $arg_separator, $_key); 3082 if (!empty($_render)) { 3083 $render[] = $_render; 3084 } 3085 } else { 3086 if (is_numeric($key) && empty($prefix)) { 3087 $render[] = urlencode("{$numeric_prefix}{$key}") . "=" . urlencode($val); 3088 } else { 3089 if (!empty($prefix)) { 3090 $_key = sprintf($prefix, $key); 3091 $render[] = urlencode($_key) . "=" . urlencode($val); 3092 } else { 3093 $render[] = urlencode($key) . "=" . urlencode($val); 3094 } 3095 } 3096 } 3097 } 3098 $render = implode($arg_separator, $render); 3099 if (empty($render)) { 3100 $render = ''; 3101 } 3102 return $render; 3103 } 3104 } 3105 3106 /** 3107 * 获取批定类型的关联连接 3108 * 3109 * @param string $extent 内容所需关联链接范围 article, forum, group, blog 3110 * @return string 有效的关联链接 3111 */ 3112 function getrelatedlink($extent) { 3113 global $_G; 3114 loadcache('relatedlink'); 3115 $allextent = array('article' => 0, 'forum' => 1, 'group' => 2, 'blog' => 3); 3116 $links = array(); 3117 if($_G['cache']['relatedlink'] && isset($allextent[$extent])) { 3118 foreach($_G['cache']['relatedlink'] as $link) { 3119 $link['extent'] = sprintf('%04b', $link['extent']); 3120 if($link['extent'][$allextent[$extent]] && $link['name'] && $link['url']) { 3121 $links[] = daddslashes($link); 3122 } 3123 } 3124 } 3125 return $links; 3126 } 3127 3128 /** 3129 * 通过 AID 获取附件表名 3130 * @param <int> $aid 3131 */ 3132 function getattachtablebyaid($aid) { 3133 $tableid = DB::result_first("SELECT tableid FROM ".DB::table('forum_attachment')." WHERE aid='$aid'"); 3134 return 'forum_attachment_'.($tableid >= 0 && $tableid < 10 ? intval($tableid) : 'unused'); 3135 } 3136 3137 /** 3138 * 返回指定 TID 所对应的附件表编号 3139 * @param <int> $tid 3140 */ 3141 function getattachtableid($tid) { 3142 $tid = (string)$tid; 3143 return intval($tid{strlen($tid)-1}); 3144 } 3145 3146 /** 3147 * 通过 TID 获取附件表名 3148 * @param <int> $tid 3149 */ 3150 function getattachtablebytid($tid) { 3151 return 'forum_attachment_'.getattachtableid($tid); 3152 } 3153 3154 /** 3155 * 通过 PID 获取附件表名 3156 * @param <int> $pid 3157 */ 3158 function getattachtablebypid($pid) { 3159 $tableid = DB::result_first("SELECT tableid FROM ".DB::table('forum_attachment')." WHERE pid='$pid' LIMIT 1"); 3160 return 'forum_attachment_'.($tableid >= 0 && $tableid < 10 ? intval($tableid) : 'unused'); 3161 } 3162 3163 /** 3164 * 添加一个新的附件索引记录,并返回新附件 ID 3165 * @param <int> $uid 3166 */ 3167 function getattachnewaid($uid = 0) { 3168 global $_G; 3169 $uid = !$uid ? $_G['uid'] : $uid; 3170 return DB::insert('forum_attachment', array('tid' => 0, 'pid' => 0, 'uid' => $uid, 'tableid' => 127), true); 3171 } 3172 3173 /** 3174 * 获取 SEO设置 3175 * @param string $page 调用哪个页面的 3176 * @param array $data 可替换数据 3177 * @return array('seotitle', 'seodescription', 'seokeywords') 3178 */ 3179 function get_seosetting($page, $data = array(), $defset = array()) { 3180 global $_G; 3181 $searchs = array('{bbname}'); 3182 $replaces = array($_G['setting']['bbname']); 3183 3184 $seotitle = $seodescription = $seokeywords = ''; 3185 $titletext = $defset['seotitle'] ? $defset['seotitle'] : $_G['setting']['seotitle'][$page]; 3186 $descriptiontext = $defset['seodescription'] ? $defset['seodescription'] : $_G['setting']['seodescription'][$page]; 3187 $keywordstext = $defset['seokeywords'] ? $defset['seokeywords'] : $_G['setting']['seokeywords'][$page]; 3188 preg_match_all("/\{([a-z0-9_-]+?)\}/", $titletext.$descriptiontext.$keywordstext, $pageparams); 3189 if($pageparams) { 3190 foreach($pageparams[1] as $var) { 3191 $searchs[] = '{'.$var.'}'; 3192 //处理分页,分页数大于1时显示 3193 if($var == 'page') { 3194 $data['page'] = $data['page'] > 1 ? lang('core', 'page', array('page' => $data['page'])) : ''; 3195 } 3196 $replaces[] = $data[$var] ? strip_tags($data[$var]) : ''; 3197 } 3198 if($titletext) { 3199 $seotitle = strreplace_strip_split($searchs, $replaces, $titletext); 3200 } 3201 if($descriptiontext && (CURSCRIPT == 'forum' || IS_ROBOT || $_G['adminid'] == 1)) { 3202 $seodescription = strreplace_strip_split($searchs, $replaces, $descriptiontext); 3203 } 3204 if($keywordstext && (CURSCRIPT == 'forum' || IS_ROBOT || $_G['adminid'] == 1)) { 3205 $seokeywords = strreplace_strip_split($searchs, $replaces, $keywordstext); 3206 } 3207 } 3208 return array($seotitle, $seodescription, $seokeywords); 3209 } 3210 3211 3212 /** 3213 * 需处理连续分隔符的str_replace() 3214 * @param array $searchs 被替换的数组 3215 * @param array $replaces 用于替换的数组 3216 * @param string $str 目标字符串 3217 */ 3218 function strreplace_strip_split($searchs, $replaces, $str) { 3219 $searchspace = array('((\s*\-\s*)+)', '((\s*\,\s*)+)', '((\s*\|\s*)+)', '((\s*\t\s*)+)', '((\s*_\s*)+)'); 3220 $replacespace = array('-', ',', '|', ' ', '_'); 3221 return trim(preg_replace($searchspace, $replacespace, str_replace($searchs, $replaces, $str)), ' ,-|_'); 3222 } 3223 3224 /** 3225 * 返回带第几页的title 3226 * @global $_G 3227 * @param string $navtitle 源标题 3228 * @param int $page 页码 3229 * @return string 3230 */ 3231 function get_title_page($navtitle, $page){ 3232 if($page > 1) { 3233 $navtitle .= ' - '.lang('core', 'page', array('page' => $page)); 3234 } 3235 return $navtitle; 3236 } 3237 /** 3238 * 3239 * 生成缩略图文件名 3240 * @param String $fileStr: 原文件名,允许附带路径 3241 * @param String $extend: 新文件名后缀 3242 * @param Boolean $holdOldExt: 是否保留原扩展名 3243 * @return 返加新的后缀文件名 3244 */ 3245 function getimgthumbname($fileStr, $extend='.thumb.jpg', $holdOldExt=true) { 3246 if(empty($fileStr)) { 3247 return ''; 3248 } 3249 //去掉原扩展名 3250 if(!$holdOldExt) { 3251 $fileStr = substr($fileStr, 0, strrpos($fileStr, '.')); 3252 } 3253 $extend = strstr($extend, '.') ? $extend : '.'.$extend; 3254 return $fileStr.$extend; 3255 } 3256 3257 /** 3258 * 更新数据的审核状态 3259 * @param <string> $idtype 数据类型 tid=thread pid=post blogid=blog picid=picture doid=doing sid=share aid=article uid_cid/blogid_cid/sid_cid/picid_cid/aid_cid/topicid_cid=comment 3260 * @param <array/int> $ids ID 数组、ID 值 3261 * @param <int> $status 状态 0=加入审核(默认) 1=忽略审核 2=审核通过 3262 */ 3263 function updatemoderate($idtype, $ids, $status = 0) { 3264 global $_G; 3265 $ids = is_array($ids) ? $ids : array($ids); 3266 if(!$ids) { 3267 return; 3268 } 3269 if(!$status) { 3270 foreach($ids as $id) { 3271 DB::insert('common_moderate', array('id' => $id, 'idtype' => $idtype, 'status' => 0, 'dateline' => $_G['timestamp']), false, true); 3272 } 3273 } elseif($status == 1) { 3274 DB::update('common_moderate', array('status' => 1), "id IN (".dimplode($ids).") AND idtype='$idtype'"); 3275 } elseif($status == 2) { 3276 DB::delete('common_moderate', "id IN (".dimplode($ids).") AND idtype='$idtype'"); 3277 } 3278 } 3279 3280 /** 3281 * 显示漫游应用公告 3282 */ 3283 function userappprompt() { 3284 global $_G; 3285 3286 if($_G['setting']['my_app_status'] && $_G['setting']['my_openappprompt'] && empty($_G['cookie']['userappprompt'])) { 3287 $sid = $_G['setting']['my_siteid']; 3288 $ts = $_G['timestamp']; 3289 $key = md5($sid.$ts.$_G['setting']['my_sitekey']); 3290 $uchId = $_G['uid'] ? $_G['uid'] : 0; 3291 echo '<script type="text/javascript" src="http://notice.uchome.manyou.com/notice/userNotice?sId='.$sid.'&ts='.$ts.'&key='.$key.'&uchId='.$uchId.'" charset="UTF-8"></script>'; 3292 } 3293 } 3294 3295 3296 function makeSearchSignUrl() { 3297 global $_G; 3298 3299 $url = ''; 3300 $params = array(); 3301 $my_search_data = unserialize($_G['setting']['my_search_data']); 3302 $my_siteid = $_G['setting']['my_siteid']; 3303 $my_sitekey= $_G['setting']['my_sitekey']; 3304 require_once libfile('function/cloud'); 3305 if($my_search_data['status'] && getcloudappstatus('search') && $my_siteid) { 3306 $my_extgroupids = array(); 3307 $_extgroupids = explode("\t", $_G['member']['extgroupids']); 3308 foreach($_extgroupids as $v) { 3309 if ($v) { 3310 $my_extgroupids[] = $v; 3311 } 3312 } 3313 $my_extgroupids_str = implode(',', $my_extgroupids); 3314 $params = array('sId' => $my_siteid, 3315 'ts' => time(), 3316 'cuId' => $_G['uid'], 3317 'cuName' => $_G['username'], 3318 'gId' => intval($_G['groupid']), 3319 'agId' => intval($_G['adminid']), 3320 'egIds' => $my_extgroupids_str, 3321 // 'fIds' => $params['fIds'], 3322 'fmSign' => '', 3323 ); 3324 $groupIds = array($params['gId']); 3325 if ($params['agId']) { 3326 $groupIds[] = $params['agId']; 3327 } 3328 if ($my_extgroupids) { 3329 $groupIds = array_merge($groupIds, $my_extgroupids); 3330 } 3331 3332 $groupIds = array_unique($groupIds); 3333 foreach($groupIds as $v) { 3334 $key = 'ugSign' . $v; 3335 $params[$key] = ''; 3336 } 3337 $params['sign'] = md5(implode('|', $params) . '|' . $my_sitekey); 3338 3339 $params['charset'] = $_G['charset']; 3340 $mySearchData = unserialize($_G['setting']['my_search_data']); 3341 if ($mySearchData['domain']) { 3342 $domain = $mySearchData['domain']; 3343 } else { 3344 $domain = 'search.discuz.qq.com'; 3345 } 3346 $url = 'http://' . $domain . '/f/discuz'; 3347 } 3348 return !empty($url) ? array($url, $params) : array(); 3349 } 3350 ?>