画像アップロード掲示板
#! /usr/local/bin/perl
$DIR = './dat/boardimg/'; #画像保存フォルダ
$FILE = './dat/boardimg.dat'; #書込保存ファイル
$MAX = 50; #保存件数(書込・画像)
$VIEW = 10; #1ページの表示件数
$IMGMAX = 20 * 1000; #画像サイズ制限(バイト)
$TEXTMAX = 1000; #本文文字数制限(全角)
$NAMEMAX = 10; #名前文字数制限(全角)
$TITLEMAX = 20; #題名文字数制限(全角)
$PASSWORD = '1234'; #削除用パスワード
$time = time;
loadForm(); #フォームデータ取り込み
print qq(Content-type: text/html; charset=UTF-8\n\n);
print <<END; #HTML出力
<!DOCTYPE html>
<html>
<head>
<title>画像アップロード掲示板</title>
<style type="text/css">
<!--
body { padding:10px 5%; background:#efe }
form { margin:0px; text-align:left }
h1 { margin:0px; font-size:20px }
img { margin:10px 20px }
hr { height:10px; color:#9c9; background:#9c9; border-top:2px solid #393 }
textarea { width:80% }
.err { color:#f33; font-weight:bolder; text-align:center }
//-->
</style>
</head>
<body>
<h1>画像アップロード掲示板</h1>
<hr>
<form action="$ENV{'SCRIPT_NAME'}" method="POST" enctype="multipart/form-data">
名前:<input type="text" name="name" size="50" maxlength="$NAMEMAX" value="$FORM{'name'}"><br>
<br>
題名:<input type="text" name="title" size="50" maxlength="$TITLEMAX"><br>
<br>
本文:<textarea name="text" rows="10" cols="70"></textarea><br>
<small>※全角$TEXTMAX文字以内</small><br>
<br>
画像:<input type="file" name="img" value="" size="50"><br>
<small>※JPEG・GIFのみ($IMGMAXバイト以内)</small><br>
<br>
<input type="hidden" name="mode" value="write">
<input type="submit" value=" 書き込み "><br>
</form>
END
open(FILE, "<$FILE") or printError("書込保存ファイルが開けません!!"); #データ読込
eval{ flock(FILE, 1) };
@DATA = <FILE>;
close FILE;
if($FORM{'mode'}) { #書込・削除
#サンプルにつき書き込み停止
#writeData();
}
printData(); #記事出力
print <<END; #HTML出力
<hr>
</body>
</html>
END
exit;
#==============================================================================記事出力
sub printData
{
my $next = $FORM{'next'} + $VIEW;
if($next > @DATA) {
$next = @DATA;
}
print qq(<form action="$ENV{'SCRIPT_NAME'}" method="POST" enctype="multipart/form-data">\n);
for($i = $FORM{'next'} ; $i < $next ; ++$i) {
my ($tm, $name, $title, $text, $img) = split(/\t/, $DATA[$i]);
my ($sec, $min, $hour, $date, $mon, $year, $day) = localtime($tm);
print qq(<hr>\n);
printf qq(<input type="radio" name="no" value="%d">), $i;
if($title eq "") {
$title = "無題";
}
print qq(<b>【$title】 $name</b><br>);
if($img) {
print qq(<img src="$DIR$img" align="right" alt="$title">);
}
print qq($text<br clear="right">);
printf qq(<div align=right>[%02d/%02d %02d:%02d]</div>), ++$mon, $date, $hour, $min;
}
print qq(<hr>\n);
print qq(<div align="right">\n);
print qq(<input type="password" name="pass" value="$FORM{'pass'}" size="4">\n);
print qq(<input type="hidden" name="mode" value="delete">\n);
print qq(<input type="hidden" name="next" value="$FORM{'next'}">\n);
print qq(<input type="submit" value=" 削 除 ">\n);
print qq(</div>\n);
print qq(</form>\n);
if($FORM{'next'}) { #前ページへのリンク
print qq(<form action="$ENV{'SCRIPT_NAME'}" method="POST" enctype="multipart/form-data">\n);
printf qq(<input type="hidden" name="next" value="%d">\n), $FORM{'next'} - $VIEW;
print qq(<input type="submit" value=" ← 前ページ ">\n);
print qq(</form>\n);
}
if($next < @DATA) { #次ページへのリンク
print qq(<form action="$ENV{'SCRIPT_NAME'}" method="POST" enctype="multipart/form-data">\n);
print qq(<input type="hidden" name="next" value="$next">\n);
print qq(<input type="submit" value=" 次ページ → ">\n);
print qq(</form>\n);
}
}
#==============================================================================書込・削除
sub writeData
{
my $img;
if($FORM{'mode'} eq 'write') { #データ追加
if($FORM{'text'} and length($FORM{'text'}) <= $TEXTMAX * 2
and length($FORM{'name'}) <= $NAMEMAX * 2
and length($FORM{'title'}) <= $TITLEMAX * 2 ) {
if($FORM{'img'}) {
$img = writeImg(); #画像アップロード
}
unshift @DATA, "$time\t$FORM{'name'}\t$FORM{'title'}\t$FORM{'text'}\t$img\t\n";
while(@DATA > $MAX) { #書込保存件数チェック
deleteImg(@DATA - 1); #画像削除
pop @DATA; #書込削除
}
opendir(DIR, $DIR) or printError("画像保存フォルダが開けません!!");
my @IMG = readdir(DIR);
closedir(DIR);
while(@IMG > $MAX + 2) { #画像保存枚数チェック
@IMG = sort @IMG;
unlink ($DIR . @IMG[2]); #画像削除
splice @IMG, 2, 1;
}
}
else {
printError("文字数オーバーまたは本文が空白です!!");
}
}
elsif($FORM{'mode'} eq 'delete') { #データ削除
if($FORM{'no'} ne "") {
if($FORM{'pass'} eq $PASSWORD) {
deleteImg($FORM{'no'}); #画像削除
splice @DATA, $FORM{'no'}, 1; #書込削除
}
else {
printError("削除パスワードが違います!!");
}
}
}
open(FILE, ">$FILE"); #データ書き込み
eval{ flock(FILE, 2) };
print FILE @DATA;
close FILE;
}
#==============================================================================画像書込
sub writeImg
{
my @filename = split(/\./, $FORM{'filename'});
$filename[@filename - 1] =~ tr/A-Z/a-z/;
if(length($FORM{'img'}) > $IMGMAX) {
printError("画像サイズオーバー!! (" . length($FORM{'img'}) . "バイト)");
}
elsif($filename[@filename - 1] eq "jpg" or $filename[@filename - 1] eq "gif") {
my $img = $time . "\." . $filename[@filename - 1];
my $filename = $DIR . $img;
open(IMG1, ">$filename") or printError("ファイル作成に失敗しました!!");
binmode(IMG1);
print IMG1 $FORM{'img'};
close(IMG1);
return $img;
}
else {
printError("$FORM{'filename'}はアップロードできません!!");
}
}
#==============================================================================画像削除
sub deleteImg
{
my ($tm, $name, $title, $text, $img) = split(/\t/, $DATA[$_[0]]);
$img = $DIR . $img;
if(-e $img) {
unlink $img;
}
}
#==============================================================================エラー出力
sub printError
{
print <<" END";
<hr>
<div class="err">【エラー】$_[0]</div>
END
printData();
print <<" END";
<hr>
</body>
</html>
END
exit;
}
#==============================================================================フォームデータ取込
sub loadForm
{
my ($query, $pair);
if($ENV{'REQUEST_METHOD'} eq 'POST') {
read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
}
my ($split) = split(/\x0D\x0A/, $query);
foreach $pair (split(/$split/, $query)) {
my @query = split(/\x0D\x0A/, $pair);
if($query[1] =~ /name="(\w+)"/) {
for($i = 3 ; $i < @query ; $i++) {
if($FORM{$1}) {
$FORM{$1} .= "\x0D\x0A";
}
$FORM{$1} .= $query[$i];
}
if($query[1] =~ /(filename)="(.+\.\w+)"/) {
$FORM{$1} = $2;
}
else {
$FORM{$1} =~ tr/\t/ /;
$FORM{$1} =~ tr/</ /;
$FORM{$1} =~ tr/>/ /;
$FORM{$1} =~ s/\x0D\x0A/<br>/g;
}
}
}
}
〔 実行する 〕