----------------------------------------------------------------------------------------------------------------------------
代码: include/global.func.php ~400
function forumperm($permstr) { global $groupid, $extgroupids; $groupidarray = array($groupid); foreach(explode("\t", $extgroupids) as $extgroupid) { if($extgroupid = intval(trim($extgroupid))) { <------赋值还是判断? 太容易混淆人了 $groupidarray[] = $extgroupid; } } }点评: 赋值还是判断? 太容易混淆人了
foreach(explode("\t", $extgroupids) as $extgroupid) { $extgroupid = intval($extgroupid); $extgroupid > 0 && $groupidarray[] = $extgroupid; }
include/newreply.inc.php=240 $parseurloff = !empty($parseurloff); include/newthreads.inc.php~375 $parseurloff = !empty($parseurloff);
点评: 会导致变量为空字符串非int类型。因为mysql比较宽松对SQL标准支持不佳,对于字段类型输入值校检不严格:如果是int类型字段,你输入的是空字符那么会自动给你转换成0。但这对以后的移植不利,对于个人以后在技术上的发展未必好。类似的是mysql LIMIT的写法,既支持LIMIT {[offset,] row_count}格式也支持LIMIT {row_count OFFSET offset}标准,但大部分人就只知道使用前者而不知道后者标准格式。
FIX:
$parseurloff = empty($parseurloff) ? 0 : 1;
Undefined index: allowadminlog ---- Modified : ucs/view/default/admin_admin.htm Modified : ucs/view/default/admin_feed.htm Modified : ucs/view/default/admin_mail.htm Modified : ucs/view/default/admin_note.htm <li><input type="checkbox" name="allowadminlog" value="1" class="checkbox" {if $admin[allowadminlog]} checked="checked" {/if}/>{lang admin_allow_log}</li>点评: PHP弱类型语言,变量不预声明即可使用,方便。但对未定义变量进行操作时会导致PHP抛出一个Notice,这在PHP中不算啥错误,但会给DZ调试带来一些意想不到的问题:DZ采用XML作为ajax交流格式,不知道是js代码编写问题还是XML本身问题,如果php.ini中打开display_error开关,当前台页面调用ajax操作遇上PHP抛出日志信息时前台将会出错,firebug中往往不是提示XML错误而是显示common.js某行错误(比如 Error:s is NULL, $ is not exists之类的)。不熟悉的还以为是JS代码有问题,其实根源在于PHP代码不严谨,而XML格式复杂严格。个人觉得网站ajax使用JSON比XML更佳,无论是后台程序处理输出代码还是前台JS解析数据。对于PHP数组,一条echo json_encode($array)即可快捷返回JSON格式信息给前台;而前台JS一条eval "{data}"命令即可立刻解析成JS变量对象(处于安全考虑,现在不推荐使用eval来解析,如果使用jQuery那么可以使用$.ajax()的dataType:json或者直接$.getJSON()来直接获得数组变量)。
FIX: 关闭php.ini中display_error选项。或者修改DZ代码使用isset()或者!empty()判断变量,比如
{if isset($admin[allowadminlog]) && $admin[allowadminlog]} 或者 {if !empty($admin[allowadminlog])}
----------------------------------------------------------------------------------------------------------------------------
类型: 未定义变量$pmstatus = uc_pm_checknew($discuz_uid, 4); $filter = !empty($filter) && in_array($filter, array('newpm', 'privatepm', 'announcepm')) ? $filter : ($pmstatus['newpm'] ? 'newpm' : 'privatepm');点评: 未对返回值$pmstatus['newpm']有效性进行判断
----------------------------------------------------------------------------------------------------------------------------
类型: 未定义变量foreach($ucdata['data'] as $pm) { .... }点评: 未对 $ucdata变量'data'键有效做判断就直接开始循环,相当于对一个可能不存在的变量进行访问并迭代。问题出在line49调用uc_pm_list()对$ucdata赋值,而ucc/control/pm.php: onls() 函数返回值$result未初始化'data'键名。
$styleid = empty($styleidnew) ? $styleid : $styleidnew;点评: 这位兄弟是不是求加薪不成功,没有新生活导致见new就失望于是也不给变量new生活。
----------------------------------------------------------------------------------------------------------------------------
类型: 变量使用
updateprompt()函数中$db->query("UPDATE {$tablepre}members SET prompt=prompt^1 WHERE uid='$discuz_uid' AND prompt=prompt|1", 'UNBUFFERED');点评: 函数并未global声明$discuz_uid变量
----------------------------------------------------------------------------------------------------------------------------
类型: 变量使用
$db->query("INSERT INTO {$tablepre}medallog (uid, medalid, type, dateline, expiration, status) VALUES ('$uid', '".$modmedal[medalid]."', '0', '$timestamp', '".$modmedal['expiration']."', '$medalstatus')");点评: $modmedal[medalid]缺少单引号。在双引号中使用数组变量DZ都采用不带单引号的方式,比如 "... $modmedal[medalid] "而不使用繁琐但更安全的大括号方式 "... {$modmedal['medalid']} ",很少使用例子中拼接字符串方式。这次难道用一次拼接,结果习惯的力量那么大还是用了不带单引号的访问方式。也许,也许小哥加班熬夜,眼花,没看到前后的两个小点还以为是在双引号的范围内。
FIX: 把变量键名加上单引号 $modmedal['medalid']
$db->query("UPDATE {$tablepre}sessions SET uid='$discuz_uid', username='$discuz_user', groupid='$groupid', styleid='$styleid', invisible='$invisible', action='$discuz_action', lastactivity='$timestamp', lastolupdate='$lastolupdate', seccode='$seccode', fid='$fid', tid='$tid' $pageviewsadd WHERE sid='$sid'");点评: 更新状态时seccode值有时会出现验证码字符串而非int。写入失败,后台时常有此日志。问题出在那儿一直没找到,算一个悬疑历史问题坑
$db->query("UPDATE {$tablepre}members set uid=uid $updatesql WHERE $conditions", 'UNBUFFTERED');点评: 俺自从用上gVim之后写代码彻底抛弃庞大臃肿的zend statio了,emeditor用得也很少。感觉vim用熟悉之后实在太舒服,不但提高速度并且更加高效,难怪对于VIM和Emacs,一条经典评价“VIM是编辑器之神,Emacs是神之编辑器”。对于“伪装成文本编辑器而实际干的是操作系统活的Emacs”,我不想买脚踏板所以还是安心用VIM吧。经常出现用j下移鼠标时文字排版大幅度变化或者进入莫名其妙的Ex模式一时退不出去,后来才发现是大写锁定了————以前输入大写习惯是使用Caps Locks锁定大写然后再输入字符,不过有时候忘记解除大写锁定有时候解除操作却按到大写上的帽子上……哦是Tab上,于是j变成了<S-j>删除段尾回车让下一行并入当前行。所以后来我就改变习惯,除非特定情况,大写字符使用Shift组合键来输入。但这又产生一个新问题,因为输入时手掌形态改变,肌肉还没习惯新的活动范围所以以前顺手的敲击活动多少带点别扭,结果就是有些长字符串输入错误。写代码的这位兄弟估计没弹过钢琴,一激情下蹦哒出一个不和谐音符。不过还好没严重危害。
修改DZ时我使用TC进行了全文搜索替换,但后来又见着UNBUFFERED这位老哥。心中还奇怪难道TC没搜索到么,仔细一看,原来中间带了个套~
FIX: UNBUFFTERED 修改为 UNBUFFERED
----------------------------------------------------------------------------------------------------------------------------
$db->query("UPDATE {$tablepre}threads SET .... rate='".intval(@($fpost['rate'] / abs($fpost['rate'])))."', moderated='1' WHERE tid='$newtid'");代码: topicadmin.php~240
@$firstpost['rate'] = $firstpost['rate'] / abs($firstpost['rate']);代码: space.php 95
@$percent = round($member['posts'] * 100 / $db->result_first("SELECT COUNT(*) FROM {$tablepre}posts"), 2);代码: stats.php~260
$pageviewavg = sprintf ("%01.2f", ($stats_total['visitors'] ? $stats_total['hits'] / $stats_total['visitors'] : 0)); !$post && $post = 1; $activeindex = round(($membersaddavg / $members + $postsaddavg / $posts) * 1500 + $threadreplyavg * 10 + $mempostavg * 1 + $mempostpercent / 10 + $pageviewavg);代码: stats.php 多处
$avgmodactioncount = @($totalmodactioncount / count($members)); @$width = intval(370 * $count / $max); @$percent = sprintf ("%01.1f", 100 * $count / $sum); $membersaddavg = round($members / $runtime);代码: admin/forums.inc.php~640
$forum['autoclose'] = $forum['autoclose'] / abs($forum['autoclose']);代码: stats.php~550
foreach($extendedcredit as $i => $members) { @$width = intval(370 * $members['credits'] / $max); $width += 2;代码: stats.php~750:
'avgoffdays' => @($totaloffdays / count($members)), 'avgthismonthposts' => @($totalthismonthposts / count($members)), 'avgtotalol' => @($totalol / count($members)), 'avgthismonthol' => @($totalthismonthol / count($members)), 'avgmodactions' => @($totalmodactions / count($members)), 'avgthismonthposts' => @($totalthismonthposts / count($members)), 'avgtotalol' => @($totalol / count($members)), 'avgthismonthol' => @($totalthismonthol / count($members)), 'avgmodactions' => @($totalmodactions / count($members)),
$threadrate = @intval(@($post['rate'] + $rate) / abs($post['rate'] + $rate));点评: 避免除零错误是学习编程时的基本概念,没想到在DZ中还能挖出这么多来。某些问题除零错误是在建站初始无对应数据时发生,待正常运作之后就不会发生。而多数将伴随你网站终身,不断充实你的error-log文件~ 如果说某位程序大猿数学不好不知道除零错误还可以理解,但恶劣的是有些人明知道这个问题却使用@来抑制错误,这就属于有意找抽的……
//$sql = "SELECT * FROM {$tablepre}feeds WHERE $where ORDER BY feed_id DESC LIMIT $start_limit, $conf[num]"; // DZ自己注释掉的 $sql = "SELECT * FROM {$tablepre}feeds WHERE $where ORDER BY feedid DESC LIMIT $start_limit, $conf[num]";点评: dz.cdb_feeds这个表的主键是feed_id, ucenter.feeds表的主键是feedid.你们程序员通过注释把feed_id改成feedid,但是dz数据表没升级啊。难道我补丁没下全?这个坑不影响结果集,但对feed读取时的排序有影响(使用在ORDER BY中)
FIX: 修改feed_id 为 feedid
if($db->result_first("SELECT COUNT(*) FROM {$tablepre}favoritethreads WHERE tid='$tid' AND uid='$discuz_uid'")) { showmessage('favoritethreads_exists', dreferer()); } $timestamp = time(); $attention_exists = $db->result_first("SELECT COUNT(*) FROM {$tablepre}favoritethreads WHERE tid='$tid' AND uid='$discuz_uid'"); // <===点评: 前面查询如果存在结果(即有收藏)就已经退出执行流程并提示用户 'favoritethreads_exists',下面干嘛又执行一次呢,难道真会再次运行?
---------------------------------------------------------------------------------------------------------------------------
类型: 流程错误$session = $this->_loadsession($uid, $ip, $GLOBALS['admincp']['checkip']); $this->errorcount = $session['errorcount']; // <---- $this->storage = $session['storage']; if(empty($session)) { // <------ $this->creatsession($uid, $adminid, $ip); $cpaccess = 1; } elseif($session['errorcount'] == -1) {点评: 对$this->errorcount赋值先于 if (empty($session)) 判断,会导致 update()方法SQL错误($this->errorcount非数字)
FIX: 先判断再赋值
} elseif($session['errorcount'] == -1) { $this->errorcount = $session['errorcount']; // must before exec $this->update() !! $this->storage = $session['storage']; $this->update(); $cpaccess = 3; } elseif($session['errorcount'] <= 3) {
if($post['first']) { foreach(array('threads', 'threadsmod', ... 'attachments', ...) as $value) { $db->query("DELETE FROM {$tablepre}$value WHERE tid='$post[tid]'", 'UNBUFFERED'); } $query = $db->query("SELECT uid, attachment, dateline, thumb, remote FROM {$tablepre}attachments WHERE tid='$post[tid]'"); while($attach = $db->fetch_array($query)) { dunlink($attach['attachment'], $attach['thumb'], $attach['remote']); }点评: attachments的记录都被删除了还能再取出记录去unlinke么?虽然再次操作取不出记录但不代表数据库没工作啊,它还是会傻傻地去查询索引的。
for($i = 0; $i < count($forums); $i++) { // <----- if($forums[$i]['type'] == 'group') { echo showforum($i, 'group'); for($j = 0; $j < count($forums); $j++) { // <----- if($forums[$j]['fup'] == $forums[$i]['fid'] && $forums[$j]['type'] == 'forum') { .... } } echo showforum($i, '', 'lastboard'); } elseif(!$forums[$i]['fup'] && $forums[$i]['type'] == 'forum') { echo showforum($i); for($j = 0; $j < count($forums); $j++) { // <----- .... } echo showforum($i, '', 'lastchildboard'); } }点评: 内外两层for循环使用的count($forums)条件判断可以在循环开始前就计算出个结果赋值给一个变量然后以后就访问该变量。可能DZ认为一个论坛版块不会太多所以吃多点也不会噎着~
if(isset($statvars['thismonth'])) { $thismonth = unserialize($statvars['thismonth']); } else { $dateline = strtotime(gmdate('Y-n-01', $timestamp)); $query = $db->query("SELECT o.uid, m.username, o.thismonth AS time ..... while($online = $db->fetch_array($query)) { $online['time'] = round($online['time'] / 60, 2); // <------ $thismonth[] = $online; } $newstatvars[] = "'onlines', 'thismonth', '".addslashes(serialize($thismonth))."'"; }点评: 虽然 round($online['time'] / 60, 2) 限定了小数位数2位,但超过1位小数的数字在serialize()时将会变成近似值!得到类似的结果 a:2:{i:0;a:3:{s:3:"uid";i:1;s:8:"username";s:3:"root";s:4:"time";d:36.8299999999999982946974341757595539093017578125;}i:1;
$query = $db->query("SELECT COUNT(*) FROM {$tablepre}paymentlog WHERE uid='$discuz_uid'"); $totalamount = $db->result($query, 1);点评: 第二个参数1导致不会有结果,前面的查询条件只可能返回一行记录,而不会有第二行所以指定1是错误的。不是说程序猿数数都从0开始;日子9号过了是A号;向程序员朋友借钱1K他会给你1024块。难道这也是临时工代码……
$db->query("DELETE FROM {$tablepre}rewardlog WHERE tid IN ($tidsdelete)", 'UNBUFFERED');代码: modcp/threads.inc.php 232,233
$db->query("DELETE FROM {$tablepre}threadsmod WHERE tid IN ($tidsdelete)", 'UNBUFFERED');点评: 当第一次删除之后执行第二次时虽然不会有实际删除操作但一样要做索引查找以匹配记录给数据库带来多余的负担。难道DZ程序员以前玩过linux,关机重启之前要输入sync && sync重复来确保缓冲写入磁盘。mysql好像没这个特性也不健忘吧,它可是数据库耶,不需要你一个命令重复n次才会磨磨蹭蹭去做的呀。
define('UC_API', strtolower(($_SERVER['HTTPS'] == 'on' ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST'].substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/'))));点评: 未检测 $_SERVER['HTTPS']变量存在就直接使用,$_SERVER['PHP_SELF']在nginx下可能为空。现在Apache虽然依旧是webserver份额老大,但linux已经不是它的天下,nginx异军突起,增长迅速。top1000网站中已经占据25%的份额超过了IIS成了第二。Nginx+PHP-FPM(fastcgi)的搭配已经被越来越多的网站采用。并且nginx的配置文件简洁,好比程序代码,易读性可配置性要比httpd.conf好不少。不过nginx对HTTP1.1标准支持不完整,导致PHP_INFO/PHP_SELF变量可能为空。鉴于DZ7.2代码比较老,Nginx又很新,康盛也懒得为此打补丁吧。
define('UC_API', (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http'). '://'. $_SERVER['HTTP_HOST']. ($_SERVER['PHP_SELF'] ? substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/')) : substr($_SERVER['SCRIPT_NAME'], 0, strrpos($_SERVER['SCRIPT_NAME'], '/'))) );
$anew['perm'] = $allowsetattachperm ? $anew['perm'] : 0;点评: $anew数组中并没有 'perm'这个键名.下面SQL插入时也未使用此键名变量!难道是个彩蛋?可怎么调出来呢,↑↑↓↓←→←→AB没效果耶~
----------------------------------------------------------------------------------------------------------------------------
类型: 变量使用$anew['perm'] = $allowsetattachperm ? $anew['perm'] : 0;代码: include/post.func.php=472
$db->query("UPDATE {$tablepre}attachments SET readperm='$anew[readperm]',点评: 未做键名检查————发帖或修改时如果用户删除了附件读取权限值(默认0)为空则页面表单中 name="attachnew[aid][readperm]"这个input对象不会提交,后台接收到的POST变量无此键名。SQL执行无效。
FIX:
$anew['readperm'] = $allowsetattachperm && isset($anew['readperm']) ? intval($anew['readperm']) : 0;
----------------------------------------------------------------------------------------------------------------------------
类型: 变量使用$anew['perm'] = $allowsetattachperm ? $anew['perm'] : 0;代码: include/post.func.php=472
$attach['perm'] = $allowsetattachperm ? intval($attachperm[$key]) : 0;点评: 同上
$pmstatus = uc_pm_checknew($discuz_uid, 4); $filter = !empty($filter) && in_array($filter, array('newpm', 'privatepm', 'announcepm')) ? $filter : ($pmstatus['newpm'] ? 'newpm' : 'privatepm');点评: 未对返回值$pmstatus['newpm']有效性进行判断
----------------------------------------------------------------------------------------------------------------------------
类型: 变量使用foreach($ucdata['data'] as $pm) { .... }点评: 未对 $ucdata变量'data'键有效做判断就直接开始循环,相当于对一个可能不存在的变量进行访问并迭代。问题出在line49调用uc_pm_list()对$ucdata赋值,而ucc/control/pm.php: onls() 函数返回值$result未初始化'data'键名。
$datalist[$data['tid']]['subject'] = isset($data['subject']) ? str_replace('\\\'', ''', addslashes($data['subject'])) : NULL;FIXTO:
$datalist[$data['tid']]['subject'] = isset($data['subject']) ? htmlspecialchars(htmlspecialchars_decode($data['subject']), ENT_QUOTES) : NULL;然后修改global.func.php, ucs/mode/base.php, ucclient/mode/base.php的cutstr()函数:
//$string = str_replace(array('&', '"', '<', '>', '''), array('&', '"', '<', '>', '\''), $string); $string = htmlspecialchars_decode($string, ENT_QUOTES); .... //$strcut = str_replace(array('&', '"', '<', '>', '\''), array('&', '"', '<', '>', '''), $strcut); $strcut = htmlspecialchars($strcut, ENT_QUOTES);
if(!$bbcodeoff && $allowbbcode) {// line126 .... } // line201 修改成 if($allowbbcode) { // line126 if (!$bbcodeoff) { ..... } // 添加开始 elseif ($bbcodeoff && substr($message, 0, 5) === '[i=s]') { // allow parse '[i=s]last modified by [/i]' even if bbcodeoff $message = preg_replace('/^\[i=s\](.*)\[\/i\]/', '<i class="pstatus">\\1</i>', $message ); } //添加结束 } // line201+n
$db->query("UPDATE {$tablepre}posts SET first='1', subject='$subject' WHERE fid='$waiting_fid' AND pid='".$splitauthors[0]['pid']."'" );点评: first='1'只设置了一次,如果分割主题时选择包含了1楼那么原主题内变成1楼的帖子的first依然为0. 本来在不支持事务的MyISAM引擎上做分隔主题这种操作就具有一定危险性,不过DZ更直接增加了这个这个机率。提醒你分割主题时不要把顶楼分割出去哟,不然剩下变成1楼的帖子将会成为孤儿。多来几次你就会明确记住这个准则了,也不会因为数据库偶尔非原子性操作带来的随机故障而烦恼。这多么简单啊。呵呵
$db->query("UPDATE {$tablepre}posts SET subject='".addslashes($thread['subject'])."' WHERE pid='$fpost[pid]'");修改为
$db->query("UPDATE {$tablepre}posts SET first=1, subject='".addslashes($thread['subject'])."' WHERE pid='$fpost[pid]'");
$forum = $db->fetch_first("SELECT t.tid, t.closed,".(defined('SQL_ADD_THREAD') ? SQL_ADD_THREAD : '')." f.*, ff.* $accessadd1 $modadd1, f.fid AS fid FROM {$tablepre}threads t .... $tid = $forum['tid'];点评: 如果查询结果空$forum将会false,不做判断而直接赋值给$tid会出错,否则就可能要继续执行到后继的viewthreads.php中的判断,浪费系统资源。另外viewthreads.php 也未对$tid判断即以此为条件直接查询,徒增DB负担(MySQL会有 ‘Impossible WHERE noticed after reading const tables’ )
----------------------------------------------------------------------------------------------------------------------------
类型: 未知
foreach((array)$this->apps as $appid => $app) { $appid = $app['appid']; <---------?? if($appid == intval($appid)) { if($appids && !in_array($appid, $appids)) { $appadd[] = 'app'.$appid."='1'"; } else { $varadd[] = "('noteexists{$appid}', '1')"; } } }点评: 一直没研究明白这个赋值要表达什么意思。难道这位当时正在韩大嘴语录,看到“瞄的是A,想的是B,解说的是C,观众以为是D,其实指的是E”这一段,顿悟,遂看到是代码,想的是妹妹,说的是工资,同事以为是八卦,领导以为是抽风~
foreach((array)$this->apps as $appid => $app) { if(intval($appid) == $app['appid']) { // 帮你精简一行代码 if($appids && !in_array($appid, $appids)) { $appadd[] = 'app'.$appid."='1'"; } else { $varadd[] = "('noteexists{$appid}', '1')"; } } }
-------------------------------------------------------------------------------------------------------------------------
类型: 代码错误
坑爹指数: ★★
代码: include/request.func.php=372
case 'hourposts';
点评: 这个芝麻坑真难发现啊
FIX:
case 'hourposts':
-------------------------------------------------------------------------------------------------------------------------
类型: 安全漏洞
坑爹指数: ★★★
代码: include/newreply.inc.php~381
if($modnewreplies) { $db->query("UPDATE {$tablepre}forums SET todayposts=todayposts+1 WHERE fid='$fid'", 'UNBUFFERED'); showmessage('post_reply_mod_succeed', "forumdisplay.php?fid=$fid"); } else {
代码: include/newthread.inc.php~440
if($modnewthreads) { $db->query("UPDATE {$tablepre}forums SET todayposts=todayposts+1 WHERE fid='$fid'", 'UNBUFFERED' ); ... } else {
点评: 如果此帖发布需要审核,那么这段代码将会造成一个漏洞:此用户就可以发帖而不受发帖间隔时间的限制!如果“会员每小时发帖数限制”也无限制那么虽然帖子不会直接显示出来但将会造成数据库增大给后台管理造成麻烦。
FIX: 在showmessage()之前更新用户最近发帖时间戳
$db->exec("UPDATE {$tablepre}members SET lastpost='$timestamp' WHERE uid='$discuz_uid'", 'UNBUFFERED');
-------------------------------------------------------------------------------------------------------------------------
类型: 代码错误
坑爹指数: ★
代码: admin/db.inc.php=82
showtablerow('', '', '<input class="checkbox" name="chkall" onclick="checkAll(\'prefix\', this.form, \'customtables\', \'chkall\', true)" checked="checked" type="checkbox" id="chkalltables" /><label for="chkalltables"> '.lang('db_export_custom_select_all').' - '.lang('db_export_discuz_table')).'</label>';
点评: 老眼昏花括弧没包好哟
FIX:
showtablerow('', '', '<input class="checkbox" name="chkall" onclick="checkAll(\'prefix\', this.form, \'customtables\', \'chkall\', true)" checked="checked" type="checkbox" id="chkalltables" /><label for="chkalltables"> '.lang('db_export_custom_select_all').' - '.lang('db_export_discuz_table').'</label>');
本来计划单独开一PHP优化篇。后来发现下面坑爹代码多数会影响性能(PHP以及数据库执行),修复了bug即优化。故合并为一篇。
补充个优化PHP的:
如果你的服务器http server支持Gzip/deflate压缩,那么就使用http serer提供的功能,并到后台,全局-优化设置-服务器优化把“页面 Gzip 压缩”选项设定为否。
如果设定“是”,那么将使用DZ提供的一个gzip PHP插件来实现压缩页面。缺点是耗费PHP脚本执行时间,对于nginx+php-fpm模式运行更容易出现502错误。
转载请保留链接 http://my.oschina.net/u/126398/blog/38873