北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

Shift_JIS-2004との戦い

もう、文字化けは飽き飽きです。


JIS X 0213:2004 な文字をCGIで処理するとおかしいことになるって現象があったので、調査しました。始めは、Jcode.pm とか Encode.pm の問題かと思ったんですが、分解して検証してみるとこの辺の動きには問題なさそう。徐々に上流に戻りながら調べてみたところ、どうやらCGIに到達しているデータ時点が化けているっぽいことが判明しました。送り主はIE6 (XP) 。

#!/usr/local/bin/perl
use strict;

print "Content-type: text/html; charset=Shift_JIS?n?n";

my $query = $ENV{QUERY_STRING} || join('', <STDIN>);
$query =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;


print <<__FORM__;
<html>

<head>
<title>CGI TEST</title>
</head>

<body>
<form action="test.cgi" method="GET">
<input name="test" >
<input name="test2" >
<input type="submit">
</form>
<hr>
<pre>
$query
</pre>
</body>

</html>
__FORM__


こんな至極単純なCGIでテストすると*1、「あああ」「熿」を送ると「test=、「、「、「&test2=滕」になりました。これは、ここで槍玉に挙がってるケース1と同じ現象です。


ああ、IEひでーなーとあきらめかけていたら、偶然対処法を発見。フォームのあるHTMLに、 <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> を入れるだけで、なんとこの現象が直ってしまいます。不思議不思議。「熿」は実体参照で送られてきます。


なお、同じことをSafariでやると、普通に「?」表示でした。

*1:問題切り分けのため、敢えてモジュールを何も使ってない