2007-05-02 15:13:31

CGI.pm の charset('utf-8')

[Perl]

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