#!/usr/local/bin/perl

$title = 'Double Dealer BBS (English)';
$reload = './ebbs.cgi';
$modoru = '../discuss.html';
$body = '<body bgcolor="#000000" text="#FFFFFF" link="#0099FF" vlink="#00CCFF" alink="#FF0099">';
$title_back = '#000099';
$s_mail = 0;
$mailto = '10065@contest.thinkquest.gr.jp'; # 送信先Ｅメール
$sendmail = '/usr/lib/sendmail'; # 送信スクリプト(sendmail) プロバイダに聞くこと$tag = 0;
@kyohi = (

	'<table(.|\n)*>',
	'<meta(.|\n)*>',
	'<pre(.|\n)*>',
	'<form(.|\n)*>',
	'<embed(.|\n)*>',
	'<script(.|\n)*>',
	'<frame(.|\n)*>',
	'<a(.|\n)*on(.*)=(.|\n)*>',
	'<img(.|\n)*on(.*)=(.|\n)*>',
	'',
	'',
	'',

'');

$msg_top1 = '';
$msg_top2 = '';
$msg_top3 = '';


$msg_mid1 = 'Before submitting articles, please create your own cancel key for canceling your article.
<br>';
$msg_mid2 = 'Once you create cancel key and submit it, your cancel key are preserved for a certain period.<br>';
$msg_mid3 = 'For canceling your article after submitting, please click "reset" then press "submit."';
$msg_btm1 = 'For cancel your article, check the cancel column at your article and write your cancel key at the right upper cancel blank、then finally click the cancel button<br>';
$msg_btm2 = 'Wrong cancel key do not work<br>';
$msg_btm3 = 'It is possible to cancel all article by writing master key (use only the master) instead of cancel key at the cancel column';
$ref_axs = 0;
$max_size = 2000;
$def = 20;
$max = '300';
require './jcode.pl';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg,$ydayg,$isdstg) = gmtime(time + 30*24*60*60);
$method = 1;
$file = 'ebbs.dat';
$tmp_dir = '../gather';
@wday_array = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
$date_now = sprintf("%01d/%01d(%s)%02d:%02d",$mon +1,$mday,$wday_array[$wday],$hour,$min);
$date_num = sprintf("%02d%02d%02d%02d%02d",$mon +1,$mday,$hour,$min,$sec); # <-変更禁止
&lock0;

if ($method eq '1' && $ENV{'QUERY_STRING'} ne '') { &error('Error!','Illigal Using.'); }

