CGI.pm の charset('utf-8')
CGI.pmのデフォルト文字コードはISO-8859-1。
そこでcharsetメソッドで文字コード指定するが charset('utf-8') は注意。
例1)
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw(-nosticky);
my $cgi = new CGI;
$cgi->charset('utf-8');
my $str = $cgi->param('str') || '';
$str = $cgi->escapeHTML($str);
print $cgi->header,
$cgi->start_html(-title=>'test',-lang=>'ja-JP'),
$cgi->h1($str), #[error] Wide character in print
$cgi->start_form(-method=>'get'),
$cgi->textfield('str', $str, 10, 20), #[error] Wide character in print
$cgi->submit,
$cgi->end_form,
$cgi->end_html;
Wide character in printがログに出力される。
charset('utf-8')だとutf8フラグがparamメソッド取得文字列に付加される。
paramメソッド内で my $utf8 = $charset eq 'utf-8' とキメ撃ちしている事を利用して
$cgi->charset('UTF-8');
と大文字にすれば回避できるが、どうにも気持ち悪い。
仕方なくEncode::encode_utf8でutf8フラグをオフにする。
例2)
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw(-nosticky);
use Encode;
my $cgi = new CGI;
$cgi->charset('utf-8');
my $str = $cgi->param('str') || '';
$str = $cgi->escapeHTML( Encode::encode_utf8($str) );
print $cgi->header,
$cgi->start_html(-title=>'test',-lang=>'ja-JP'),
$cgi->h1($str),
$cgi->start_form(-method=>'get'),
Encode::encode_utf8( $cgi->textfield('str', $str, 10, 20) ),
$cgi->submit,
$cgi->end_form,
$cgi->end_html;
paramメソッドの時点でUTF8フラグが立つので、$str取得時はEncode::encode_utf8でutf8フラグをオフにする。
さらにtextfieldメソッドがモジュール内部でparamメソッドを使用しているため、textfieldメソッド使用時丸ごとEncode::encode_utf8で括った。
出力前に$cgiを丸ごと Unicode::RecursiveDowngrade とかでutf8フラグ除去するのがよいのか、binmode STDOUT, ":utf8"; するのがよいのか等、もう面倒な事この上ない。
CGI.pmはお気楽なはずだったのに。。残念。
※現時点 CGI.pm 3.29