さて、いよいよ簡単な掲示板を完成させようと思いますが、その前に2つだけ説明させてください。
ひとつは、Perl プログラムでは、# の記述があれば、それ以降はコメント覧となる事です。
ただ、print 等の、文字列データ中は、文字として判断されます。
HTMLを記述している場所でもそういう事になります。
ふたつ目は、サブルーチンの存在です。
たとえば、同じHTMLを表示するのに、何度も同じ記述を、同じスクリプト内で書くのは面倒だし、見づらいし、ナンセンスです。
そこで、大きな流れ以外をサブルーチンにして、引き出して実行するようにすれば、プログラムもスッキリ見やすくなります。
書き方はこんな感じです。
sub html {
#この部分にHTMLを表示するソースを書きます。
}
サブルーチンの宣言は、sub の後に、適当な名前(先頭は英字それ以降は英数と _ のどれか)を書いて、{ } このカッコ内が、実行される事になります。
サブルーチンを実行する命令は、& の後にサブルーチンの名前を入れます。
&html;
上記のように書けば、サブルーチン、html が、実行される事になります。
さて、では受け取ったデータを、まずはデータファイルに追加するソースを書きます。
掲示板の投稿データを保存するファイル名は、logdata.dat とします。
$logdata = "$cname & $chat\n";
open(LOGD,">>logdata.dat") || die "Can't Open User Access Log: $!\n";
print LOGD $logdata;
close(LOGD);
こんな感じです。
カウンタの数字データを保存した時とは若干違う部分があります。
それは、>> が2つ並んでいる事です。
前回は上書きでしたが、今回は追加するって事です。
もし上書きしたら、前の人が投稿した掲示板のデータが消えてしまいますから。
そして1行目の説明ですが、名前と本文を、一つのデータとして保存する為に、データを スペース & スペース で区切って、最後に改行して $logdata に入れています。
別に2行に分けて保存してもかまわないのですが、後の処理が面倒になるので、ひとまとめにします。
ちなみにこの場合、データの中に、スペース & スペースの並びの文字列があった場合、誤作動しますので、このまとめ方には工夫が必要です。
まず、テキストデータでは使われないであろう文字の並びにする事が必要です。
さて、HTML表示は、サブルーチン html にする事にします。
だからこの処理の最後は・・・
&html;
になります。
では、サブルーチン html を書きましょう。
sub html {
#まずはデータを読み出す。
#データを含めて、HTMLを表示します。
exit;
}
こういう事になりますね。
ではまずは、データ読みだしのソースです。
open(LOGD,"logdata.dat") || die "Can't Open User Access Log: $!\n";
@lines=<LOGD>;
close(LOGD);
これで @lines には、今まで書き込みが行われたデータが全て、入れられています。
カウントのデータを取り出した時と同じですね。
では次にいよいよHTML表示したいと思います。
print <<END_OF_HTML;
<html>
<head>
<title>ぼくの掲示板</title>
</head>
<body bgcolor="#FFDDFF">
<font color="#007777">掲示板</font><br>
<hr>
<form method="post" action="index.cgi">
<input type=text name="cname" size="40"><br>
<textarea name="chat" rows="14" cols="50"></textarea><br>
<input type="submit" value="送信">
</form>
<hr>
END_OF_HTML
この部分に、引き出したデータを全て、見栄えよく表示します。
print <<END_OF_HTML;
</body>
</html>
END_OF_HTML
exit;
上記の、この部分に・・・のところのソース例を書きます。
foreach $line (@lines) {
if ($line =~ /(.*) & (.*)/) {
$cname = $1; $chat = $2;
$chat =~ s/\r/<br>/g;
print <<END_OF_HTML;
<font color="#FF0000">$cname</font><br>
$chat<br>
<hr>
END_OF_HTML
}
}
説明すると、1行目は、$line に、順次データを入れて、@lines のデータの数だけ、{ } このカッコ内を繰り返す。
2行目は、もし $line のデータが、後に示すような場合、という意味。
(.*) これは、不特定な文字列って意味です。
それが、スペース & スペースを挟んで二つあります。
もしそのような場合って意味です。
もちろんそのようにデータを保存しているわけですがら、間違いなくこれは実行されます。
3行目は、1つ目のデータは、$cname に入れ、2つ目は、$chat に入れるって意味です。
$1 は、1つ目にマッチしたデータが自動で入る便利な変数で、$2 は二番目、もしもっとあれば、$3 3番目と、ずっと続きます。
4行目は、改行コードを、HTMLの改行タグ、<br>に変更しています。
それ以降は、HTMLの出力(表示)です。
これで、超簡単な掲示板のソースがほぼ完成しました。
後は、最初のところで、送信データが無ければ、即、サブルーチンのHTMLを表示し、そうでなければデータ処理をしてから表示するようにソースを書くだけです。
完成形は以下のようになります。
#! /usr/local/bin/perl
#インタプリタ指定
#以下受信データを受け取る
if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
else { $buffer = $ENV{'QUERY_STRING'}; }
#以下、出力形式を指定
print "Content-type: text/html; charset=UTF-8\n\n";
#以下、送信されてきたデータが無ければ、即、HTML表示
if ($buffer eq "") { &html; }
#以下、受信データの処理とデコード
@pairs = split(/&/,$buffer);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/\n//g;
$FORM{$name} = $value;
}
$cname = $FORM{'cname'};
$chat = $FORM{'chat'};
$logdata = "$cname & $chat\n";
#以下、データをデータファイルに追加書き込み
open(LOGD,">>logdata.dat") || die "Can't Open User Access Log: $!\n";
print LOGD $logdata;
close(LOGD);
#以下、HTML表示
&html;
#以下、サブルーチンhtml
sub html {
open(LOGD,"logdata.dat") || die "Can't Open User Access Log: $!\n";
@lines=<LOGD>;
close(LOGD);
print <<END_OF_HTML;
<html>
<head>
<title>ぼくの掲示板</title>
</head>
<body bgcolor="#FFDDFF">
<font color="#007777">掲示板</font><br>
<form method="post" action="index.cgi">
<input type=text name="cname" size="40"><br>
<textarea name="chat" rows="14" cols="50"></textarea><br>
<input type="submit" value="送信">
</form>
<hr>
END_OF_HTML
foreach $line (@lines) {
if ($line =~ /(.*) & (.*)/) {
$cname = $1; $chat = $2;
$chat =~ s/\r/<br>/g;
print <<END_OF_HTML;
<font color="#FF0000">$cname</font><br>
$chat<br>
<hr>
END_OF_HTML
}
}
print <<END_OF_HTML;
</body>
</html>
END_OF_HTML
exit;
}
これをこのまま切り取って、拡張子 cgi で、文字コード UTF-8 で保存すれば、掲示板として動きます。
しかし、あくまで動くだけで、セキュリティは無いし、見た目もしょぼく、日付の表示もありません。
たとえば投稿できる文字数を制限したり、たとえばHTMLのタグの使用を制限したり、投稿数の最大数を制限したりしないと、悪戯されれば収拾がつきません。
だからコレをそのまま使用する事は避けてください。
とはいえ、まあこれで、基本編は終了します。
これからは、個々の関数について、Perl の色々な事について書ければと思います。
ぶっちゃけ、ココまでを理解できれば、後は書籍で勉強しても、かなり分かると思います。
まあそれでも、書ければ書くつもりですがw
では、CGI基本編終了です。