Perl CGI でフォームからの絵文字入力を制限する方法

絵文字制限時にエラーを戻す時のエンティティ変換

Vodafone の場合の留意点

Vodafoneの絵文字は[0x1B]G"[0x0F](女の子の顔)や [0x1B]G&[0x0F](Tシャツ)など、エンティティ変換の対象となる文字を含むものがあります。

これらの絵文字を含む文字列を、一括でエンティティ変換(例えば「"」=>「"」)してしまうと、[0x1B]G"[0x0F] と変換され、(Tシャツ)、(クマ)、(ネズミ)、(クジラ)、(自動車)と、絵文字が大増殖してしまいます。
このため、Vodafone 絵文字が出てきたら、その部分はエンティティ変換対象から外して変換を行います。

絵文字対応エンティティ変換用 Perl サブルーチン

上記のマッチをテストする場合と同じ理屈で文字列マッチを行いますが、今度は m// でなく s/// を使用します。また、ダブルバイトの範囲はエンティティ変換対象外ですので、通常のアスキー領域とVodafone絵文字領域のみを切り分けます。
出現する文字列全てに対して変換を掛けるので、繰り返し処理オプション g を使用します。

#エンティティ変換(テキストエリア用)————-
#Vodafone絵文字にはHTML特殊文字が含まれるのでこれをエスケープ
sub text4textarea($){
    my $string = shift;
    my $ascii = '[\x00-\x7f]'; #ASCIIと制御文字
    my $voda = '\x1b\x24[GEFOPQ][\x21-\x7a]*\x0f'; #少々簡略
    if ($string){
#        $string =~ s/\G((?:$ascii)*?)((?:$voda)*)/&html_entity($1).$2/ge
#        ↑このコードは間違い(2005-8-28修正)。「\G」は不要です。
#        頭から順にマッチを探してしまうため、ダブルバイトのある文字列を変換できない。
        $string =~ s/((?:$ascii)*?)((?:$voda)*)/&html_entity($1).$2/ge
    }
    return $string;
}

#引数内に含まれる特殊文字は全てエンティティ変換する————
sub html_entity{
    my $string = shift;
    if ($string){
        $string =~ s/\&/\&/g;
        $string =~ s/</\&lt;/g;
        $string =~ s/>/\&gt;/g;
        $string =~ s/"/\&quot;/g;
    }
    return $string;
}

参考資料

ダブルバイトを意図どおりマッチさせる方法については、以下のページを参考にしました。
http://www.din.or.jp/~ohzaki/perl.htm#JP_Match

参考書

「文字コード超研究」(ラトルズ)
深沢 千尋 (著)