FORMタグから受け取った文字列の処理

FORMタグから送られるデータの形

FORMタグを使って送られるデータはどのような形をしているのか、調べて見ましょう。

(例) フォームから送られたデータを表示するCGIプログラム「print.cgi」

#!/usr/local/bin/perl

$form = <STDIN>; # 標準入力から1行読み取って変数$formに代入(実はちょっと手抜きです)

&header; # HTML ヘッダー

print $form; # 変数$formの値を表示するHTMLをprint文で表示。

&footer; # HTML フッター

# HTML ヘッダー
sub header {
    print "Content-type: text/html\n\n";
    print <<"EOM";
<html>
<head>
<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS">
</head>
<body>
EOM
}

# HTML フッター
sub footer {
    print "</body>\n</html>\n";
}

CGIプログラムにデータを送信するフォーム「form.htm」

<HTML>
<HEAD>
</HEAD>
<BODY>
<FORM METHOD="POST" ACTION="print.cgi">
名前:<INPUT TYPE="text" NAME="name"><BR>
会員番号:<INPUT TYPE="number" NAME="number" VALUE="KK-"><BR>
パスワード:<INPUT TYPE="password" NAME="pass" SIZE=20><BR>
ご意見・ご感想をお待ちしております。<P>
<TEXTAREA ROWS=8 COLS=40 NAME="message">
ひとことどうぞ
</TEXTAREA>
<INPUT TYPE=submit VALUE="送信">
</FORM>  

動作テスト

form.htm のフォームに下記のような入力をして送信してみます。

名前: shio masayuki
会員番号: KK-123!
パスワード: xyz
テキストエリア: ひとことどうぞ

実行結果

name=shio+masayuki&number=KK-123%21&pass=xyz&message=%82%D0%82%C6%82%B1%82%C6%82%C7%82%A4%82%BC%0D%0A

が表示されます。

上記の結果から

のがわかります。このままでは分かりにくいので、受け取ったデータを分かりやすい形に直さなければいけません

INPUTタグのNAME属性に全角文字を使った場合にも「%**」で置き換わってしまうので、安全のためにNAME属性は半角英数字を使用するほうがいいです。

FORMタグから送られたデータの処理

NAME1=値1&NAME2=値2&…
 (NAME*はINPUTタグで使用したNAME属性、値*はそれに対応する値)

という形の長い文字列として与えられます。以後、

$form = <STDIN>;

で変数$formに受け取った文字列を代入したものとして話を進めます。

FORMタグから受け取った文字列には大きく分けて以下の2つの作業が必要です。

  1. &で結ばれた「NAME=値」部分の切り分け
  2. 値部分の文字列を変換

順に説明しましょう。

&で結ばれた「NAME=値」部分の切り分け

&を区切り文字として文字列を分割するにはsplitを使います。

@array = split(/&/, $form); 

これにより、変数$formの値を&で区切って配列@arrayに代入します。

「値」の文字列を変換

         「値」にはフォームの内容に以下のような操作を加えられたものが与えられています。

        このため、操作を加える前の値に変換する必要があります。具体的には、

foreach (@array) { # 配列@arrayの要素の数だけ繰り返し

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

	($key, $val) = split (/=/); # =で区切って名前と値を分割
	$key =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c",hex($1))/ge; # %HH形式を16進数に
	$val =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c",hex($1))/ge; # %HH形式を16進数に
	$val =~ s/\r\n/\n/g; # 改行コードの統一
	$in{$key} = $val; # 連想配列%inに代入
}

        のような操作を行います。

実行例(print.cgi)

前回のprint.cgiを以下のプログラムに置き換えて、前回のform.htmに文字を入力してみましょう。

#!/usr/local/bin/perl

$form=<STDIN>;

@array = split(/&/,$form); # $formの内容を&で区切って配列@arrayに格納

foreach (@array) { # 配列@arrayの要素の数だけ繰り返し

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

    ($key, $val) = split (/=/); # =で区切って名前と値を分割

    $key =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c",hex($1))/ge; # %HH形式を16進数に
    $val =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c",hex($1))/ge; # %HH形式を16進数に
    $val =~ s/\r\n/\n/g; # 改行コードの統一

    $in{$key} = $val; # 連想配列%inに代入
}

&header; # HTML ヘッダー

$,=','; # print文の文字区切りを「,」に設定
print %in; # 連想配列%inの値を表示。

&footer; # HTML フッター

(以下、ヘッダーとフッターのサブルーチン定義)