それ、BOM 付きです - Windows 上の apache で Internal Server Error になる原因を調べる修行

Windows 上の apache でなぜか Internal Server Error になるんですけど、という問題の調査依頼。まずは apache のエラーログをごっそりもらって中を覗いてみる。

D:/path/to/apache/.htaccess: Invalid command '\xff\xfeO', perhaps misspelled or defined by a module not included in the server configuration

てなエラーが続いている。なんだマルチバイトコードが紛れ込んでいるのか、ということで、とりあえず一旦 .htaccess を削除した上で再度試してもらおうと結論づけた。

が、数時間後、ふと気づいた。これって BOM じゃないのか? そうだとすると、いろいろが説明つきやすいぞ。

Windows XP とかのメモ帳と BOM

日本語版 Windows のメモ帳は昔は文字コードとして Shift-JIS しか使えなかった。英数字だけの場合は Shift-JIS でなくて ascii コードだけで済むけど、まあ ascii コードだけで書かれてファイルを Shift-JIS として開いても別に問題はなかった。だから、ファイルを読み込むときもファイルに書き込むときも Shift-JIS でやっていてうまいこといってた。

Windows XP の頃、「やっぱ時代は UTF-8 だよね」という空気になっていたので、メモ帳もこっそり UTF-8 対応するように進化した。もちろん Shift-JIS も扱える。ファイルを読み込むときにファイルの中身を見て、「これは Shift-JIS だな」とか「これは UTF-8 だわい」とか判定して開いてくれるようになったわけ。便利だね。

で、ファイルを保存するときには文字コードを指定できるようになってる。実際にやってみよう。たとえば、メモ帳で「あ」一文字だけ書いた改行コードもないファイルを文字コードANSI」で s.txt として保存してみる。次にそのファイルを開き、「名前を付けて保存」で、今度は文字コードを「UTF-8」に変えて、u.txt として保存してみる。UTF-8 にも Shift-JIS にも対応しているテキストエディタで開いてみると、s.txt の文字コードが Shift-JIS、u.txt の文字コードUTF-8 になっているのがわかるはず。

どっちも改行なしで「あ」だけのファイルだけど、「プロパティ」を見ると s.txt のファイルサイズは 2 バイトなのに対して u.txt のほうは 6 バイトになっているのがわかる。「あ」はいわゆる 2 バイト文字だから s.txt が 2 バイトなのはいいとして、なんで u.txt が 6 バイトもあるのかって話。いわゆる 2 バイト文字は UTF-8 だと 3 バイトになるから、残りの 3 バイトはなんだ? ってことになる。これが BOM なんだね。

さて BOM って何ってことだけど。UTF-8 はマルチバイト、つまり一つの文字を複数バイトで表すから、その「上下」に重なった複数のバイトを上から順に並べるか、それとも下から順に並べるか、どっちにすんのよって問題があるわけ。本当は Shift-JIS だったってマルチバイトだからそういう問題があるんだけど、まあ上から順に出すことにしとこうや、とみんなが決めうちでやっているか問題にはならなかったわけ。UTF-8 ではそこをちゃんと対応しようぜってことで、「上から順」か「下から順」かを示せるマークを決めて、それをつけたら読み込む順番もわかるよねってした。そのマークってのが、それがバイト順を示す印、Byte Order Mark、すなわち BOM なわけ。

で、XP とか Vista とか Server 2003 とか、そのへんのメモ帳は UTF-8 で保存したときに無条件で BOM をつけるわけ。多機能なテキストエディタだと「BOM なしの UTF-8」(UTF-8N とかって名前の文字コード) で保存できるものもあるけど、メモ帳は無条件で BOM をつけるわけ。私はね、メモ帳でファイルを開くときの文字コード判定を簡単にしたいってことなんじゃないかと悪推してる。BOM つけておけば、ファイルの先頭見ただけで UTF-8 ってわかるからね。

BOM のいたずら

で最初の問題に戻ると、きっと .htaccess をメモ帳で作成して UTF-8 で保存したと思うんだよね。そうすると、ファイルの先頭に BOM がつく。apache にしてみたら、「えっと .htaccess ファイルがあるぞ。じゃ、このファイルの中のコマンドを実行しないとね。う、いきなしマルチバイトコードが書いてある。わけわかんないっす。ダメっす。」ってことになる。それがさきのエラーメッセージ。

 Invalid command '\xff\xfeO'

最後に O (ゼロでなくオー) がついているところを見ると、該当 .htaccess は先頭行が Options で始まっているんじゃないですかね。

BOM はほかにもいろんなところでいたずらしてくれる。