#!/usr/bin/perl
#↑パールのアドレス(@ニフティ#!/usr/local/bin/perl)(インフォウェブ#!/usr/bin/perl)必ずあなたの使用しているサーバーのパールの場所を指定します。
#このプログラムの著作権はKXコンピューターシステムズにあります。
#無断使用、コピーはお断りします。このプログラムは無料で配布しています。
#このプログラムの使用に際して、問題があっても一切の保障はできません。
#gazobbs.cgi ver.5.0B 2003.7.26
#一部変更 一部の環境で背景画像が表示されない件をFIX 2003.5.24
#クッキー、削除キー対応、 2003.7.27
#Copyright (c) 2002 KX Computer Systems & Edward Carr, All Rights Reserved
#http://www.kx777.com/
#ディレクトリとファイルのパーミッション
# CGIのディレクトリ(755 or 777)-gazocgi
# -lock ロックファイルのディレクトリ(777)
# -img1 投稿された画像を入れておくディレクトリ(777)
# -gazobbs.cgi(755)
# -gazobbs.log(666)
# -jcode.pl(755)
# -cgi-lib.pl(755)
# -img.cgi(755)
# 背景画像とメール、ホームページアイコンのディレクトリ(755)-gazoimg
# -bbscat1.gif(644) 記事脇の画像(お好きなものに変更してください)
# -mail.gif(644)
# -home.gif(644)
#
# 下のURLなどをあなたの実際のURLに変更してください。
# ファイル名も変更してください。このプログラムの文字だけでなく、
# 実際のファイルも名前を変えてください。
#************************************************************************
#パソコンからインターネットに読み込むためのCGIライブラリ
require "./cgi-lib.pl";
#画像の制限サイズ(byte 20000なら20Kバイト)
$image_max = 60000;
#投稿を許可する(管理者専用とするか?)
$kyoka=1;#1は許可、1以外は不許可
##############★重要
$nifty_flg=1;#@ニフティなどCGI用のディレクトリに画像を置くと普通は読めないサーバの場合1にその他のサーバは0に設定してください。1の時はimg.cgiの設定もしてください。(たいてい、Apacheのデフォルトの設定では/cgi-bin/のファイルは、すべて実行ファイルとなるので注意してください。)
#この設定を有効にすると、1画像につき1つの読み出し用プログラムを呼び出すことになるので、重くなります。
##############★
$admin_name = 'KX'; # あなたの名前(ハンドルネーム)
$admin_email = 'nashiyo@nainai.come'; # あなたのメールアドレス
$master = 'aaaa'; # 管理用のパスワード 2つ設定できます。
$master2 = 'AAAA'; # 管理用のパスワード2 2つとも必ず変えておくこと。
#管理者の入り口は画面の一番したにあります。
$bbs_title = "\画\像\掲\示\板\べ\ー\だ!";#タイトル 漢字の前は\がお勧め。
$back_url = "http://anatano/anatano/index.htm"; #HOME(あなたのホームページに換える)
$image_url = "../gazoimg/"; # 背景画像があるURL(@ニフティなどでは絶対URL)
##$image_url = "http://homepage2.nifty.com/nantara-kantara/"; # @ニフティの例
$back_img=""; #背景の画像名
$back_img2="bbscat1.gif"; #記事の脇の背景
$body_text = '#ffffff'; #
タグの設定
$body_link = '#ff0000';
$body_alink = '#ff0000';
$body_vlink = '#ff0000';
$body_bgcolor = '#000000';
$body=<<"_EOF_";
_EOF_
$page = 10;# 1ページに表示する記事数
# ファイル関連の設定
$tz = "JST-9";# TimeZone
$cginame = 'gazobbs.cgi'; # この CGI のファイルの名前
$ENV{'SCRIPT_NAME'} = "./gazobbs.cgi";#このCGIの場所
$jcode= './jcode.pl';# jcode.pl のある場所
$logfile = './gazobbs.log'; # 記録用ファイル名(絶対に変えておくこと)
$lock1= './lock/gazobb1.lock'; # 鍵ファイル(1)
$lock2= './lock/gazobb2.lock'; # 鍵ファイル(2)
$lock_flag = 1; # 鍵ファイルの 1:使用 0:不使用
# -------------------- # 色
#記事部の一番外の背景色
$bgcol="#333333";
#わく線の色
$bgcol2="red";
#記事タイトルの色
$bgcol3="#ffffff";
#記事タイトルの背景色
$bgcol4="black";
#掲示板タイトルの色
$bgcol5="black";
#掲示板タイトルの背景色
$bgcol6="white";
# -------------------- # タイトル部分の HTML文
$html_title=<<"_EOF_";
\n";
}
###########
#表示処理
###########
###########
#記事の表示処理2
###########
###########
#ページ計算処理
###########
sub html_body {
local($start,$end) = &page_log;
for ($i = $start;$i<$end;$i++) {
($date,$title,$img_flg,$img_fl_nam,$subname,$formdata3,$formdata4,$message,$host,$delkey) = &get_data($logs[$i]);
if ($FORM{'pass'} eq $master || $FORM{'pass'} eq $master2) {
print "
\n";
}
# $date = &get_weekly_date($date);
&html_format($date,$title,$img_flg,$img_fl_nam,$subname,$formdata3,$formdata4,$message,$host,$delkey);
}
}
###########
#ページ計算処理
###########
sub page_log { # ページを設定
local($start,$end);
$start = $FORM{'start'}; $end = $start + $page;
if ($start < 0) { $start = 0; }
if ($start > @logs) { $start = @logs; }
if ($end < 0) { $end = 0;}
if ($end > @logs) { $end = @logs; }
print "\n";
$temp = $start-$page;
if ($start>0) { print "前ページ▲ "; }
else { print "△"; }
$temp = $start+$page;
if ($end<=$#logs) { print "次ページ▼ "; }
else { print "▽"; }
return ($start,$end);
}
###########
#記事の表示処理
###########
sub html_format {#記事の表示
($date,$title,$img_flg,$img_fl_nam,$subname,$formdata3,$formdata4,$message,$host,$delkey) = @_;
#自動リンク
$message =~ s/(http:\/\/[\w\$\#\~\.\/\-\?\=\&\:\%]+)/$1<\/a>/g;
$message =~ s/(ftp:\/\/[\w\$\#\~\.\/\-\?\=\&\:\%]+)/$1<\/a>/g;
#名前、記事
print<<"_EOF_";
_EOF_
}
###########
#ログを変数に代入する処理
###########
sub get_data {
local($date,$title,$img_flg,$img_fl_nam,$subname,$formdata3,$formdata4,$message,$host,$delkey) = split(/<>/,$_[0]);
$message =~ s/\n//;
return ($date,$title,$img_flg,$img_fl_nam,$subname,$formdata3,$formdata4,$message,$host,$delkey);
}
###########
#曜日計算処理
###########
sub get_weekly_date {
local($date) = $_[0];
local($year,$mon,$day,$week) = (substr($date,0,4),substr($date,4,2),substr($date,6,2),0);
if ($mon < 3) { $year--; $mon += 12; }
$week = (int($year) + int($year/4) - int($year/100) + int($year/400) + int(($mon*13+8)/5) + $day) % 7;
local($year,$mon) = (substr($date,0,4),substr($date,4,2));
$date = $year."/".$mon."/".$day."($hiduke[$week])";
return $date;
}
###########
#投稿用の入り口ボタンを表示する処理
###########
sub html_sub {
if($kyoka eq 1){
print<<"_EOF_";
_EOF_
}
}
###########
#管理者用の入り口を表示する処理
###########
sub html_adminenter {
print<<"_EOF_";
_EOF_
}
###########
#管理者が削除する画面を表示する処理
###########
sub html_editor {
&editor_edit;
if ($nengappi == 0) {
($year,$mon,$day) = &get_date;
} else {
($year,$mon,$day) = (substr($nengappi,0,4),substr($nengappi,4,2),substr($nengappi,6,2))
}
if ($year.$mon.$day eq (split(/<>/,$_))[0]) {
($date,$title,$img_flg,$img_fl_nam,$subname,$formdata3,$formdata4,$message,$host,$delkey) = &get_data($_);
$message =~ s/
/\n/g;
}
$kiji = @logs;
$size = (stat($logfile))[7];
print<<"_EOF_";
_EOF_
}
###########
#投稿用が終わったら元の画面を表示する処理
###########
sub html_done {
&editor_edit;
print "Location: $ENV{'SCRIPT_NAME'}\n\n";
}
###########
#投稿用の入力画面を表示する処理
###########
sub html_submit {#訪問者書き込みの画面
##くっきーを頂きます。
$cooks = $ENV{'HTTP_COOKIE'};
$cooks = '' unless($cooks =~s/.*carrbbsdata=(.*)carrend.*/$1/);
($cookname,$cookemail,$cookurl,$cookcolor,$cookdate,$count,$cooknekogao,$ckey,$dum) = split(/<>/, $cooks);
$histry = "$count回目:LAST LOGIN:$lastdate" if($lastdate);
if(!$count){ #くっきー情報の無い場合のデフォルト値
$color = 'red';$count = 1;$nekogao = './neko0.gif';
}
#getcookie END
($year,$mon,$day) = &get_date;
$image_s=$image_max/1000;
print<<"_EOF_";
_EOF_
}
###########
#投稿された内容をチェックし書き出す処理
###########
sub editor_edit {
if ($FORM{'message'} ne '') {
if ($FORM{'year'}< 1583 || $FORM{'year'}> 9999) { return; }
if ($FORM{'mon'}< 1 || $FORM{'mon'}> 12) { return; }
if ($FORM{'day'}< 1 || $FORM{'day'}> (0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[$FORM{'mon'}]) { return; }
if ($FORM{'mon'} == 2 && $FORM{'day'} == 29) {
if (($FORM{'year'} % 4 != 0 && $FORM{'year'} % 100 == 0) || ($FORM{'year'} % 400 != 0)) { return; }
}
$FORM{'mon'} = substr("0$FORM{'mon'}",length($FORM{'mon'})-1,2);
$FORM{'day'} = substr("0$FORM{'day'}",length($FORM{'day'})-1,2);
$times = time;#18時間時差があるなら、$times = time+18*60*60とする。
($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime($times);
$min = "0$min" if ($min < 10); $month++;
$youbi = ('日','月','火','水','木','金','土') [$wday];
$date = $FORM{'year'}.$FORM{'mon'}.$FORM{'day'};
$date2 = $FORM{'year'}.$FORM{'mon'}.$FORM{'day'}."($youbi)$hour:$min";
$FORM{'message'} =~ s/\r\n/
/g;
$FORM{'message'} =~ s/\r|\n/
/g;
#画像出力
#サイズエラー検出
if (length($in{'IMAGE'}) > $image_max) { &Error("サイズオーバー","画像は$image_maxバイト以内にしてください."); }
foreach (@in) {
($fname) = $_ =~ /\bfilename="([^"]*)"/i;
($fname) = $_ =~ /\bfilename=([^\s:;]+)/i unless defined $fname;
if ($fname eq '') { next; }
($name) = $_ =~ /\bname="([^"]+)"/i;
($name) = $_ =~ /\bname=([^\s:;]+)/i unless defined $name;
($ctype) = $_ =~ /\s*Content-type:\s*"([^"]+)"/i;
($ctype) = $_ =~ /\s*Content-Type:\s*([^\s:;]+)/i unless defined $ctype;
unless ($ctype =~ /^image/i) { &error('エラー',"この画像ファイルは使用できません。"); }
if ($ctype eq '') { &error('エラー',"$fnameはContent-Typeが認識できないために受付できません."); }
if ($name =~ /IMAGE/) {
$fname = reverse("$fname");
($fname) = split(/\\|\/|\:/,$fname);
$fname = reverse("$fname");
($fname,$ext) = split(/\./,$fname);
$ext1 = $ext; $ext2 = '';
$randtime=time;
if (!open(IMAGE,"> ./img1/$date$randtime$ext2\.$ext")) { &Error('書出エラー',"画像データ ./img1/$date$randtime$ext2\.$ext が記録できませんでした."); }
binmode(IMAGE);
print IMAGE $in{$name};
close(IMAGE);
$f_n="./img1/$date$randtime$ext2\.$ext";
chmod(0666,"./img1/$date$randtime$ext2\.$ext");
}
}
if($f_n ne ''){
$img_flg = "1";
}else{$img_flg = "0"}
$host = $ENV{'REMOTE_HOST'};
push(@new,"$date2<>$FORM{'title'}<>$img_flg<>$date$randtime$ext2\.$ext<>$FORM{'subname'}<>$FORM{'formdata3'}<>$FORM{'formdata4'}<>$FORM{'message'}<>$host<>$FORM{'123key'}<>\n");
#くっきーをブラウザにプレゼントします。
local($dmy,$mdc,$monc,$yrc,$wdayc,$mc,$yc);
($dmy,$dmy,$dmy,$mdc,$monc,$yrc,$wdayc,$dmy,$dmy) = localtime($times + 7776000);
$yc = ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday') [$wdayc];
$mc = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec') [$monc];
$yrc = $yrc+1900; $mdc = "0$mdc" if ($mdc < 10);
$count++;
$data = "$FORM{'subname'}<>$FORM{'formdata3'}<>$FORM{'formdata4'}<>$FORM{'color'}<>$date2<>$count<>$FORM{'nekogao'}<>$FORM{'123key'}<>carrend";
print "Set-Cookie: carrbbsdata=$data; expires=$yc, $mdc-$mc-$yrc 00:00:00 GMT\n";
#このクッキーはだいたい3ヶ月間有効です。
}#if
#削除処理
($del1,$del2)=split(/:#/,$FORM{'del'});
foreach $data (@logs) {
local($datex,$title,$img_flg,$img_fl_nam,$subname,$formdata3,$formdata4,$message,$host,$delkey) = split(/<>/,$data);
if ($del1 eq $title && $del2 eq $datex && ($FORM{'pass'} eq $master || $FORM{'pass'} eq $master2 || $FORM{'pass'} eq $delkey)) {#1
if($img_flg eq 1){unlink("./img1/$img_fl_nam");}
next;
}#1
push (@new,$data);
}
@logs = &write_file($logfile,@new);
undef @new;
}#END
###########
#ファイル読み込み処理
###########
sub read_file {#
local($logfile) = $_[0];
if (!open(IN,$logfile)) {
&error(1,"記録ファイルの読み込み不可");
}
local(@files) = ;
close(IN);
return @files;
}
###########
#ファイル書き出し処理
###########
sub write_file {
#出力
local($logfile,@lines) = @_;
&dubble_lock_file;
if ($lock_error) { &error(1,"ロックファイルを検出しました。時間をおいてご利用下さい。"); }
if (!open(OUT,">$logfile")) {
&dubble_unlock_file;
&error(1,"記録ファイルの書き込み不可");
}
print OUT @lines;
close(OUT);
&dubble_unlock_file;
return @lines;
}
###########
#ファイルロック処理
###########
sub dubble_lock_file {
if($lock_flag){
if (!(&lock_file($lock1))) { &dubble_unlock_file; }
elsif (!(&lock_file($lock2))) { &dubble_unlock_file; }
}}
sub dubble_unlock_file {
if($lock_flag){
&unlock_file($lock2);&unlock_file($lock1);
}}
sub lock_file {
if($lock_flag){
local($lockfile) = $_[0];
if (!$lock_flag) { return 1; }
local($retry) = 5;
while (-f $lockfile) {
if ($retry-- <= 0) {
local($mtime) = (stat($lockfile))[9];
if ($mtime < time()-60*15) { return 0; }
$lock_error = 1;
return 1;
}
sleep 1;
}
open (LOCK,">$lockfile");
close(LOCK);
return 1;
}}
sub unlock_file {
if($lock_flag){
local($lockfile) = $_[0];
unlink($lockfile);
}}
###########
#日付の処理2
###########
sub get_date {
$ENV{'TZ'} = $tz;
local($sec,$min,$hour,$day,$mon,$year) = localtime(time);
if ($hour < 12) {
local($sec,$min,$hour,$day,$mon,$year) = localtime(time-12*60*60);
}
$mon++;
if ($mon < 10) { $mon = "0$mon"; }
if ($day < 10) { $day = "0$day"; }
if ($year < 99) { $year += 100; }
$year += 1900;
return ($year,$mon,$day);
}
###########
#フォームからの読み込み処理
###########
sub GetQuery {
$cmd = $ENV{'QUERY_STRING'};
@pairs = split(/&/,$cmd);
foreach $pair (@pairs) {
($key,$val) = split(/=/,$pair);
$val =~ tr/+/ /;
$val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
$cmd{$key} = $val;
}#foreach
}
sub GetData {
&ReadParse;
while (($key,$val) = each %in) {
#イメージスキップ
if ($key eq 'IMAGEs' || $key eq 'IMAGE') { next; }
#コード変換
&jcode'h2z_sjis(*val);
&jcode'convert(*val,'sjis');
#改行変換
$val =~ s/\t//g;
$val =~ s/\r\n/\r/g;
$val =~ s/\n/\r/g;
#タグ禁止
$val =~ s/&/&/g;
$val =~ s/"/"/g;
$val =~ s/</g;
$val =~ s/>/>/g;
#変数代入
$in{$key} = $val;
$FORM{$key} = $val;
if ($key eq 'edit') { $nengappi = $val; }
}
}
sub Error {
#エラー処理
unlink($lockfile);
local (@msg) = @_;
local ($i);
&html_header;
print <<"EOF";
$body
$msg[0]
EOF
if ($msg[1] ne '') {
print "\n";
foreach $i (1 .. $#msg) { print "- $msg[$i]\n"; }
print "
\n";
}
print <<"EOF";