15. 総合練習
今日は、今までの総合練習として、1つだけ課題を出そうと思います。
1. 簡易的な掲示板を作成してください。ただし、以下に条件に従ってください。
(1) HTMLは、下のテンプレートを使用してください。
(2) ユーザは、ハンドルネームとメッセージを入力でき、一度登録したら、
次回からはクッキーにより、ハンドルネームをデフォルトで表示するように
してください。
(3) データの保存は、ファイルに行ってください。保存するデータは、日付、
ハンドルネーム、メッセージです。
(4) プログラムは、1つのCGIファイルで完結させてください。フォームの
送信先は、自分自身のファイルになります。ただし、データファイルは
別ファイルとしてください。
(5) データファイルに何もデータがない場合は、ハンドルネームとメッセージの
入力部分のみを表示してください。 データがあるときは、メッセージ一覧を
表示してください。
(6) 日付は、メッセージを登録した日付のこととします。
テンプレートHTML
-----------------------------------------------------------------
<HTML>
<BODY>
<CENTER>
<P><FONT style="font-size=12pt"><B>◆ 簡易掲示版 ◆</B></FONT></P>
<FORM action="" method="post">
<TABLE bgcolor="#b0b0b0" border="0" cellPadding="3" cellSpacing="2">
<TBODY>
<TR bgcolor="#f0f0f0">
<TD nowrap><FONT style="font-size=9pt">ハンドル</FONT></TD>
<TD nowrap><INPUT name="hd" size="22" maxlength="40">
</TR>
<TR bgcolor="#f0f0f0">
<TD nowrap><FONT style="font-size=9pt">メッセージ</font></TD>
<TD nowrap><INPUT name="ms" size="62" maxlength="200">
</TR>
</TBODY>
</TABLE>
<BR>
<TABLE bgcolor="#b0b0b0" border="0" cellPadding="3" ccllPladding="2">
<TBODY>
<TR bgcolor="f0f0f0">
<TD nowrap><INPUT name="submit1" type="submit" value=" 投稿 "></TD>
<TD nowrap><INPUT name="reset1" type="reset" value="リセット"></TD>
</TR>
</TBODY>
</TABLE>
</FORM>
<TABLE bgcolor="#b0b0b0" border="0" cellpadding="3" cellspacing="2">
<TBODY>
<TR bgcolor="#d0d0d0">
<TD nowrap><FONT style="font-size=9pt">日付</FONT></TD>
<TD nowrap><FONT style="font-size=9pt">ハンドル</FONT></TD>
<TD><FONT style="font-size=9pt">メッセージ</FONT></TD>
</TR>
<TR bgcolor="#f0f0f0">
<TD nowrap><FONT style="font-size=9pt">2005/01/01 15:00</FONT></TD>
<TD nowrap><FONT style="font-size=9pt">ハンドル名を出力</FONT></TD>
<TD><FONT style="font-size=9pt">ここにメッセージを出力</FONT></TD>
</TR>
</TBODY>
</TABLE>
</CENTER>
</BODY>
</HTML>
-----------------------------------------------------------------
★前回の課題の解答
1. クッキーに接続した日時(YYYY/MM/DD HH:MM:SS)を保存し、取り出すプログラムを
作成してください。取り出した日時は、「前回のアクセス日時」として、HTML上に
表示してください。1つのプログラムにまとめてしまっても結構です。
→下のサンプルを参照してください。
-----------------------------------------------------------------
#!/usr/local/bin/perl
# クッキー名
$cookie_name = "cname";
# クッキーを取得する関数
%cook_data = GetCookie();
# クッキーの内容を取得
$access_time = $cook_data{$cookie_name};
# 現在時刻を取得
($sec, $min, $hour, $mday, $mon, $year) = localtime();
$new_time = sprintf("%04d/%02d/%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
# クッキーに書き込む文字列を作成
$str_cookie = $cookie_name . "=" . $new_time;
# クッキーに書き込む関数
SetCookie($str_cookie, 60*60*24*30);
print "Content-type: text/html\n\n";
print << "END_OF_HTML";
<html>
<body>
前回の接続時間 $access_time
</body>
</html>
END_OF_HTML
#------------------------------------------------------------------
# 関数 : SetCookie
# 説明 : クッキー設定
# 引数 : 保存する文字列
# : クッキーの有効時間(秒)
# 戻値 : なし
#------------------------------------------------------------------
sub SetCookie
{
my($data, %data, $str_cookie, $cookie_time);
my($sec, $min, $hour, $mday, $mon, $year, $wday);
my(@mons, @week, $dt);
$str_cookie = @_[0];
$cookie_time = @_[1];
#// 文字列のエスケープ
$str_cookie =~ s/\,/%2C/g;
$str_cookie =~ s/ /%20/g;
$str_cookie =~ s/;//g;
$str_cookie =~ s/([^\w\=\& ])/'%' . unpack("H2", $1)/eg;
#// 有効期限設定
($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime(time + $cookie_time);
@mons = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
@week = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
$dt = sprintf("%s\, %02d-%s-%04d %02d:%02d:%02d GMT", $week[$wday], $mday, $mons[$mon], $year+1900, $hour, $min, $sec);
#// ヘッダ出力
print "Set-Cookie: $str_cookie expires=$dt;\n";
}
#------------------------------------------------------------------
# 関数 : GetCookie
# 概要 : クッキー取得
# 引数 : なし
# 戻値 : クッキーのハッシュ値
#------------------------------------------------------------------
sub GetCookie
{
my($cookie) = $ENV{'HTTP_COOKIE'};
my($key, $val, %data);
my(@cookie);
#// クッキー取得
@cookie = split(/ /, $cookie);
foreach(@cookie)
{
($key, $val) = split(/=/);
#// 文字列をデコードする
$val =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;
$val =~ s/%2C/\,/g;
$val =~ s/%20/ /g;
$data{$key} = $val;
}
#// 戻り値セット
return %data;
}
exit(0);
-----------------------------------------------------------------
■解説
前回のサンプルにあった関数をそのまま使用しています。
クッキー名は任意の文字列ですので、何でも構いません。
クッキーの有効期限は、30日間としています。
最初のアクセス時は何も表示されませんが、更新ボタンでもう一度アクセスすると、
前回保存した日時が表示されます。
2. HTML上に、名前の入力ボックスを作成し、これをPOSTで受け取り、クッキーに
保存し、次回のアクセス時からは、この名前が表示されるプログラムを作成して
ください。1つのプログラムにまとめてしまっても結構です。
→下のサンプルを参照してください。
-----------------------------------------------------------------
#!/usr/local/bin/perl
# パラメータ取得
%param = GetPara();
$access_name = $param{'access_name'};
# クッキー名
$cookie_name = "cname2";
# 名前が送られていない場合は、クッキーから取得
if (!$access_name) {
# クッキーを取得する関数
%cook_data = GetCookie();
# クッキーの内容を取得
$access_name = $cook_data{$cookie_name};
}
# 名前が空でなければクッキーに格納
if ($access_name) {
# クッキーに書き込む文字列を作成
$str_cookie = $cookie_name . "=" . $access_name;
# クッキーに書き込む関数
SetCookie($str_cookie, 60*60*24*30);
}
print "Content-type: text/html\n\n";
print << "END_OF_HTML";
<html>
<body>
END_OF_HTML
if ($access_name) {
print "ようこそ$access_nameさん";
}
# 入力画面を表示する
print << "END_OF_HTML";
<form action="014a.cgi" method="post">
お名前 <input type="text" name="access_name" value="名前を入力してください。" size="50"><br>
<input type="submit" value="送信">
</form>
</body>
</html>
END_OF_HTML
#------------------------------------------------------------------
# 関数 : SetCookie
# 説明 : クッキー設定
# 引数 : 保存する文字列
# : クッキーの有効時間(秒)
# 戻値 : なし
#------------------------------------------------------------------
sub SetCookie
{
my($data, %data, $str_cookie, $cookie_time);
my($sec, $min, $hour, $mday, $mon, $year, $wday);
my(@mons, @week, $dt);
$str_cookie = @_[0];
$cookie_time = @_[1];
#// 文字列のエスケープ
$str_cookie =~ s/\,/%2C/g;
$str_cookie =~ s/ /%20/g;
$str_cookie =~ s/;//g;
$str_cookie =~ s/([^\w\=\& ])/'%' . unpack("H2", $1)/eg;
#// 有効期限設定
($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime(time + $cookie_time);
@mons = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
@week = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
$dt = sprintf("%s\, %02d-%s-%04d %02d:%02d:%02d GMT", $week[$wday], $mday, $mons[$mon], $year+1900, $hour, $min, $sec);
#// ヘッダ出力
print "Set-Cookie: $str_cookie expires=$dt;\n";
}
#------------------------------------------------------------------
# 関数 : GetCookie
# 概要 : クッキー取得
# 引数 : なし
# 戻値 : クッキーのハッシュ値
#------------------------------------------------------------------
sub GetCookie
{
my($cookie) = $ENV{'HTTP_COOKIE'};
my($key, $val, %data);
my(@cookie);
#// クッキー取得
@cookie = split(/ /, $cookie);
foreach(@cookie)
{
($key, $val) = split(/=/);
#// 文字列をデコードする
$val =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;
$val =~ s/%2C/\,/g;
$val =~ s/%20/ /g;
$data{$key} = $val;
}
#// 戻り値セット
return %data;
}
#------------------------------------------------------------------
# 関数 : GetPara
# 概要 : パラメータ取得
# 引数 : なし
# 戻値 : パラメータハッシュ配列
#------------------------------------------------------------------
sub GetPara
{
my($query_string); #// エンコードされたパラメータ全体
my(@a, $a); #// エンコードされたパラメータを分解したもの
my($name, $value); #// デコードされたパラメータ
my(%in);
#// パラメータの読み込み
if ($ENV{ "REQUEST_METHOD" } eq "POST")
{
#// POSTなら標準入力から読み込む
read(STDIN, $query_string, $ENV{ "CONTENT_LENGTH"});
}
else
{
#// GETなら環境変数から読み込む
$query_string = $ENV{"QUERY_STRING"};
}
#// 「変数名1=値1&変数名2=値2」の形式をアンパサンド(&)で分解
@a = split(/&/, $query_string);
# パラメータの取得
foreach $a (@a)
{
#// =(イコール)で分解
($name, $value) = split(/=/, $a);
#// + や %8A などのデコード
$value =~ tr/+/ /;
$value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex( $1 ))/eg;
$value =~ s/\t/ /g;
$value =~ s/\r//g;
$value =~ s/\n/<br>/g;
#// 後で使用するため,$in{'パラメータ名'} に代入しておく
$in{ $name } = $value;
}
return %in;
}
exit(0);
-----------------------------------------------------------------
■解説
こちらも、クッキーの関数をそのまま利用しています。
さらに、前々回使用したパラメータ取得関数を再度使用しています。
今回は、一度名前を送信したかどうかで表示を変えなくてはなりませんので、
パラメータをまず取得し、空ならクッキーを取得します。
クッキーから取得した場合も、再度クッキーに書き込むと、クッキーの
有効期限を更新できます。
名前が取得できれば「ようこそ」を表示し、なければ送信ボックスのみを
表示するという処理になります。
|