Maia mailguard主旨及郵件亂碼之修正

2007/12/26
在amavisd-new的網站看到這個軟體,看起來還不錯,在中文的網站(簡體)有人介紹,因此裝起來看看
後來覺得不錯,但主旨或內容如果是中文utf-8或big5或 rgb2312,會顯示亂碼(不正確解碼),查詢網路沒有中文化的相關資料,
因此自己檢視程式,查到並修改一些程式碼,成功解決了......

中文化的前置作業
1.我修改maia_languages表格的id=129的language_name 為taiwan
2.主旨的長度上述為20我變更為40,因為20相當中文字的10個字元太少
3.在maia下locale將en目錄複製為tw ,cp -r en tw
4.翻譯文章目錄tw,下面的檔案
5.安裝語言要有管理權限
6.上述編碼不要弄錯是utf-8
#注意,我使用自己翻譯的文字



maia顯示郵件列表時會有亂碼(解碼時有問題)
例:
url:http://主機/maia/list-cache.php?cache_type=?ham
在程式中list-cache.php,查到decode_header這個函式,再追到mime.php中有定義
它使用preg_math函式其樣版為(.*?)\=\?(.+?)\?([QqBb]?)\?(.+?)\?\=(.*)
它是使用正規表示法因使用kiki來測試會查到什麼
我在kiki輸入評估樣版:(.*?)\=\?(.+?)\?([QqBb]?)\?(.+?)\?\=(.*)
範例的編碼主旨由:=?utf-8?B?Rnc6IOaIgOS6uuWAkeacgOaDs+imgeeahOaDheS6uuemruWkp+iqv+afpQ==?=
 Format: =?charset?encoding?contents?=

執行Evaluate後如上圖
(utf08)是第二項
(B)是第三項
第四項是標題
我們分析一下字串
:=?utf-8?B?Rnc6IOaIgOS6uuWAkeacgOaDs+imgeeahOaDheS6uuemruWkp+iqv+afpQ==?= 
=?                                                         ?=   這是區隔符號, =?是開始 ,?=是結束
其內部的?為區格符號
因此我們可以再分為三段文字
utf-8
B
Rnc6IOaIgOS6uuWAkeacgOaDs+imgeeahOaDheS6uuemruWkp+iqv+afpQ==
其中utf-8是字集
B代表使用base64編碼,其後接的字串是使用base64編碼的文字
#因此我們要解碼,並將原先的字集轉為utf-8 ,因為中文的主旨可能是big-5或utf-8 或任何其它編碼

1.首先停用主旨解碼(這是檢視完整郵件的主旨和列表的主旨無關)
   修改view.php 中
   原來: $args['decode_headers'] = true;
   變更: $args['decode_headers'] = false;
 #因為其引用pear的模組 Mail_Mime 中 mimeDecode.php ,有問題,因此要停用
 #你可能對上一行 $args['decode_bodies'] = true;有興趣,它是針對內容的mime編碼方式,如base64或uuencode
2變更程式mime.php decode_header函式的回傳值:
  原來: return $preceding_text . $decoded_text . decode_header($following_text, $charset);
  變更: return iconv($header_charset, "UTF-8", $decoded_text);
 
  例:我們以上述範例來說明
  在函式中參數對應如下
  $preceding_text = $matches[1];                              空的
  $header_charset = trim($matches[2]);                     utf-8
  $header_encoding_type = strtoupper($matches[3]); B
  $header_contents = trim($matches[4]);                    Rnc6IOaIgOS6uuWAkeacgOaDs+imgeeahOaDheS6uuemruWkp+iqv+afpQ==
  $following_text = $matches[5];
   因此將值代入回傳值 return iconv($header_charset, "UTF-8", $decoded_text); 就會正確,如果
3.變更程式mime.php display_parts函式
      if (isset($structure->headers["from"])) {
         $ret .= "<tr><td class=\"mailheader\" align=\"left\" valign=\"top\">\n";
         $ret .= "<font color=\"red\">寄件者:</font></td>";
         $ret .= "<td class=\"mailheader\" align=\"left\" valign=\"top\">" .decode_header(trim(htmlentities($structure->headers["from"]))) . "</td></tr>";
      }
      if (isset($structure->headers["to"])) {
         $ret .= "<tr><td class=\"mailheader\" align=\"left\" valign=\"top\">\n";
         $ret .= "<font color=\"red\">收件者:</font></td>";
         $ret .= "<td class=\"mailheader\" align=\"left\" valign=\"top\">" .decode_header(trim(htmlentities($structure->headers["to"]))) . "</td></tr>";
      }
      if (isset($structure->headers["subject"])) {
         $ret .= "<tr><td class=\"mailheader\" align=\"left\" valign=\"top\">\n";
         $ret .= "<font color=\"red\">主旨:</font></td>";
         $ret .= "<td class=\"mailheader\" align=\"left\" valign=\"top\">" .decode_header(trim(htmlentities($structure->headers["subject"]))). "</td></tr>";
4.變更程式mime.php display_parts函式
     加入$pcharset在$primary及$secondary
     $primary = strtolower(trim($structure->ctype_primary));
     $secondary = strtolower(trim($structure->ctype_secondary));
     $pcharset = strtolower(trim($structure->ctype_parameters["charset"]));
     #它是取得郵件本文的某一區塊的字集編碼
5.變更程式mime.php sanitize_html函式
   function sanitize_html($body)
   function sanitize_html($body,$pcharset)
   及回傳值
    原
    $html = "\n<!-- Maia: Decoded HTML begins here -->\n";
    $html .= trim(strip_tags($body, $allowable_tags));
     $html .= "\n<!-- Maia: Decoded HTML ends here -->\n\n";
    變
    $html = "\n<!-- Maia: Decoded HTML begins here -->\n";
    $html .= iconv($pcharset,'UTF-8',trim(strip_tags($body, $allowable_tags)));
     $html .= "\n<!-- Maia: Decoded HTML ends here -->\n\n";

這樣就完成了
如果你不是使用utf-8那可以將 UTF-8改為$default_charset
並在要使用到的函式中加入 global $default_charset,以取得config.php中的$default_charset (預設字集)
#修正檔請下載maia