----------------------------------------------------------------------------------------------------------------------------php
代碼: include/global.func.php ~400html
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}標準,但大部分人就只知道使用前者而不知道後者標準格式。 mysql
FIX: linux
$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()判斷變量,好比 nginx
{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']有效性進行判斷
----------------------------------------------------------------------------------------------------------------------------web
類型: 未定義變量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生活。
----------------------------------------------------------------------------------------------------------------------------ajax
類型: 變量使用
updateprompt()函數中$db->query("UPDATE {$tablepre}members SET prompt=prompt^1 WHERE uid='$discuz_uid' AND prompt=prompt|1", 'UNBUFFERED');點評: 函數並未global聲明$discuz_uid變量
----------------------------------------------------------------------------------------------------------------------------sql
類型: 變量使用
$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']shell
$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錯誤。