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

。。。

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

 

posted on 2017-03-22 11:30  dudumao  阅读(4418)  评论(0编辑  收藏  举报

导航

阿里云