B02:掲示板に画像を表示する
プロバイダが用意したCGIを置く領域にあるファイルは、直接アクセスしても読み込む事ができない場合があります。
しかし、CGIで出力したページに画像などを表示したい場合もあります。
今回は、掲示板に画像を表示するようなCGIを紹介します。
単純にファイルを置く場所を分けているだけですが、気付かないと意外につまづいてしまいます。
ファイルを開く
解説
#!/usr/local/bin/perl
プロバイダがPerlを置いている場所を記述します。
ここでは/usr/local/bin/perlにあるとしています。
#このファイルのURL
$url="sample.cgi";
CGIファイル自身のURLを$urlに代入しています。
#画像ファイルを置いてあるURL
$picture[0]="sample1.png";
$picture[1]="sample2.png";
$picture[2]="sample3.png";
$picture[3]="sample4.png";
$picture[4]="sample5.png";
掲示板で表示する画像のURLを$picture[xx]に代入しています。
これらのファイルはCGIから出力するのではなくHTMLで表示するので、HTMLファイルと同じ場所に置いてある必要があります。
☆今回のポイント☆
CGIからアクセスするファイルとHTMLからアクセスするファイルの置き場所に気を付けよう!
$weekchar[0]="(Sun)";
$weekchar[1]="(Mon)";
$weekchar[2]="(Tue)";
$weekchar[3]="(Wed)";
$weekchar[4]="(Thu)";
$weekchar[5]="(Fri)";
$weekchar[6]="(Sat)";
CGIで取得できる曜日のデータは数字なので、変換する文字列を$weekchar[xx]に代入しています。
$a=$ENV{'QUERY_STRING'};
@b=split(/&/,$a);
foreach $c (@b) {
($d, $e) = split(/=/, $c);
$e =~ tr/+/ /;
$e =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg;
$e =~ s/&/&amp/g;
$e =~ s/"/&quot/g;
$e =~ s/</&lt/g;
$e =~ s/>/&gt/g;
$e =~ s/\r\n/\n/g;
$e =~ s/\r/\n/g;
$e =~ s/\n/\<br>/g;
$FORM{$d} = $e;
}
このCGIではGET方式で投稿データ渡してもらっていますが、GET方式はデータをURLの一部に変換してくっつける方法なので、データを元の状態に戻しています。
その際、HTMLで表示できない特殊文字や改行コードの変換なども行っています。
$title=$FORM{'title'};
$name=$FORM{'name'};
$message=$FORM{'message'};
$number=int($FORM{'number'});
元の状態に戻したデータを、それぞれの変数に代入しています。
$year=(localtime(time))[5]+1900;
$month=(localtime(time))[4]+1;
$today=(localtime(time))[3];
$week=(localtime(time))[6];
$hour=(localtime(time))[2];
$min=(localtime(time))[1];
投稿された時間を掲示板に表示するので、時刻のデータを変数に代入しています。
if($FORM{'title'} ne ""){
if($FORM{'name'} ne ""){
if($FORM{'message'} ne ""){
掲示板に入力された、題名、名前、メッセージのいずれも空でなかった時のみ、この条件文の中にある処理を行います。
open(OUT,"<message.dat");
open(IN,">message.tmp");
$i=1;
while($data=<OUT>){
print IN "$data";
$i++
}
close(OUT);
close(IN);
message.datからmessage.tmpにデータを移しています。
message.datには投稿されたデータの一件が一行として保存されています。
open(OUT,"<message.tmp");
open(IN,">message.dat");
print IN "<hr>[$i]";
print IN "<font color=\"green\">$title</font>:";
print IN "<font color=\"blue\">$name</font>:";
print IN "<font color=\"red\">$year/$month/$today$weekchar[$week]$hour:$min</font>";
print IN "<br><img src=\"$picture[$number]\"><br>$message\n";
while($data=<OUT>){
print IN "$data";
}
close(OUT);
close(IN);
投稿されたデータを保存してから、message.tmpに移してあったデータをmessage.datに戻しています。
つまり、message.datの一行目に新しいデータが追加された事になります。
printf("Location:$url\n\n");
このCGIが呼び出された時にデータが存在したという事は、URLの後ろに変換されたデータがくっついているという事です。
そのままだと、リロードされた時などに同じデータが投稿されたと判断してしまうので、このCGI自身に移動しています。
こうすると、URLの後ろに余分なデータが付いていない状態になります。
exit;
}
}
}
一つ上の処理でこのCGI自身に移動しているので、一旦、プログラムを終了させます。
このCGIが呼び出された時にデータが存在しなかった場合は、ここから下の処理が実行されます。
printf("Content-type:text/html\n\n");
printf("<html>\n<head>\n<title>掲示板</title>\n</head>\n<body>\n");
printf("<form method=\"get\" action=\"$url\">\n");
printf("気分:\n");
printf("<input type=\"radio\" name=\"number\" value=\"0\" checked><img src=\"$picture[0]\">\n");
printf("<input type=\"radio\" name=\"number\" value=\"1\"><img src=\"$picture[1]\">\n");
printf("<input type=\"radio\" name=\"number\" value=\"2\"><img src=\"$picture[2]\">\n");
printf("<input type=\"radio\" name=\"number\" value=\"3\"><img src=\"$picture[3]\">\n");
printf("<input type=\"radio\" name=\"number\" value=\"4\"><img src=\"$picture[4]\"><br>\n");
printf("題名:<input type=\"text\" name=\"title\"><br>\n");
printf("名前:<input type=\"text\" name=\"name\"><br>\n");
printf("メッセージ:<br>\n");
printf("<textarea name=\"message\" cols=\"50\" rows=\"10\"></textarea><br>\n");
printf("<input type=\"submit\" value=\"投稿\"></form>\n");
printf("通常は最新の10件を\表\示しています。<br>\n");
printf("<a href=\"$url?all\">全てのメッセージを\表\示</a>\n");
掲示板の上の方にある投稿内容を入力する部分を出力しています。
最後の行に、このCGIのURLに?allという文字列をくっつけた場所にリンクを貼っています。
URLにくっついている?から後ろの部分は、$ENV{'QUERY_STRING'}とすればCGIから取得できます。
HTMLのformに入力されたデータをGET方式でCGIに送ると自動的に変換されてURLの後ろに付くのですが、このようにリンクする時にに直接書いてもCGIにデータを渡す事ができます。
このCGIではallという文字列が渡された場合、投稿された全てのメッセージを表示します。
allという文字列が渡されなかった場合は、最新の10件のみ表示します。
$i=1;
open(OUT,"){
if($i<=10){
printf("$data");
}else{
if($a eq "all"){
printf("$data");
}
}
$i++;
}
close(OUT);
掲示板に投稿されて保存してあるデータを出力しています。
allという文字列が渡された場合は全部、渡されなかった場合は10件のみ出力しています。
printf("</body>\n</html>\n");
掲示板の最後の部分を出力しています。
exit;
プログラムを終了させます。