入力データの分解
 
QUERY_STRINGにセットされたデータ(GETメソッドの場合)もしくは標準入力から読んだデータ(POSTメソッドの場合)は、そのままでは利用することができません。データの中身は

名前1=値1&名前2=値2&名前3=値3&名前4=値4& ...名前N=値N

となっているので、&で分解します。
なお、日本語に関する処理は「日本語コードの取り扱い」の項を参照してください。
 
このサブルーチンは再利用可能なので 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;
}

次に連想配列(ハッシュ)に取り込みます。