画像アップロード掲示板
#! /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=Shift_JIS\n\n); print <<END; #HTML出力 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <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; } } } }
〔 実行する 〕