2008年4月23日水曜日

IMAPフォルダに日本語を使ったときの文字化けみたいなやつ … 「IMAP-UTF7」というそうだ

普通の人はあんまり見ることはない気もしますが、IMAPでフォルダ名に日本語を使うと、BASE64みたいな、アルファベットや記号など7bitコード文字だけにエンコードされた名前になります。



あれって、IMAP-UTF7という名前のエンコーディングなんだそうです。



簡単にデコードできるツールってないかな?と思って、FreeBSDのportsの中を探してみたら、

ports/converters/p5-Unicode-IMAPUtf7/

というのがありました。



付属していたスクリプトをそっくりマネして書いただけなんですが、とりあえずテストするスクリプト。


require 'Unicode/IMAPUtf7.pm';
my $t = Unicode::IMAPUtf7->new, 'Unicode::IMAPUtf7';



my @input = qw(&Tgtm+DBN- &kAFP4W4IMH8wojCkMMYw4A- &j,dg0TDhMPww6w-);



for (my $i = 0; $i < @input; $i++) {
        $tmp = $t->decode($input[$i]);
        print "|" . $input[$i] . "| -> |$tmp|\n";
}


実行してみる。

% perl imap-utf7.pl | nkf
|&Tgtm+DBN-| -> |下DBN-|
|&kAFP4W4IMH8wojCkMMYw4A-| -> |送信済みアイテム|
|&j,dg0TDhMPww6w-| -> |迷惑メール|


なるほど・・・



ただ、1個めのデコード結果がおかしいような。本当は「下書き」になるはずなんだけど。



nkfがおかしいのかな?と思い、iconv。

% perl imap-utf7.pl | iconv -f 'utf-8' -t euc-jp
|&Tgtm+DBN-| -> |下DBN-|
|&kAFP4W4IMH8wojCkMMYw4A-| -> |送信済みアイテム|
|&j,dg0TDhMPww6w-| -> |迷惑メール|

だめですね。



いろいろ試す。

|&Tgtm+DBN-| -> |下DBN-|
|&Tgs-123| -> |下123|
|&ZvgwTQ-| -> |書き|
|&ZvgwTw-| -> |書く|
|&Tgswa2b4ME0-| -> |下に書き|
|&Tgtm+A-| -> |下A-|

「下書」がアウトらしい・・・



ひょっとして、Unicode/IMAPUtf7.pm がおかしい???



4 件のコメント:

  1. IMAP-UTF7 ってのは正式な名前じゃないわけです。
    このエンコードを定義している RFC 3501 では 「Modified UTF-7」としています。
    ともあれ、そのRFCを読んでいただくと分かりますが、Modified UTF-7 には "+" は含まれません。ということで、お試しになっている文字列がそもそも、Modified UTF-7 ではないわけですが、いったいどうやって作ったものでしょうか?

    返信削除
  2. Unicode::IMAPUtf7のドキュメントにはRFC2060と出てますが、
    RFC3501によって、RFC2060がobsoleteになってるんですね。
    IMAPサーバはimap-uwで、IMAPクライアントは、Netscape Communicator、Mozilla Thunderbird、Outlook Expressなどで、とくに文字化けなしです。
    「下書き」をUTF-7でエンコードすると「+Tgtm+DBN」になるようなので、+を&に置き換えて、最後に-を追加して…
    use Unicode::IMAPUtf7;
    my $t = Unicode::IMAPUtf7->new();
    print $t->decode('&Tgtm&DBN-') . "\n";
    とすれば「下書き」に戻りました。
    どういうわけか
    print $t->encode('下書き');

    +Tgtm&DBN-
    になるんですが、これはdecode()しても「下書き」に戻りません。
    謎が増えました…
    ファイルシステム上でのファイル名がどうなるかは、IMAPサーバの実装依存という感じはしますね。
    Unixで+と&といえば、「lost&found」が「lost+found」になってるのを思い出しました。

    返信削除
  3. Unicode::IMAPUtf7 のソースを見てみたら・・・これはまずいでしょ。
    そもそも、latin1 しか考えてないような。
    Encode::IMAPUTF7 のほうがよさそう。

    返信削除
  4. 確認していただきありがとうございます。
    うーん、そういうオチでしたか。

    返信削除