DiscuzX /source/function/function_core.php通用核心函數庫文件分析

。。。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 ?>
相關文章
相關標籤/搜索