RFC2231を読む
人生に三度来るという RFC 読みたい期の第一期
何をとち狂ったのか、仕事の息抜きに RFC を読んでいます。これは人生に三度来るという RFC 読みたい期に突入したと言って良いでしょう。
で、何の RFC を読んでいるかというと、メールの添付ファイル名についてのフォーマット
ここら辺を見ているのだけど、もう少し素人にも優しいページ
ココを見て解読中。
余談
Thunderbird 1.5 がでたばかりの頃は、この RFC2231 に準拠したファイル名を解釈できるメーラーは多くなかったそうで、「XXさんのメールについてる添付ファイルが読めません><」みたいな事があったそうな。
で、その時のファイル名ってのが RFC2322 に準拠した変換をしている・・・はずだけど、微妙に間違っていたらしい。
以下を見ると、一目瞭然で、ファイル名を折り返す際の行末はセミコロンで区切るはずが、改行のみで区切られているという件。
ちなみに、現在、自分の使っている Thunderbird 2.0(MacOSX版)では正しくセミコロンで区切られているようです。
閑話休題
で、 RFC を読んでいるわけだけど、非常にわかりにくい。なので、日本語の解説ページを辺り、デコード方法を考える。
例えば、Japanese Filename ここでの例として、以下のような文字列が現されている*1。
Content-Disposition: attachment;
filename*=iso-2022-jp'ja'%1B%24B%24%5B%244%24%5B%242%1B%28B.jpeg
これが「ほごほげ.jpeg」となるようだ。
とりあえず、filename* の解釈とか、iso-2022-jp とか書いてある部分は無視して、本文部分(つまり、「ほごほげ.jpeg」の部分)をどう解釈すれば良いのかを考える。
%1B%24B%24%5B%244%24%5B%242%1B%28B.jpeg
これね。
まず最初に、なんとなくイメージとして、文字コードが ISO2022-JP*2であることから、漢字INや漢字OUTと言ったJIS漢字コードが含まれる事が想像できる。
という訳で、どのように解釈していくかと言うと・・・
- %がある部分は 16 進数の二桁だよ
- 元々英数字のものはそのままだよ
という風に見る。つまり、16進数の文字か、16進数ではない文字のどちらかを片側に合わせてあげる必要がある(ややこしい・・・)。
例えば、16進数部分(%XX)を文字列*3に戻してあげれば、普通の文字コード(JISコード)の文字列になるはずである。
というわけで、 ruby で書いてみた。・・・というか、書くに至るまでに2時間くらい掛かった\(^o^)/
ロジック的には分かったんだけど、基数変換とかやってるとわけわからなくなるんよ><
irb(main):150:0* str = '%1B%24B%24%5B%244%24%5B%242%1B%28B.jpeg' => "%1B%24B%24%5B%244%24%5B%242%1B%28B.jpeg" irb(main):151:0> str.gsub(/%([\dA-F][\dA-F])/i) { $1.to_i(16).chr } => "\e$B$[$4$[$2\e(B.jpeg"
とりあえず、%の次の二文字を取るのはすぐにできるんだけど、それをどうやって文字に戻すのか、もうパニックですよ。。。
ってか、 gsub とか久しぶりにつかった気がする!
で、こんな感じの文字列になったのだけど、これでは常人には読めない。とりあえず、文字コードを UTF-8 にしてみる。
irb(main):153:0* res = str.gsub(/%([\dA-F][\dA-F])/i) { $1.to_i(16).chr } => "\e$B$[$4$[$2\e(B.jpeg" irb(main):154:0> $KCODE='u' => "u" irb(main):155:0> NKF.nkf("-w", res) => "ほごほげ.jpeg"
おおぉ、読める!
というわけで
うまい事 %の 16進数を抜き出して、その値をアスキーコード表に基づいて変換してあげると、元の文字列にできますね。
ね、簡単でしょう?