if ($method eq '1') { $method = 'post'; read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'}); }
else { $method = 'get'; $buffer = $ENV{'QUERY_STRING'}; }

@pairs = split(/&/,$buffer);
@pairs = (grep(/^action=/,@pairs),grep(!/^action=/,@pairs));
foreach $pair (@pairs) {

	($name, $value) = split(/=/, $pair);
	$value =~ tr/+/ /;
	$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

	&jcode'convert(*value,'sjis');

	if ($value =~ /(.*)\"\,\"(.*)/) { &error('miss','error!'); }

	$value =~ s/<!--(.|\n)*-->//g;

	if ($tag) {

		foreach (@kyohi) {
	
			if (/^$/) { next; }
			if ($value =~ /$_/i) { &error('miss','error!'); }
		}
	}

	else { $value =~ s/</&lt;/g; $value =~ s/>/&gt;/g; }

	if ($s_mail && $name eq 'value') {

		$mail_value = $value;
		if ($mail_value =~ /\r\n/) { $mail_value =~ s/\r\n/\n/g; }
		if ($mail_value =~ /\r/) { $mail_value =~ s/\r/\n/g; }
	}

	if ($FORM{'action'} eq 'regist') {

		if ($value =~ /\r\n/) { $value =~ s/\r\n/\r/g; }
		if ($value =~ /\n/) { $value =~ s/\n/\r/g; }

		if ($FORM{'how'} eq '1') { $value =~ s/\r/<br>\r/g; }
	}

	if ($name eq 'name' || $name eq 'email') { $value =~ s/\;//g; $value =~ s/\://g; $value =~ s/\,//g; }

	if ($name eq 'target') { push(@RM,$value); }
	else { $FORM{$name} = $value; }
}

if ($FORM{'action'} eq 'password') { &encode; }

$cookies = $ENV{'HTTP_COOKIE'};

@pairs = split(/;/,$cookies);
foreach $pair (@pairs) {

	($name, $value) = split(/=/, $pair);
	$name =~ s/ //g;
	$DUMMY{$name} = $value;
}

@pairs = split(/,/,$DUMMY{$reload});
foreach $pair (@pairs) {

	($name, $value) = split(/:/, $pair);
	$COOKIE{$name} = $value;
}

if ($FORM{'admin'} eq 'change') { &password; exit; }
if ($FORM{'action'} eq 'remove') { &remove; }
elsif ($FORM{'action'} eq 'regist') { &regist; }

if (!open(DB,"$tmp_dir\/$file")) { &error('setup miss',"$file is not here."); }
@lines = <DB>;
close(DB);

if (-z "$tmp_dir\/$file") { $first = 1; &password; exit; }
elsif (!(@lines[0] =~ /MiniBBSv8/)) { &error('data error',"$file cant use."); }

&html;
exit;

sub html {

	#--- 入力フォーム画面 --------------------------------#

	print "Content-type: text/html\n\n";

	print "<html><head><title>$title</title></head>\n";
	print "$body\n";
	print "<h1>$title</h1>\n";

	print "$msg_top1\n";
	print "$msg_top2\n";
	print "$msg_top3<p>\n";

	print "<form method=$method action=\"$reload\">\n";
	print "<input type=hidden name=\"action\" value=\"regist\">\n";

	print "Name <input type=text name=\"name\" size=20 value=\"$COOKIE{'name'}\" maxlength=19><br>\n";
	print "Mail Address <input type=text name=\"email\" size=40 value=\"$COOKIE{'email'}\"><br>\n";
	print "Title <input type=text name=\"subject\" size=70 maxlength=69><br>\n";
	print "Contents <font size=-1><input type=radio name=\"how\" value=\"1\" checked>Auto Space & Return ";
	print "<input type=radio name=\"how\" value=\"2\">Manual</font><br>\n";
	print "　　　 <textarea name=\"value\" rows=5 cols=70></textarea><br>\n";
	print "URL <input type=text name=\"url\" size=70 value=\"http://\"><p>\n";
	print "　　　 <input type=submit value=\"     Submit     \"><input type=reset value=\"Reset\">  ";
	print "Delete Password <input type=password name=\"pwd\" size=10 value=\"$COOKIE{'pwd'}\"> <font size=-1>(For canceling your article)</font></form><p>";

	print "$msg_mid1\n";
	print "$msg_mid2\n";
	print "$msg_mid3<p>\n";

	#--- 記録記事の出力 ----------------------------------#

	@lines = reverse(@lines);

	if ($FORM{'page'} eq '') { $page = 0; } else { $page = $FORM{'page'}; }

	$page_end = $page + $def - 1;
	if ($page_end > $#lines) { $page_end = $#lines; }

	print "<form method=$method action=\"$reload\">\n";
	print "<input type=hidden name=\"action\" value=\"remove\">\n";

	foreach ($page .. $page_end) {

		if ($lines[$_] =~ /^\"(\d+)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\",\"(.*)\"/) {

			$number = $1;
			$pwd = $2;
			$name = $3;
			$email = $4;
			$host = $5;
			$date = $6;
			$subject = $7;
			$value = $8;
			$url = $9;
			$how = $10;

			print "<hr size=5><p>\n";
			print "<table width=100% border=0><tr><td bgcolor=$title_back><font size=+2><b>$subject</b></font></td></tr></table>\n";

			print "<i><b>Date</b> $date ";
			if ($email) { print "<b>Writer</b> <a href=\"mailto:$email\">$name</a> [$host]  "; } else { print "Writer $name [$host]  "; }

			print "<input type=checkbox name=\"target\" value=\"$number\">Cancel<p></i>\n";

			print "<blockquote><font size=+1>\n";

			if ($how == 1) { print "$value<p>\n"; }
			else { print "<pre>$value</pre><p>\n"; }

			if ($url) { print "<a href=\"$url\" target=\"_top\">$url</a><p>\n"; }

			print "</font></blockquote>\n";
		}
	}

	#--- 改ページ処理 ------------------------------------#

	$page_next = $page_end + 1;
	$i = $page + 1; $j = $page_end + 1;

	print "<hr><p><table border=1 cellpadding=2 cellspacing=2><tr>\n";

	print "<td>Cancel Key <input type=password name=\"pwd\" size=10 value=\"$COOKIE{'pwd'}\"> ";
	print "<input type=submit value=\"delete\"></td></form>\n";

	if ($#lines >= 0) {

		if ($page_end ne $#lines) {

			print "<td>newly $i \- $j</td>\n";
			print "<form method=$method action=\"$reload\">\n";
			print "<input type=hidden name=\"page\" value=\"$page_next\">\n";
			print "<td><input type=submit value=\"next page\"></td></form>\n";
		}
		else { print "<td>newly $i \-&gt; last</td>\n"; }
	}

	print "<td>maximum recorded rates $max</td>\n";

#	print "<th><font size=+1><a href=\"$reload\">reload</a></font></th>\n";
#	print "<th><font size=+1><a href=\"$modoru\" target=\"_top\">end</a></font></th>\n";
	print "</tr></table><p>\n\n";

	print "$msg_btm1\n";
	print "$msg_btm2\n";
	print "$msg_btm3<p>\n";

	print "<table border=1 cellpadding=2 cellspacing=2><tr>\n";
	print "<form method=$method action=\"$reload\">\n";
	print "<input type=hidden name=\"admin\" value=\"change\">";
	print "<td><input type=submit value=\"change the master key\"></td></form>\n";
	print "</tr></table><p>\n\n";

	# このスクリプトの著作権表示（かならず表示してください）
	print "<h5 align=right><a href=\"http://www.rescue.ne.jp/\" target=\"_top\">MiniBBS v8.90</a></h5>\n";

	print "</body></html>\n";
}

sub regist {

	if ($ref_axs) {

		$ref = $ENV{'HTTP_REFERER'};
		$ref_url = $reload; $ref_url =~ s/\~/.*/g;
		if (!($ref =~ /$ref_url/i)) { &error('error!',"not $reload is illigal."); }
	}

	if ($FORM{'name'} eq '') { &error('error!','write your name.'); }
	$FORM{'name'} =~ s/</&lt;/g; $FORM{'name'} =~ s/>/&gt;/g;

	if ($FORM{'email'} ne '' && !($FORM{'email'} =~ /(.*)\@(.*)\.(.*)/)) { &error('error!','write right address.'); }
	$FORM{'email'} =~ s/</&lt;/g; $FORM{'email'} =~ s/>/&gt;/g;

	if ($FORM{'pwd'} eq '' || $FORM{'pwd'} =~ /\W/ || length($FORM{'pwd'}) > 10) { &error('error!','write cancel key.'); }

	if ($FORM{'subject'} eq '' && $FORM{'value'} eq '') {

		$COOKIE{'name'} = '';
		$COOKIE{'email'} = '';
		$COOKIE{'pwd'} = '';
		&cookie; 
		print "Set-Cookie: $reload=\n";
		&html;
		exit;
	}

	if ($FORM{'subject'} eq '') { &error('error!','write title.'); }
	$FORM{'subject'} =~ s/</&lt;/g; $FORM{'subject'} =~ s/>/&gt;/g;

	if ($FORM{'value'} eq '') { &error('error!','write contents.'); }
	if ($max_size) {

		$value_size = length($FORM{'value'});
		if ($value_size > $max_size) { &error('error!',"too big! (max $max_size) now=value_size."); }
	}

	if ($FORM{'url'} ne '' && !($FORM{'url'} =~ m#(.*)tp(.*)://#)) { &error('error!','write right url.'); }
	if ($FORM{'url'} =~ m#^(.*)tp(.*)://$#) { $FORM{'url'} = ''; }

	&cookie;
	$cook="name\:$FORM{'name'}\,email\:$FORM{'email'}\,pwd\:$FORM{'pwd'}";
	print "Set-Cookie: $reload=$cook; expires=$date_gmt\n";

	#-- リムネット専用ホスト取得ルーチンの入れ替え位置 : ここから --#

	$host = $ENV{'REMOTE_HOST'};
	$addr = $ENV{'REMOTE_ADDR'};
	if ($host eq $addr) { $host = gethostbyaddr(pack('C4',split(/\./,$host)),2) || $addr; }

	#-- リムネット専用ホスト取得ルーチンの入れ替え位置 : ここまで --#

	&lock1;

	if (!open(DB,"$tmp_dir\/$file")) { &error('setup error!',"$file if not found."); }
	@lines = <DB>; $password = shift(@lines);
	close(DB);

	&encode2($FORM{'pwd'});

	if ($max <= $#lines + 1) { shift(@lines); }
	push(@lines,"\"$date_num\"\,\"$pwd\"\,\"$FORM{'name'}\"\,\"$FORM{'email'}\"\,\"$host\"\,\"$date_now\"\,\"$FORM{'subject'}\"\,\"$FORM{'value'}\"\,\"$FORM{'url'}\"\,\"$FORM{'how'}\"\n");

	if (!open(DB,"> $tmp_dir\/$tmp_file")) { &error('setup error!','temp file cant create'); }
	print DB $password;
	print DB @lines;
	close(DB);

	&lock2;

	$COOKIE{'name'} = $FORM{'name'};
	$COOKIE{'email'} = $FORM{'email'};
	$COOKIE{'pwd'} = $FORM{'pwd'};

	if ($s_mail) { &e_mail; }
}

sub cookie {

	if ($yearg < 10)  { $yearg = "0$yearg"; }
	if ($secg < 10)   { $secg  = "0$secg";  }
	if ($ming < 10)   { $ming  = "0$ming";  }
	if ($hourg < 10)  { $hourg = "0$hourg"; }
	if ($mdayg < 10)  { $mdayg = "0$mdayg"; }

	$y0="Sunday"; $y1="Monday"; $y2="Tuesday"; $y3="Wednesday"; $y4="Thursday"; $y5="Friday"; $y6="Saturday";
	$youbi = ($y0,$y1,$y2,$y3,$y4,$y5,$y6) [$wdayg];

	$m0="Jan"; $m1="Feb"; $m2="Mar"; $m3="Apr"; $m4="May"; $m5="Jun";
	$m6="Jul"; $m7="Aug"; $m8="Sep"; $m9="Oct"; $m10="Nov"; $m11="Dec";
	$month = ($m0,$m1,$m2,$m3,$m4,$m5,$m6,$m7,$m8,$m9,$m10,$m11) [$mong];

	$date_gmt = "$youbi, $mdayg\-$month\-$yearg $hourg:$ming:$secg GMT";
}

sub error {

	print "Content-type: text/html\n\n";
        print "<html><head><title>$title</title></head>\n";
        print "$body\n";
        print "<h1>$_[0]</h1>\n";
	print "<h3>$_[1]</h3>\n";
	print "Please back!<p>\n";
        print "</body></html>\n";
        exit;
}

sub remove {

	&lock1;

	if (!open(DB,"$tmp_dir\/$file")) { &error('setup error!',"$file is not found."); }
	@lines = <DB>;
	close(DB);

	$password = shift(@lines);
	chop($password);
	($header,$password1) = split(/:/,$password);
	if ($password1 =~ /^\$1\$/) { $salt = 3; } else { $salt = 0; }

	$target = join('|',@RM);
	if (crypt($FORM{'pwd'}, substr($password1,$salt,2)) eq $password1) { $admin = 1; }

	foreach $line (@lines) {

		if ($line =~ /^\"(\d+)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\"\,\"(.*)\",\"(.*)\"/) {

			$number = $1;
			$pwd = $2;

			if ($number =~ /$target/) {

				if (!$admin && crypt($FORM{'pwd'}, substr($pwd,$salt,2)) ne $pwd) { push(@NEW,$line);}
			}
			else { push(@NEW,$line); }
		}
	}

	if (!open(DB,"> $tmp_dir\/$tmp_file")) { &error('error!','temp file cant create'); }
	print DB "$password\n";
	print DB @NEW;
	close(DB);

	&lock2;

	@lines = @NEW;
}

sub password {

	if (-z "$tmp_dir\/$file") { $first = 1; }

	print "Content-type: text/html\n\n";
	print "<html><head><title>$title</title></head>\n";
	print "$body\n";
	print "<h1>マスターキーの設定/変更</h1>\n";

	if ($first && $message eq '') { print "記事を削除するための管理パスワードを登録します。<p>\n"; }
	else { print "$message<p>\n"; }

	print "<form method=$method action=\"$reload\">\n";
	print "<input type=hidden name=\"action\" value=\"password\">\n";
	if (!$first) { print "旧パスワード <input type=password name=\"password_old\" size=10><br>\n"; }
	print "新パスワード <input type=password name=\"pwd\" size=10><br>\n";
	print "新パスワード <input type=password name=\"pwd2\" size=10>（確認のためもう一度）<p>\n";
	print "<input type=submit value=\"     登録     \"></form><p>\n";
	print "</body></html>\n";
}

sub encode {

	&lock1;

	if (!open(DB,"$tmp_dir\/$file")) { &error('error!',"$file is not found."); }
	@lines = <DB>;
	close(DB);

	$password = shift(@lines);
	chop($password);
	($header,$password1) = split(/:/,$password);
	if ($password1 =~ /^\$1\$/) { $salt = 3; } else { $salt = 0; }

	if ($header eq 'MiniBBSv8') { if (crypt($FORM{'password_old'}, substr($password1,$salt,2)) ne $password1) { $message = '旧パスワードが認証されませんでした.'; &password; exit; }}
	if ($FORM{'pwd'} =~ /\W/ || $FORM{'pwd'} eq '') { $message = '新パスワードに英数字以外の文字が含まれているか空欄です.'; &password; exit; }
	if ($FORM{'pwd'} ne $FORM{'pwd2'}) { $message = '確認のために入力された新パスワードが一致しません.'; &password; exit; }

	&encode2($FORM{'pwd'});

	if (!open(DB,"> $tmp_dir\/$tmp_file")) { &error('error!','temp file cant create.'); }
	print DB "MiniBBSv8\:$pwd\n";
	print DB @lines;
	close(DB);

	&lock2;

	&html; exit;
}

sub encode2 {

	$now = time;
	($p1, $p2) = unpack("C2", $now);
	$wk = $now / (60*60*24*7) + $p1 + $p2 - 8;
	@saltset = ('a'..'z','A'..'Z','0'..'9','.','/');
	$nsalt = $saltset[$wk % 64] . $saltset[$now % 64];
	if (!eval '$pwd = crypt($_[0], $nsalt);') { &error('error!','pascode cant use.'); }
}

sub e_mail {

	# 管理者に投稿をメールする

	if (!open(OUT,"| $sendmail -t")) { return; }

	print OUT "To: $mailto\n";
	if ($FORM{'email'} ne '') { print OUT "From: $FORM{'email'}\n"; }
	else { print OUT "From: $mailto\n"; }
	$subject = "[$title] 新着情報";
	&jis("Subject: $subject"); print OUT "$msg\n";
	print OUT "Content-Transfer-Encoding: 7bit\n";
	print OUT 'Content-Type: text/plain; charset=iso-2022-jp' . "\n\n\n";

	&jis("投稿者: $FORM{'name'}"); print OUT "$msg\n";
	&jis("Ｅメール: $FORM{'email'}"); print OUT "$msg\n";
	&jis("題名: $FORM{'subject'}"); print OUT "$msg\n";
	&jis("\n$mail_value"); print OUT "$msg\n\n";
	&jis("ＵＲＬ記入欄: $FORM{'url'}"); print OUT "$msg\n";

	close(OUT);
}

sub jis { $msg = $_[0]; &jcode'convert(*msg, 'jis'); }

sub lock0 {

	$ps = $$;
	if ($ps eq '') { $ps = $date_num; }
	$tmp_file = "$ps\.tmp";
	$ls = "$tmp_dir\/*\.tmp";
}

sub lock1 {

	$list = `ls $ls`;
	@lists = split(/\s+/,$list);

	local($retry) = 3;
	while (@lists) {

		if (--$retry <= 0) {

			foreach (@lists) { unlink; }
			&error("Busy(1)",'Please rewrite!');
		}
		sleep(1);
		$list = `ls $ls`;
		@lists = split(/\s+/,$list);
	}
}

sub lock2 {

	$list = `ls $ls`;
	@lists = split(/\s+/,$list);
	@lists = grep(!/$tmp_file/,@lists);
	if (@lists) { unlink("$tmp_dir\/$tmp_file"); &error("Busy(2)",'Please rewrite!'); }

	if (!rename("$tmp_dir\/$tmp_file","$tmp_dir\/$file")) { &error("Busy(3)",'Please rewrite!'); } ;
	chmod 0666,"$tmp_dir\/$file";
}
