#! /usr/local/bin/perl
#----------------#
# 初期設定 #
#----------------#
# 掲示板の名前 --------------------------
$title = 'あやしいわーるどREQUIEM';
# 文字色や背景などの設定
# body部
$bgc = '004040';
$textc = 'ffffff';
$linkc = 'eeffee';
$vlinkc = 'dddddd';
$alinkc = 'ff0000';
# 題名の色
$subjc = 'ffffee';
# --- 表示件数 --------------------------------------------
# 1ページに表示する件数のデフォルト値
$def = 30;
# 1ページに表示する件数の最小値
$defmin = 0;
# この件数以上でリロード/書き込みしたときには次はこの件数にする。
$defmax =300;
# --- URL ----------------------------------------------
# このスクリプト
$cgiurl = 'bbs.cgi';
# 連絡先
$mailadd = 'goodby@strangers.com';
# ログのURL
$loglog0 = 'log';
$loglog1 = 'http://';
# ---------------------------------------- 書き込みチェック ----------------------------------------
# 管理人名前チェック・メールアドレス・パスワード
$namez = 'しば';
$pass = 'chiba';
# 書き込み最大量
$maxlength = 1024*16;
#投稿内容文字数
$max_v = 8000;
#投稿内容行数(上の文字数との兼ね合いを考えて)
$max_line = 120;
# 二重書き込みチェック件数
$check = 10;
# 二重書き込みチェックバイト数
$checklength = 10;
# 書き込み件数の最大登録数の設定
$max = '300';
# ------------------------------------ ディレクトリ・ファイル名 ------------------------------------
# 日本語コード変換ライブラリjocde.plのパス
require './jcode.pl';
# 内容が書き込まれる記録ファイルのパスを設定
$file = './loveyou.dat';
# 別途とるログのファイル名先頭文字・拡張子の指定
$logfile = "./log/";
$logfiledat = ".html";
# -------------------------------------------- カウンタ --------------------------------------------
# カウンタプラス値
$countplus = "";
# カウンタ開始日
$countdate = '99/6/20';
# カウンタファイルの先頭文字・拡張子の指定
$countfile = './count/count';
$countfiledat = '.txt';
# カウンタ強度(0のときは使用しない)
$countlevel = 3;
# --------------------------------------------- その他 ---------------------------------------------
# 時差
$tim =0*3600;
# 入力形式の設定
$method = 'post';
# 時刻処理
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time + $tim );
$month = ($mon + 1);
# 時刻のゼロサプレス
if ($month < 10) { $month = "0$month"; }
if ($mday < 10) { $mday = "0$mday"; }
if ($sec < 10) { $sec = "0$sec"; }
if ($min < 10) { $min = "0$min"; }
if ($hour < 10) { $hour = "0$hour"; }
# 曜日変換処理
$y0="日"; $y1="月"; $y2="火"; $y3="水"; $y4="木"; $y5="金"; $y6="土";
$youbi = ($y0,$y1,$y2,$y3,$y4,$y5,$y6) [$wday];
# 時刻フォーマット
$date_now = "$month月$mday日($youbi)$hour時$min分$sec秒";
# ログファイル名取得
$filedate = "$logfile$year$month$mday$logfiledat";
# よくわからない変数
$gesu = $ENV{'REMOTE_PORT'};
# 投稿時のaction名
$action = "regist";
# 追加対策 -------------------------------
# 外部投稿防止コード
$protect_a = 9987; # 4桁
$protect_b = 55; # 2桁
$protect_c = 112; # 3桁
# 過去ログの最大ファイルサイズ
$maxoldlogsize = 3 * 1024 * 1024; # 3MB
###########################################################################################
# フォーム入力されたデータを$bufferに格納する(getかpostかによって取得方法が異なる)
#if ($ENV{'REQUEST_METHOD'} eq "POST" && $ENV{'CONTENT_LENGTH'} < $maxlength) { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
#else { $buffer = $ENV{'QUERY_STRING'}; }
if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; }
if ($ENV{'CONTENT_LENGTH'} > $maxlength) {&error(5);}
# $bufferに格納されたFORM形式のデータを取り出す
@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;
# 記録するデータはsjis
&jcode'convert(*value,'sjis');
#改行連打のいたずらを回避(3行以上何も書かずに改行のみの部分は改行無視)
#スペース+改行の連打を回避(上記を回避するためにスペースをいれて改行する悪戯の場合)
if ($value =~ /\r\n/) { $value =~ s/\r\n/\r/g; }
if ($value =~ /\n/) { $value =~ s/\n/\r/g; }
if ($value =~ / \r \r/) { $value =~ s/ \r \r//g; }
if ($value =~ /\ \r\ \r/) { $value =~ s/\ \r\ \r//g; }
if ($value =~ / \r/) { $value =~ s/ \r/\r/g; }
if ($value =~ /\ \r/) { $value =~ s/\ \r/\r/g; }
if ($value =~ /\r\r\r\r/) { $value =~ s/\r\r\r\r//g; }
# 処理の都合上の処理
$value =~ s/\n//g; # 改行文字は消去
if ($name eq 'value') { $value =~ s/&/&\;/g; $value =~ s/\,/\0/g; }
elsif ($name ne 'page' && $name ne 'image') { $value =~ s/\,//g; $value =~ s/\;//g; $value =~ s/\://g; $value =~ s/\=//g; }
else { $value =~ s/\,//g; }
$value =~ s/<\;/g; $value =~ s/>/>\;/g;
$FORM{$name} = $value;
}
# 表示ページ数の決定 ##################################################
if ($FORM{'def'} ne '') { $def = $FORM{'def'}; }
if ($def < $defmin) { $def = $defmin;}
$defnext = $def;
if ($defnext > $defmax) {$defnext = $defmax;}
# 表示色の決定 ########################################################
if ($FORM{'bgcolor'} ne '') { $bgc = $FORM{'bgcolor'}; }
$body = "
";
# ポップアップウインドウの決定 ########################################################
#if ($FORM{'image'} eq '') { $checked1='checked'; }
#if ($FORM{'image'} eq '2') { $checked2='checked'; }
#if ($FORM{'himage'} eq '') { $himage=''; }
#if ($FORM{'himage'} eq '2'){ $link='$sec$min'; }
# 全体の流れを決定する(actionやpwdはフォーム入力されたデータを格納する名前)
########################################################
# action=regist --> 記事記録処理して通常画面へ
# その他 --> 通常画面へ
if (($FORM{'def'} eq '0') && ($FORM{'value'} ne '')) { ®ist; }
if ($FORM{'def'} eq '0') { &read; }
if ($FORM{'action'} eq "$action") { ®ist; }
if ($FORM{'action'} eq 'search1') { &search1; }
if ($FORM{'action'} eq 'search2') { &search2; }
if ($FORM{'action'} eq 'search3') { &search3; }
&html;
# メイン表示サブルーチン #######################################################
sub html {
# プロテクトキー生成
local ( $ptime ) = time + $tim * 60 * 60;
local ( $pkey ) = ( $ptime + $protect_a ) * $protect_b + $protect_c;
print "Content-type: text/html\n\n";
print "$title\n";
print "$body\n";
# バナーはここ
print "$title \n";
print "おしらせページ \n";
print " スワティ\n";
#print "連絡先\n";
print "\n";
#--- 記録記事の出力 ----------------------------------#
# 記録ファイルを読み出しオープンして、配列<@lines>に格納する
if (!open(DB,"$file")) { &error(0); }
@lines = ;
close(DB);
if ($FORM{'page'} eq '') { $page = 0; } else { $page = $FORM{'page'}; }
$accesses = @lines; $accesses--;
$page_end = $page + $def - 1;
if ($page_end > $accesses) { $page_end = $accesses; }
foreach ($page .. $page_end) {
($date,$name,$email,$value,$subject,$hpage,$himage,$code,$postid) = split(/\,/,$lines[$_]);
$value =~ s/\0/\,/g; # ヌルコードに変換記録した半角カンマを復帰させる
chop($himage) if $himage =~ /\n/;
chop($hpage) if $hpage =~ /\n/;
chop($postid) if $postid =~ /\n/;
&disp;
}
#--- 改ページ処理 ------------------------------------#
print "
\n";
$page_next = $page_end + 1;
$i = $page + 1; $j = $page_end + 1;
if ($page_end ne $accesses) {
print "以上は、現在登録されている新着順$i番目から$j番目までの記事です。
\n";
print "
\n";
}
else {
print "以上は、現在登録されている新着順$i番目から$j番目までの記事です。";
print "これ以下の記事はありません。\n";
}
# このスクリプトの著作権表示(かならず表示してください)
print "\n";
print "\n";
print "\n";
exit;
}
# 書き込み処理サブルーチン ############################################################
sub regist {
# 内容がスペースならリロード
if ($FORM{'value'} eq "") { &html; }
# 別のページからこのCGIへの投稿を排除する処理
$ref = $ENV{'HTTP_REFERER'};
$ref_url = $cgiurl; $ref_url =~ s/\~/.*/g;
if (!($ref =~ /$ref_url/i)) { &error(form); }
# 入力されたデータのチェック ##################################
if ($FORM{'bgcolor'} eq "") { &error(1); }
if ($FORM{'def'} eq "") { &error(1); }
if ($FORM{'win_time'} eq "") { &error(1); }
if ($FORM{'win_count'} eq "") { &error(1); }
if ($FORM{'name'} eq "") { $FORM{'name'} = ''; }
if ($FORM{'email'} =~ /,/) { &error(4); }
$FORM{'email'}=~ s/\"//g;
if ($FORM{'email'} ne "") { if (!($FORM{'email'} =~ /(.*)\@(.*)\.(.*)/)) { &error(3); }}
if ($FORM{'subject'} eq "") { $FORM{'subject'} = ' '; }
if ($FORM{'page'} eq "" || $FORM{'page'} eq "http://") { $FORM{'page'} = ''; }
else{
$FORM{'page'} =~ s/\s//g;$FORM{'page'} =~ s/\"//g;$FORM{'page'} =~ s/\'//g;
$FORM{'page'} =~ s/http\:\/\/http\:\/\//http\:\/\//g;
}
# 行数制限
if ($max_line) {
$value_size = ($FORM{'value'} =~ tr/\r/\r/) + 1; # \r の数を数える
if ($value_size > $max_line) { &error(1); }
}
# 文字数制限
if ($max_v) {
$value_size = length($FORM{'value'});
if ($value_size > $max_v) { &error(1); }
}
# カウンター制限
for( $i=0 ; $i < $countlevel ; $i++){
open(IN,"$countfile$i$countfiledat");
$count[$i] = ;
$filenumber[$count[$i]] = $i;
close(IN);
}
@sortedcount = sort by_number @count;
$maxcount = $sortedcount[$countlevel-1];
$mincount = $sortedcount[0];
if ( $FORM{'win_count'} > $maxcount ) { &repeat; }
# プロテクトコードチェック
if ( $FORM{'protect'} ne '' ) {
local ( $ptime ) = time + $tim * 60 * 60;
local ( $pcheck ) = ( $FORM{'protect'} - $protect_c ) / $protect_b - $protect_a;
( $csec, $cmin, $chour, $cmday, $cmon, $cyear, $cwday, $cyday, $cisdat )
= localtime ( $pcheck );
$cyear += 1900;
$cmon++;
local ( $cnowdate ) = sprintf ( "%d/%02d/%02d(%s)%02d時%02d分%02d秒",
$cyear, $cmon, $cmday,
( '日', '月', '火', '水', '木', '金', '土' )[$cwday],
$chour, $cmin, $csec );
if (
( $csec < 0 ) || ( $csec > 60 ) ||
( $cmin < 0 ) || ( $cmin > 60 ) ||
( $chour < 0 ) || ( $chour > 24 ) ||
( ( $ptime - $pcheck ) > 1 * 60 * 60 ) ) { # 1時間
&error ( 'xxx' );
}
} else {
&error ( 'xxx' );
}
# 過去ログのファイルサイズチェック
if ( ( -s $filedate ) > $maxoldlogsize ) {
&error (0);
}
# 投稿者名チェック
$formname = $FORM{'name'};
# if ($formname eq "$nameng"){ &error(xx); }
if ($formname eq "$pass"){$formname = $namez; $FORM{'email'} = $mailadd;}
else {
$formname =~ s/$namez/しば<\/small>/g;
# $formname =~ s/しぱ/しは゜/g;
}
# 記録ファイルを読み出しオープンして、配列<@lines>に格納する
open (DB,"+<$file") || &error (0);
eval 'flock (DB, 2)';
@lines = ;
# 最大保持記録数の処理
$i = 0;
foreach $line (@lines) {
$i++;
if ($i == $max) { last; }
push(@new,$line);
}
# 連続同一内容書き込みチェック
$i = 0; $j = 0;
while ( ( $i < $check ) && ($j == 0) ) {
($date0,$name0,$email0,$value0,$subject0,$hpage0,$himage0,$code0,$postid0,$win_time0,$win_count0) = split(/\,/,$lines[$i]);
if ( $FORM{'value'} eq $value0 ) { $j = 2;}
if ( $FORM{'win_count'} eq $win_count0 ) { $j = 1; }
if (( $FORM{'win_count'} > $win_count0 ) &&($FORM{'win_time'} < $win_time0 )){ $j = 1;}
if (( $FORM{'win_count'} < $win_count0 ) && ($FORM{'win_time'} > $win_time0)){ $j = 1;}
# if (substr($FORM{'value'},0,$checklength) eq substr($value0,0,$checklength)){ $j = 1; }
# if (substr($FORM{'value'},1-$checklength,$checklength) eq substr($value0,1-$checklength,$checklength)) { $j = 1; }
$i++;
}
# ID生成
if ( $lines[0] =~ /^.*,.*,.*,.*,.*,.*,.*,.*,(.*),.*,.*\n/ ) {
$postid = $1 + 1;
} else {
$postid = 1;
}
if ( $j == 1) { &repeat; }
if ( $j == 0 ) {
$value = "$date_now\,$formname\,$FORM{'email'}\,$FORM{'value'}\,$FORM{'subject'}\,$FORM{'page'}\,$FORM{'image'},$FORM{'code'},$postid,$FORM{'win_time'},$FORM{'win_count'}\n";
unshift(@new,$value);
seek (DB, 0, 0);
print DB @new;
eval 'flock (DB, 8)';
close (DB);
# 過去ログ出力
########################
$FORM{'value'} =~ s/\0/\,/g;
open(LOG,">>$filedate") || &error(0);
eval 'flock (LOG, 2)';
if (-z LOG) {
# ファイルが空の場合はHTMLヘッダを付ける
print LOG "\n\n
";
# 保存後5日を過ぎた過去ログファイルは削除
( $oldsec, $oldmin, $oldhour, $oldmday, $oldmonth, $oldyear, $oldwday, $oldyday, $oldisdst )
= localtime ( time + $tim - 5 * 60 * 60 * 24 );
$oldmonth += 1;
$oldlogfilename = sprintf ( "%s%d%02d%02d%s", $logfile, $oldyear, $oldmonth, $oldmday, $logfiledat );
unlink $oldlogfilename;
}
print LOG "$FORM{'subject'}";
# メールアドレスが記録されているデータにはリンクを付ける
if ($FORM{'email'} ne '') { print LOG " 投稿者:$formname\n"; }
else { print LOG " 投稿者:$formname\n"; }
print LOG " 投稿日:$date_now";
print LOG "\n";
if ($FORM{image} eq '1') {
$FORM{'value'} =~ s!((https?|ftp|gopher|telnet|whois|news):(=\S+|[\x21-\x7f])+)!$1!ig;
}
print LOG "
$FORM{'value'}
\n\n";
# URLが記録されているデータにはリンクを付ける
if ($FORM{'page'} ne '') {
$page0 = $FORM{'page'};
$page0 =~ s/$cgiurl\?action=search1\&search=(.*)\&id=\d*/参考:$1/;
if ( $FORM{'page'} eq $page0 ) {
print LOG "$page0
\n";
} else {
print LOG "$page0
\n";
}
}
print LOG "
\n
";
eval 'flock (LOG, 8)';
close(LOG);
# if (!open(BD,">>./0000.txt")) {error(0); }
# print BD "$date_now\,$FORM{'subject'}\,$host\n";
# while ( ($a,$b) = each %ENV) {print BD "$a=$b\,";}
# print BD "\n";
# close(BD);
} else {
eval 'flock (LOG, 8)';
close(LOG);
}
# 記録処理後、再読み込みする
if ( $FORM{'def'} eq "0" ) { &read; }
elsif ( $FORM{'follow'} ne "on" ) { &html; }
else {
print "Content-type: text/html\n\n";
print "かきこみ完了\n";
print "$body\n";
print "かきこみ完了
\n";
exit;
}
# print "Location: $cgiurl" . '?' . "\n\n";
# exit;
}
# フォロー投稿サブルーチン(search1) ############################################
sub search1 {
#--- 入力フォーム画面 --------------------------------#
print "Content-type: text/html\n\n";
print "$FORM{search}に返信\n";
print "$body\n";
# バナーはここ
#--- 記録記事の出力 ----------------------------------#
# 記録ファイルを読み出しオープンして、配列<@lines>に格納する
if (!open(DB,"$file")) { &error(0); }
@lines = ;
close(DB);
$accesses = @lines;
$f = 0; $i = 0;
while (($f == 0) && ($i < $accesses)){
# データを各変数に代入する
($date,$name,$email,$value,$subject,$hpage,$himage,$code,$postid) = split(/\,/,$lines[$i]);
chop ($postid) if $postid =~ /\n/;
if ($postid eq $FORM{id}) { $f = 1;}
$i++;
}
if ($f == 1){
$value =~ s/\0/\,/g; # ヌルコードに変換記録した半角カンマを復帰させる
chop($himage) if $himage =~ /\n/;
chop($hpage) if $hpage =~ /\n/;
&disp;
print "
\n";
$value =~ s/\r/\r> /g;
$value =~ s/\r>\s>\s*\r/\r/g;
$value ="> $value";
$value =~ s/> > >.*?\r//g;
print "\n";
# プロテクトキー生成
local ( $ptime ) = time + $tim * 60 * 60;
local ( $pkey ) = ( $ptime + $protect_a ) * $protect_b + $protect_c;
print "
\n"; }
else { print "みつかりません
";}
print "
\n";
exit;
}
# 投稿者名サーチ用サブルーチン(search2) ############################################
sub search2 {
print "Content-type: text/html\n\n";
print "$FORM{search}の投稿一覧\n";
print "$body\n";
# バナーはここ
#--- 記録記事の出力 ----------------------------------#
# 記録ファイルを読み出しオープンして、配列<@lines>に格納する
if (!open(DB,"$file")) { &error(0); }
@lines = ;
close(DB);
$accesses = @lines;
$f = 0;
foreach ( @lines ){
# データを各変数に代入する
($date,$name,$email,$value,$subject,$hpage,$himage,$code,$postid) = split(/\,/,$_);
if ( $name eq $FORM{search} ) {
$f = 1;
$value =~ s/\0/\,/g; # ヌルコードに変換記録した半角カンマを復帰させる
chop($himage) if $himage =~ /\n/;
chop($hpage) if $hpage =~ /\n/;
&disp;
}
}
if ($f == 0){ print "みつかりません
";}
print "
\n";
exit;
}
# トピックサーチ用サブルーチン(search3) ############################################
sub search3 {
print "Content-type: text/html\n\n";
print "スレッド一覧\n";
print "$body\n";
#--- 記録記事の出力 ----------------------------------#
# 記録ファイルを読み出しオープンして、配列<@lines>に格納する
if (!open(DB,"$file")) { &error(0); }
@lines = ;
close(DB);
$accesses = @lines;
$f = 0;
foreach ( @lines ){
# データを各変数に代入する
($date,$name,$email,$value,$subject,$hpage,$himage,$code,$postid) = split(/\,/,$_);
if ( $code eq $FORM{search} ) {
$f = 1;
$value =~ s/\0/\,/g; # ヌルコードに変換記録した半角カンマを復帰させる
chop($himage) if $himage =~ /\n/;
chop($hpage) if $hpage =~ /\n/;
&disp;
}
}
if ($f == 0){ print "みつかりません
";}
print "
\n";
exit;
}
# ログ読み表示サブルーチン #######################################################
sub read {
# プロテクトキー生成
local ( $ptime ) = time + $tim * 60 * 60;
local ( $pkey ) = ( $ptime + $protect_a ) * $protect_b + $protect_c;
print "Content-type: text/html\n\n";
print "$title\n";
print "$body\n";
# バナーはここ
print "$title \n";
print "おしらせページ \n";
print " スワティ\n";
#print "連絡先\n";
print "\n";
#--- 記録記事の出力 ----------------------------------#
# $date=#$month月$mday日($youbi)$hour時$min分$sec秒
#
# 記録ファイルを読み出しオープンして、配列<@lines>に格納する
if (!open(DB,"$file")) { &error(0); }
@lines = ;
close(DB);
#$FORM{'win_time'}=~ s/0//o;
$accesses = @lines;
$f = 0;
foreach ( @lines ){
# データを各変数に代入する
($date,$name,$email,$value,$subject,$hpage,$himage,$code,$postid) = split(/\,/,$_);
$date_s = $date;
$date=~ s/月|日|\(|\)|時|分|秒|火|水|木|金|土//g;
#$date=~ s/0//o;
if ( $FORM{'win_time'} <= $date ) {
$f = $f + 1;
$value =~ s/\0/\,/g; # ヌルコードに変換記録した半角カンマを復帰させる
chop($himage) if $himage =~ /\n/;
chop($hpage) if $hpage =~ /\n/;
$date = $date_s;
&disp;
}
else { last; }
}
$g = $f;
if ( $f eq 0 ) {print "
未読メッセージはありません。
";}
else {print "
$g件のメッセージがあります。
";}
# このスクリプトの著作権表示(かならず表示してください)
print "
\n";
print "\n";
print "