tt的trackback spam嚴重及改善方法

最近因為 tt 的 trackback spam 發生的愈來愈嚴重了, 雖然有 eolin 的 antispam 在背後努力著, 但是還是進來了一堆 trackback 的 spam.

最近發生的大多是這個網址來的: 9hxofreeporn.info 還有 9hwifreeporn.info , 不知他是如何躲過 eolin 的 antispam plugin 的咧. 不過無論如此, 針對這樣的特性, 索性想寫個 plugin 來自己 antispam 一下, 結果在實測時, 發生了小狀況.

因為在 tt 裡, AddingTrackback 在 1.0.6 版本以上已成為可用的一個 event 了, 不過根據 tt 的 event 觸發行為是利用列舉 enable 的 function 來進行呼叫, 若是非 antispam 這種 plugin 倒沒什麼關係, 因為這些 event function 都是要被執行的, 不過像 antispam 這樣的應用時, 會發生 return 值要拿來做為是否加入 trackback 成功的要件的這種狀況下, 多個 event function 將會發生只回傳最後一個呼叫的 event function, tt 的 fireEvent 程式碼如下:

function fireEvent($event,$target=null,$mother=null,$condition=true){
global $service,$eventMappings,$pluginURL;
if(!$condition)
return $target;
if(!isset($eventMappings[$event]))
return $target;
foreach($eventMappings[$event] as $mapping){
include_once ("../../plugins/{$mapping['plugin']}/index.php");
if(function_exists($mapping['listener'])){
  $pluginURL="{$service['path']}/plugins/{$mapping['plugin']}";
  $target=call_user_func($mapping['listener'],$target,$mother);
}
}
return $target;
}

要命的就是其中的 foreach 中, return 回來的這個 $target, 會因為多次呼叫 call_user_func 的結果而一直被覆蓋掉, 所以若是自行撰寫獨立的 antispam 必須確保在 eolin 的 antispam 後, 但再仔細看一下, 其實 $target 是會一直再傳入的, 也就是說, 我實測結果有問題的原因, 也就是 $target 被覆蓋的原因其實並不在這裡, 而是在 eolin 的 antispam 中的 EAS_AddingTrackback function:

function EAS_AddingTrackback($target, $mother)
{
  return EAS_Call(2, $mother['site'], $mother['title'], $mother['url'], $mother['excerpt']);
}

及 EAS_Call function:

function EAS_Call($type, $name, $title, $url, $content)
{
requireComponent('Eolin.PHP.Core');
requireComponent('Eolin.PHP.XMLRPC');

global $hostURL, $blogURL;

$blogstr = $hostURL . $blogURL;

$rpc = new XMLRPC();
$rpc->url = 'http://antispam.eolin.com/RPC/index.php';
if ($rpc->call('checkSpam', $blogstr, $type, $name, $title, $url, $content, $_SERVER['REMOTE_ADDR']) == false)
{
// call fail
return true;
}

if (!is_null($rpc->fault)) {
// EAS has some problem
return true;
}

if ($rpc->result['result'] == true) {
return false; // it's spam
}

return true;
}

眼尖的人應該看出來了吧, 在 EAS_Call 中, 是判斷回呼 (RPC回 eolin antispam service)時的結果, 但是在 EAS_AddingTrackback 中, 卻不判斷原來傳入的 $target , 就直接回傳了 EAS_Call 的傳回結果, 這樣將會導致自行撰寫的 antispam plugin 若是在 eolin antispam 之前時, 就會被其回傳值給覆蓋掉, 解決方式若是要自行撰寫 plugin , 就要改寫 EAS_AddingTrackback 如下:

function EAS_AddingTrackback($target, $mother)
{
return EAS_Call(2, $mother['site'], $mother['title'], $mother['url'], $mother['excerpt']) && $target;
}

也就是拿了 EAS_Call 的回傳結果, 仍需要和之前的 $target 比對後再傳回. 這裡先簡單解釋一下 $target true 及 false 的代表意義. 在 /blog/trackback/item.php 中, 預設為 true, 如下:

if(!fireEvent('AddingTrackback',true,array('entry'=>$entry,'url'=>$url,'site'=>$site,'title'=>$title,'excerpt'=>$excerpt)))

也就是說, 預設為非 spam , 要寫入 db, 若該 $target 為 false 時, 代表不寫入 db, (當然不一定是 spam, 這要看插件的意義來決定, 不過這篇文章指的就是 spam 啦). 所以在 EAS_AddingTrackback 的最後要回傳的值必須是累加的結果, 也就是若有一個 false 就是 false 囉, 這樣就用 && (and) 來做比對, 如此一來, 便能將這個不能自己撰寫 antispam plugin 的問題解決掉了. 看起來似乎沒什麼問題, 但實務上, 到底是有一個 true 即為 true或是有一個 false 即為 false 的定義, 必須看使用上的意義來決定, 若非是在做 antispam, 這樣的改寫似乎也不太對, 不過無論如此總比原來的 eolin 都不管來得強, 否則原來的設計框架就失去意義囉.

不過真的很晚啦, 改天再來寫這個 plugin, 今天先在這裡加一行擋著先:

function EAS_AddingTrackback($target, $mother)
{
  if(strpos($mother['url'], 'freeporn.info')) return false;
  return EAS_Call(2, $mother['site'], $mother['title'], $mother['url'], $mother['excerpt']);
}

由於是 url 過濾方式, 所以可以很容易地用 freeporn.info 來做為過濾關鍵字, 一下就可以濾掉不少. 先觀察看看囉, 另外也希望大家能給我一些撰寫 antispam 上的建議, 我個人是覺得 url 就能防掉不少..

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *