連想配列(ハッシュ)への取り込み
 
入力データの分解が終わったら、名前と値で連想配列にセットします。
GETメソッドの場合、データはURLの一部なのでURLとして都合の悪い文字(RFC1738 に記述されている)は、1文字が16進数値2文字にエンコードされ、その前に%文字が付加されています。
POSTメソッドの場合は、実際にはデータは標準入力から読み込みますが、GETメソッドと同様にエンコードされています。
以下の文字が実際にエンコードされるものです。
 
0x00 から 0x20 のコントロール文字
0x7F から 0xFF のトップビットが立っているもの
" # % ; < > ? { } | \ ^ ~ ` [ ]

これらに加えて & = はデータの区切り文字に使われるので、これらがデータ中に現れる場合もエンコーディングされています。さらに空白文字は + に変換され、データ中の + はやはり16進数値にエンコーディングされています。

デコードする際は特にこれらの文字を気にせずに %XX が現れたら元の文字に変換します。

具体的には、例えばSJISの'あ'という文字は16進数値で0x82 0xA0であり、%82%A0とエンコードされています。これをデコードするには、
 
#!/usr/bin/perl

$before = '%82%A0';             # SJISの「あ」

# 先頭の%を除いて16進数を取り出す
@x = ($before =~ /%([A-Fa-f0-9][A-Fa-f0-9])/g);
# 16進数を10進数にする
@x = grep { $_ = hex } @x;
# 16進数値を文字に変換
$after = pack("cc", @x);

print "before=$before, after=$after\n"; 

これを一気に行うと
 
$_ = $before;
$after =~s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c", hex($1))/;

とすることができます。

サンプルスクリプトでは、デコードしたものを
なお、日本語に関する処理は「日本語コードの取り扱い」の項を参照してください。
 
このサブルーチンは再利用可能なので util.pl に入れておきます。
#
# parseInput(encoding)
# <IN>  encoding: 日本語コード(jis|sjis|euc)
# <OUT> Name=>Val のハッシュ(グロブ)
#
sub parseInput
{
        my($encoding) = @_;
        my($method) = $ENV{'REQUEST_METHOD'};
        local($query, @in, $key, $val);


        # 日本語が必要な場合は jcode.pl を取り込む
        require 'jcode.pl' if $encoding;

        # GETメソッドかPOSTメソッドかを判別する
        if ($method eq 'GET') {
                $query = $ENV{'QUERY_STRING'};
        }
        elsif ($method eq 'POST') {
                read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
        }

        # 入力データを分解する
        local(@query) = split(/&/, $query);

        # Name=Val を $in{'Name'} = 'Val' のハッシュにする。
        foreach (@query) {

                # + を空白文字に変換
                tr/+/ /;

                # Name=Val を分ける
                ($key, $val) = split(/=/);

                # %HH形式を元の文字にデコードする。
                $key =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c", hex($1))/ge;
                $val =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c", hex($1))/ge;

                $val =~ s/\r\n/\n/g;

                # 日本語コードが指定されている場合は変換する。
                jcode'convert(*key, $encoding) if ($encoding);
                jcode'convert(*val, $encoding) if ($encoding);

                # 連想配列(ハッシュ)にセット
                $in{$key} = $val;
        }

        # 連想配列のグロブを返す
        return *in;
}