#!/usr/bin/perl -w
use DBI;
use CGI;
use Encode;
# MySQLのmy_dbデータベースのbbsテーブルの構成
# ---------------------------
# フィールド 属性
# id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
# name VARCHAR(16) NOT NULL
# message VARCHAR(200) NOT NULL
# date TIMESTAMP(14)
# データベースの認証設定
# ---------------------------
my ($dsn, $user, $password);
$dsn = "DBI:mysql:my_db:localhost";
$user = "foo";
$password = "password";
# $nameと$messageの制限文字数
# ---------------------------
my ($max_name, $max_message);
$max_name = 16;
$max_message = 200;
# フォームから値を取り出す
# ---------------------------
my $cgi = new CGI;
my ($name, $message, $mode);
if ($cgi->param('mode')) {
$mode = $cgi->param('mode'); # モード
$name = $cgi->param('name'); # 名前欄の値
$message = $cgi->param('message'); # メッセージ欄の値
}
else {
$mode = "";
$name = "";
$message = "";
}
# 各モードの処理
# ---------------------------
# $modeが空ならば、一覧モード
if (!$mode) {
&get_header; # HTMLヘッダーを出力
&get_form; # 入力フォームを出力
&get_db; # DBから取得したデータをHTMLに生成して出力
&get_footer; # HTMLフッターを出力
}
# 確認モード
elsif ($mode eq "confirm") {
&get_header;
# 制限文字数とタグのチェック
my $error_log = "";
if (!&check_var(\$name, \$message, \$error_log)) {
&get_confirm; # 確認画面を出力
}
else {
&get_error($error_log); # エラー表示を出力
&get_form;
}
&get_footer;
}
# 修正モード
elsif ($mode eq "modify") {
&get_header;
my $error_log = "";
if (!&check_var(\$name, \$message, \$error_log)) {
&replace_br(\$message); # エスケープされた
を改行に置換
&get_form;
}
else {
&get_error($error_log);
&replace_br(\$message);
&get_form;
}
&get_footer;
}
# 書き込みモード
elsif ($mode eq "write") {
my $error_log = "";
if (!&check_var(\$name, \$message, \$error_log)) {
&write_db;
}
else {
&get_header;
&get_error($error_log);
&get_footer;
}
}
# 正常なモード以外のアクセス
else {
&get_header;
&get_error("
不正なアクセスです。
"); &get_footer; } # サブルーチン # --------------------------- # 文字数制限とタグのエスケープ sub check_var { my ($nm, $nm_restore, $msg, $msg_restore, $err_log, $err); $nm = $_[0]; # $nameのreference $msg = $_[1]; # $messageのreference $err_log = $_[2]; # $error_logのreference $nm_restore = $$nm; &restore_tag(\$nm_restore); $msg_restore = $$msg; &restore_tag(\$msg_restore); $nm_length = length(decode('utf-8', $nm_restore)); $msg_length = length(decode('utf-8', $msg_restore)); # $nameを処理する if ($nm_length == 0) { ${$err_log} .= "名前を記入してください。
\n"; $err += 1; } elsif ($nm_length > $max_name) { ${$err_log} .= "名前が制限文字数を超えています。
\n"; ${$nm} = ""; $err += 1; } else { &delete_crlf($nm); # 改行を許可しない &escape_tag($nm); } # $messageを処理する if ($msg_length == 0) { ${$err_log} .= "メッセージを記入してください。
\n"; $err += 1; } elsif ($msg_length > $max_message) { ${$err_log} .= "メッセージが制限文字数を超えています。
\n"; ${$msg} = ""; $err += 1; } else { &escape_tag($msg); &replace_crlf($msg); } return $err; } # &、<、>、"を実体参照に置換 sub escape_tag { my $var = $_[0]; # reference ${$var} =~ s/&/&/g; ${$var} =~ s/</g; ${$var} =~ s/>/>/g; ${$var} =~ s/"/"/g; } # 実体参照を元に戻す sub restore_tag { my $var = $_[0]; # reference ${$var} =~ s/&/&/g; ${$var} =~ s/<//g; ${$var} =~ s/"/"/g; } # 改行文字を以下の内容でよろしいでしょうか?
$message
データベースに接続できません。
"); return; } &restore_tag(\$name); &escape_backslash(\$name); &escape_quote(\$name); &replace_br(\$message); &restore_tag(\$message); &escape_backslash(\$message); &escape_quote(\$message); $dbh->do("SET NAMES utf8"); my $query = "INSERT INTO bbs SET name=\"" . $name . "\", message=\"" . $message . "\""; $dbh->do($query); $dbh->disconnect(); print $cgi->redirect('/bbs/bbs.pl'); } # データベースからの読み出し sub get_db { my $dbh = DBI->connect($dsn, $user, $password); if (!$dbh) { &get_error("データベースに接続できません。
"); return; } my $rows = $dbh->selectrow_array("SELECT COUNT(*) FROM bbs"); if(!$rows) { &get_error("データベースが空です。
"); return; } else { $dbh->do("SET NAMES utf8"); my ($query, $sth, @row); $query = "SELECT id, name, message, date FROM bbs ORDER BY id DESC"; $sth = $dbh->prepare($query); $sth->execute(); while(@row = $sth->fetchrow_array) { my ($name, $message, $date); $name = $row[1]; $message = $row[2]; $date = $row[3]; &escape_tag(\$name); &escape_tag(\$message); &replace_crlf(\$message); print <<"HTML";$message
$date