Safariでの意味不明な文字化け解消

XOOPSで運営してるサイトで、EUC-JPの文字コードを指定してちゃんとHTTP Headerも出ているにも関わらず、Safariが認識してくれなくて悩んでた(ずっと放置してた)んやが、ようやく納得のいく形で解決した。というか相当前に解決はしてたようやが、原因がまとまった記事が見あたらなかったのでまとめておく。問題は複数あったようだ。

Safariの問題

実装を読んだわけではないんで確信はないが、なんか文字コード判定に2段階あるらしい。
第1段階が多分HTTP Headerで指定されたContent-Typeのcharset指定で、ここで指定されたものが第2段階でのデフォルト値になる。指定がなければ恐らくデフォルトエンコーディングの値。
第2段階が実際のHTMLを読む段階での自動判定で、通常エディタなどで行われるような、文字コードを特定できるような文字が出てきた時点で確定とするタイプのアレ。このとき、METAタグも参考にして、それでも特定できなければデフォルト値、というところかなぁ。
この第2段階の自動判定が、HTTP HeaderやMETAタグで明示的に指定があった場合でも実行されるのが混乱の元だった。「METAタグ指定と実際のエンコードが違った場合、Safariだと化ける」という情報があった気がしたんだが、ガセか…。自動判定が弱々し過ぎて、勘違いしたのかもしれない。

しかし、Safariの判定ロジックがようやく納得できた。今迄HTTP Headerを無視するクソブラウザやと思ってたが、若干印象が良くなったよ。

XOOPSの問題

XOOPSはシステム側でKeywordやDescriptionなどのMETAタグが設定できるんやが、標準設定ではAuthorとフッタのところにcopyrightのマルC(©)が入っている(現在のXOOPS Cubeでもこうなっているかは知らない)。これがEUC-JPでは表現できないコードで送られてくるため、SafariはHTTP Headerを無視して自動判定の結果を優先してくれる、という仕組になっている。

ブラウザの問題(?)

XOOPSでも多分初期値としてはちゃんと実体参照で書かれてるんやと思うが、書換えるとき、表示するためにブラウザが解釈して実体に置き換えられてしまい、うっかりKeywordを書換えたりすると一緒にAuthorとかも更新されて、予期せぬうちにこの問題が発現する、というシナリオなんやろうなぁ。
で、UTF-8ならともかくEUC-JPだと表現できんので、その場合とりあえずマルCだけ適当なコードで送られて変になるんやろうか?なんかFirefox3だとまた挙動が違って、全体が別のエンコードだと思われて投稿全体が化けるとかエラいことになるようだ。多分このへんはブラウザによって挙動が違うんやろうけど、かなりデンジャラス。

解決策

そういうわけなので、問題解決としては大きく2つあって、

  1. Safari撹乱の元凶たるマルCを消す
  2. 自動判定がうまく行くように先頭あたりでコメントを付ける

ということになる。1.はいいとして、2.はEUC-JPにしか含まれない領域のbyte値を持つ文字(京とか美乳とか)を先頭あたりに挿入することによって、ブラウザを騙すということのようだ。Yahooがこの対策を取っていて有名になったらしく、いまだにYahoo Japanではheadの先頭あたりにコメントで京が入っている。見たところ問題ないから、もう消してええと思うんやけどな…。[2008/1/4追記]今度のレイアウト刷新で消えたようだ。一応証拠としてWeb魚拓

しかし本当はXOOPS側が、表示するときにエスケープ文字(&)のエスケープ処理を行わなければならないんやが、これを怠っているというのがバグとして大きい(新しいのだと修正されてるんやろうか…)。サニタイズ言うなキャンペーンとか、このへんのややこしい話は昔まとまった記事があったのでリンクを張っておこう。