掲示板 その4 - CGI(Perl)の基本と掲示板作成
目次
掲示板 その4
さらに掲示板の機能を拡張して行きます。今回新たに行なうこと
- ログ最大数の制限
- 投稿時刻の表示
- 記事削除機能の追加
プログラム
以下のプログラムをテキストエディタで入力してください。
#!/usr/bin/perl
# 掲示板 その4
require "cgi-lib.pl";
print "Content-type: text/html; charset=Shift_JIS\n\n";
# フォーム部分を表示する
print <<EOL;
<html>
<body>
<h2>掲示板</h2>
<form method="post" action="bbs4.cgi">
<table>
<tr>
<th>タイトル</th>
<td><input type="text" name="title" size="40"></td>
</tr>
<tr>
<th>メッセージ</th>
<td><textarea name="message" cols="60" rows="5"></textarea></td>
</tr>
<tr>
<th>お名前</th>
<td><input type="text" name="namae" size="30"></td>
</tr>
<tr>
<th>e-mail</th>
<td><input type="text" name="mail" size="30"></td>
</tr>
<tr>
<th>削除キー</th>
<td><input type="password" name="delkey" size="10"></td>
</tr>
<tr>
<th> </th>
<td><input type="submit" name="write" value="送信"></td>
</tr>
</table>
<hr>
<table>
<tr>
<th>記事番号</th>
<td><input type="text" name="delno" size="10"></td>
<th>削除キー</th>
<td><input type="password" name="delkey2" size="10"></td>
<td><input type="submit" name="delete" value="削除"></td>
</tr>
</table>
</form>
<hr>
EOL
&ReadParse(*form);
# フォームの値を取得
$namae = $form{"namae"};
$mail = $form{"mail"};
$title = $form{"title"};
$message = $form{"message"};
$delkey = $form{"delkey"};
# ログファイル読み込み
open(IN, "bbs4.txt");
@log = <IN>;
close(IN);
# フォームからの書き込みのときは書き込み処理を行なう
if ($form{"write"}) {
# タグの無効化
&deltag($namae);
&deltag($mail);
&deltag($title);
&deltag($message);
&deltag($delkey);
# 改行を<br>に変換
$message =~ s/\r\n/<br>/g; # Windows系(\r\n)
$message =~ s/\r/<br>/g; # Mac系(\r)
$message =~ s/\n/<br>/g; # UNIX系(\n)
# 現在時刻を取得
$time = `date +'%Y/%m/%d %T'`;
chop $time;
#記事番号は前の番号+1
($no) = split(/\t/, $log[0]);
$no++;
# ログ先頭に書き込み内容を格納
unshift @log, "$no\t$delkey\t$namae\t$mail\t$title\t$message\t$time\n";
# ログ最大数を30件に制限
splice @log, 30;
}
# フォームからの削除のときは記事削除処理を行なう
if ($form{"delete"}) {
for ($i = 0; $i <= $#log; $i++) {
($no, $delkey) = split(/\t/, $log[$i]);
if ($no eq $form{"delno"} and $delkey eq $form{"delkey2"}) {
splice @log, $i, 1;
break;
}
}
}
if ($form{"write"} or $form{"delete"}) {
# ログファイルにロックをかけて書き込み
open(OUT, "+< bbs4.txt");
flock(OUT, 2);
truncate(OUT, 0);
seek(OUT, 0, 0);
print OUT @log;
close(OUT);
}
# ログ表示
foreach $data (@log) {
chop $data;
($no, $delkey, $namae, $mail, $title, $message, $time) = split(/\t/, $data);
print "No.$no $title";
print " 投稿者:";
if ($mail ne "") {print "<a href='mailto:$mail'>";}
print $namae;
if ($mail ne "") {print "</a>";}
print " 投稿時刻:$time";
print "<br><br>\n";
print "$message<br>\n";
print "<hr>\n";
}
print "</body>\n</html>\n";
# タグを除去するサブルーチン
sub deltag {
$_[0] =~ s/</</g;
$_[0] =~ s/>/>/g;
}
入力が終わったら、「bbs4.cgi」という名前でサーバにアップロードし、パーミッションを755にしてください。さらに空のログファイル「bbs4.txt」をサーバにアップロードし、パーミッションを666(読み書き可能)にしてください。その後bbs4.cgiが動くかブラウザで確認してください。
プログラムの説明
<th>削除キー</th>
<td><input type="password" name="delkey" size="10"></td>
削除キーを入力するフォーム部品です。記事を削除するときは、この削除キーを指定して削除します。type属性にpasswordを指定するとパスワード入力フィールドになり、入力した文字が隠されます。
if ($form{"write"}) {
今回はsubmitボタンが2つ、書き込み用のボタンと削除用のボタンがあります。どちらのボタンが押されたかを判別するにはいろいろと方法がありますが、ここではsubmitフォーム部品のname属性によって判断しています。押された方の名前だけがCGIプログラムに送られます。
# 現在時刻を取得
$time = `date +'%Y/%m/%d %T'`;
chop $time;
バッククォート(`)で囲まれた文字列はサーバ上のコマンドとして実行され、結果の文字列が返ります。ここではdate命令が実行され、$timeに現在の時刻が「年/月/日 時:分:秒」の形式で入ります。
unshift @log, "$no\t$delkey\t$namae\t$mail\t$title\t$message\t$time\n";
ログファイルには、新たな項目として記事番号・削除キー・投稿時刻が追加されます。
# ログ最大数を30件に制限
splice @log, 30;
先頭から数えて30件目以降の配列要素をカットします。splice命令の書式は以下の通り。
splice 配列, オフセット(, 個数)
配列の「オフセット」で指定した番号から「個数」分の要素を削除します。「オフセット」は0から始まります。「個数」を省略したときは残り全ての要素が削除されます。
if ($form{"delete"}) {
name属性が「delete」のsubmitボタンが存在すれば削除ボタンを押した、と判断しています。
for ($i = 0; $i <= $#log; $i++) {
$#logは配列の要素数-1を表わします。上記for文で配列全体に対してループをかけています。
if ($no eq $form{"delno"} and $delkey eq $form{"delkey2"}) {
splice @log, $i, 1;
break;
}
ログ配列の記事番号がフォームの削除記事番号と一致し、なおかつログ配列の削除キーがフォームの削除キーと一致したならsplice命令によってログ配列から該当の記事を削除しています。break文はループを抜ける命令です。