2008年01月18日
川俣晶の縁側ソフトウェアその他開発日誌 total 3640 count

tconvlib.dllの8年越しの問題解決完了・ISO-2022-JP出力時最後に1バイトモードに戻す

Written By: 川俣 晶連絡先

 文字コード変換DLLのtconvlib.dllを直しました。実に8年越しの対処となります。

修正内容 §

 ISO-2022-JPへ変換を行ったとき、終了時に2バイト文字モードだった場合、US-ASCIIモードに戻すエスケープシーケンスが入っていなかったので挿入するようにした。

 最後にモードを戻す義務がどこまであるかは、RFC等を見た範囲では必ずしも明確ではなかったと記憶しますが、もはやかなり忘却の彼方です。

 この問題はたいていの場合顕在化しません。なぜかといえば、改行コードが1バイト文字なので、行末で必ず1バイトモードに戻るからです。

 この問題が顕在化するのは、メールのSubjectのエンコードが主です。SubjectをMIMEエンコードした時に、実装がまずいと文字化けの原因になります。たとえば、"あA"というSubjectがあり、"あ"だけをMIMEエンコードしたとします。このとき、MIMEエンコードしていない"A"はあくまで"A"であって他の文字ではありません。しかし、単純にMIMEエンコードをデコードして置換するだけ、という良くない実装が行われるケースがあります。このとき、従来のtconvlib.dllを使って文字コード変換を行うと、"あ"の後で戻るエスケープシーケンスが無いので、"A"は2バイト文字の1バイト目として認識され、文字化けします。

 この問題は本質的にMIMEエンコードを扱うプログラム側で解決されるべきものだと思いますが、それはさておき、最後にUS-ASCIIに戻さないのも不自然な実装だし、tconvlib.dll側を直すだけで改善されるケースも多いと思うので、tconvlib.dllも直しました。

なぜ8年も放置されたのか §

 仕様の不自然な点を解消する等の目的で、大々的なコードの改変に取り組んだものの、途中で力尽きていたからです。途中まで組んだコードを放棄して元のバージョンに戻って修正するか、それとも、そのままの方針で大工事を行うか、決断しきれず放置されていました。

 更に時間が経過すると、ソースの詳細も忘れてしまいました。作業の手順、状況も忘れて、うかつにソースに触れなくなってしまいました。

 今回は、「完全にUnicode時代に入った結果として、もうtconvを改善する必要はない」と割り切って、tconv 0.8のソースに戻ってそこから修正を入れました。

技術的な問題 §

 しかし、一瞬で終わると思った修正は難工事になりました。

 Visual SourceSafeが勝手にテキストファイル扱いして改行シーケンスを壊してしまったEUC-JPのテストファイルのおかげでテストがこけたり。ソースを読んだり。久々にVisual C++ 6.0を起動したり。

 ソースの修正も簡単には行きませんでした。APIを変えずに動作を変えるためには、IsEOFでEOFになったときにバッファにエスケープシーケンスを足して「まだEOFではない」と嘘のリターンを行うというトリッキーな方法で解決しました。