星期四, 8月 18, 2011

修正8 bit header在Openwebmail顯示亂碼問題

上一次 解決了 Roundcube的主旨亂碼問題,這次再試著解決Openwebmail的Big5/GBK顯示亂碼。註:此處修正2.53版,自從2009年以來都沒有更新,3.0 beta要釋出得要一段時間。

簡單地說,若在email的header沒有指定Content-Type charset,未編碼的8 bit header在預設UTF-8 的Openwebmail看到主旨、寄件人等名字就是一團糟。

因為敝公司仍未正式轉換到Roundcube,加上VB超人說他比較喜歡Openwebmail的介面,所以夾卵蛋拼小命也要試著做出來,至少在List畫面要正常吧!

首先,經過一番搜尋,發現最好的CJK自動偵測編碼是中國的牛人 錢宇 所開發的 Encode::Detect::CJK 。這部份必須自行安裝,在FreeBSD的ports裏並沒有,所以我用CPAN安裝後,就破壞了FreeBSD的package。CPAN的使用方式可參考高手Tsung的介紹。其實也很簡單,就一行指令:
sudo cpan install Encode::Detect::CJK
接下來加個小function,在openwebmail/modules/lang.pl,做成patch如下:
--- lang.pl 2007-08-20 14:22:38.000000000 +0800
+++ lang.pl 2011-08-18 10:41:27.000000000 +0800
@@ -6,6 +6,9 @@
 use strict;
 use vars qw(%languagecodes %countrycodes %charactersets %RTL);

+use Encode;
+use Encode::Detect::CJK qw(detect);
+
 # LANGUAGE CODES
 # derived from ISO-639-1 (updated 06/24/2006)
 # http://www.loc.gov/standards/iso639-2/langcodes.html
@@ -519,6 +522,13 @@
    return exists $charactersets{$charset};
 }

+sub to_utf8 {
+   my $encoding = detect($_[0]);
+   return encode('utf-8', decode($encoding, $_[0]));
+}
+    
+    
+
 sub guess_browser_locale {
    my $available_locales = $_[0];
有了function就好辦事,再來patch list,改openwebmail/openwebmail-main.pl :
--- openwebmail-main.pl 2009-05-08 08:34:12.000000000 +0800
+++ openwebmail-main.pl 2011-08-18 10:47:18.000000000 +0800
@@ -579,8 +579,9 @@
$charset=(ow::lang::localeinfo($browserlocale))[6];
}
# convert from message charset to current user charset
- my ($from, $to, $subject)=iconv('utf-8' , $prefs{'charset'}, $attr[$_FROM], $attr[$_TO], $attr[$_SUBJECT]);
-
+ #my ($from, $to, $subject)=iconv('utf-8' , $prefs{'charset'}, $attr[$_FROM], $attr[$_TO], $attr[$_SUBJECT]);
+ my ($from, $to, $subject) = (ow::lang::to_utf8($attr[$_FROM]), ow::lang::to_utf8($attr[$_TO]), ow::lang::to_utf8($attr[$_SUBJECT]));
+
$linehtml=$linetemplate;
if ($prefs{'uselightbar'}) {
$tr_bgcolorstr=qq|bgcolor=$style{tablerow_light} |;
@@ -640,9 +641,11 @@
foreach my $recv (@recvlist) {
my ($n, $a)=ow::tool::email2nameaddr($recv);
# if $n or $a has ", $recv may be an incomplete addr
+ $n = ow::lang::to_utf8($n);
push(@namelist, $n) if ($n!~/"/);
push(@addrlist, $a) if ($a!~/"/);;
}
+
my ($to_name, $to_address)=(join(",", @namelist), join(",", @addrlist));
$to_name=substr($to_name, 0, 29)."..." if (length($to_name)>32);
$to_address=substr($to_address, 0, 61)."..." if (length($to_address)>64);
最後在讀信時也要改一下,這次輪到openwebmail/openwebmail-read.pl:
--- openwebmail-read.pl 2009-05-08 08:34:12.000000000 +0800
+++ openwebmail-read.pl 2011-08-18 10:58:16.000000000 +0800
@@ -377,8 +377,10 @@
}

($from,$replyto,$to,$cc,$bcc,$subject)
- =iconv('utf-8', $readcharset, $from,$replyto,$to,$cc,$bcc,$subject);
- ($body) = iconv($convfrom, $readcharset, $body);
+# =iconv('utf-8', $readcharset, $from,$replyto,$to,$cc,$bcc,$subject);
+ = (ow::lang::to_utf8($from), ow::lang::to_utf8($replyto), ow::lang::to_utf8($to),ow::lang::to_utf8($cc),ow::lang::to_utf8($bcc), ow::lang::to_utf8($subject));
+# ($body) = iconv($convfrom, $readcharset, $body);
+ $body = ow::lang::to_utf8($body);

# web-ified headers
foreach ($from, $replyto, $to, $cc, $bcc, $subject) { $_=ow::htmltext::str2html($_); }
@@ -692,8 +694,11 @@
} else {
my $smartdestination;
if ($prefs{'smartdestination'}) {
- my $subject=(iconv('utf-8', $readcharset, $message{'subject'}))[0]; $subject=~s/\s//g;
- my $from=(iconv('utf-8', $readcharset, $message{'from'}))[0];
+ #my $subject=(iconv('utf-8', $readcharset, $message{'subject'}))[0];
+ my $subject= ow::lang::to_utf8($message{'subject'});
+ $subject=~s/\s//g;
+ #my $from=(iconv('utf-8', $readcharset, $message{'from'}))[0];
+ my $from = ow::lang::to_utf8($message{'from'});
foreach (@validfolders) { # use validfolders instead of movefolders because validfolders are real folders and it is not escaped
if ($subject=~/\Q$_\E/i || $from=~/\Q$_\E/i) {
$smartdestination=$_; last;
@@ -781,7 +786,8 @@
}

if ($is_writableabook_found) {
- my $fullname=(iconv('utf-8', $prefs{charset}, $ename))[0];
+ #my $fullname=(iconv('utf-8', $prefs{charset}, $ename))[0];
+ my $fullname=ow::lang::to_utf8($ename);
my ($firstname, $lastname) = split(/\s+/, $fullname, 2);
$temphtml .= qq| |. iconlink("import.s.gif", qq|$lang_text{'importadd'} |.ow::htmltext::str2html($eaddr), qq|href="$config{'ow_cgiurl'}/openwebmail-abook.pl?action=addreditform&editformcaller=readmessage&sessionid=$thissession&sort=$sort&msgdatetype=$msgdatetype&page=$page&folder=$escapedfolder&message_id=$escapedmessageid&N.0.VALUE.GIVENNAME=|.ow::tool::escapeURL($firstname).qq|&N.0.VALUE.FAMILYNAME=|.ow::tool::escapeURL($lastname).qq|&FN.0.VALUE=|.ow::tool::escapeURL($fullname).qq|&EMAIL.0.VALUE=|.ow::tool::escapeURL($eaddr).qq|&formchange=1" onclick="return confirm('$lang_text{importadd} |.ow::htmltext::str2html($jseaddr).qq| ?');"|) . qq|\n|;
} else {
因為在下完全不懂駱駝文,所以若有高手看到還請見諒。

2 則留言:

johnpupu 提到...

我看看能不能把 Encode::Detect::CJK send pr 進去

鳥毅 提到...

感謝大大的協助 :D