。。。javascript
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 * 一、模板文件 686 * 二、模板類型,如:diy模板和普通模板,diy模板位於data/diy,普通模板位於 template/default/下 687 * 三、生成的tpl模板文件的存放位置 688 * 四、是否返回模板文件的路徑,0-返回編譯後的php文件 689 * 五、原始的模板文件 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 = 二、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 ?>