#! /usr/local/bin/perl
#########################################################
# 　[bbty.cgi]　ver c-0.0082
#	基本的にはhttp://cgi.***.threewebnet.or.jp/用です
#	by 田中＠IPS http://www.threeweb.ad.jp/~tyukio/
#	LASTUPDATE 97/10/19  ようやくCOOKIE対応
#  ****アップロード後のFILE名は bbtyc.cgi です
#	3web.ne.jpへの移行対策済み
#			他のプロバイダでor＝＞neにも対応
#
#  3WEB(oskでもtkyでも可)の場合は、このCGI本体は$master_pwd以外は全く書き換えずにすむはずです
#  bbtyc.htmは普通に編集しますが、cgi.***.threewebnet.内ではhtmとは認識されません
#  書き込むときは htmではなくbbtyc.cgiにアクセスして下さい
#
#  3web以外のサーバー利用者は
# 1.perlのパスを調べて１行目書き換え 2.jcode.plはbbtyc.cgiと同じディレクトリに入れる
# 3.もしflockが使えない場合は
# ワードパッドなら[編集]＞[置換]＞置換前=flock 置換後=#flock
#		として＞[全て置換(A)]を押してから上書き保存する
# ワードパッド以外なら手動で全部のflockの左側に # を入れ、#flock にする

$master_pwd='xerox';##これは必ず変える	例:  $master_pwd='qw3frg';


$sc_n = $ENV{'SCRIPT_NAME'};#SCRIPT_NAME
$sv_n = $ENV{'SERVER_NAME'};
$ref = $ENV{'HTTP_REFERER'};

####jcode.plは必ずver2.0以上を使うこと
$jc_p= './jcode.pl'; ##3web以外の場合のjcode.plのパス(cgiと同じディレクトリならこのまま)
$jc_p= '/usr/local/lib/perl5/jcode.pl';

if($sv_n =~ /\.threeweb/i || $sv_n =~ /\.3web.ne.jp/i  ){
	$jc_p = '/usr/local/lib/perl5/jcode.pl'; #3webの場合のjcode.plのパス
	}
$jc_test= (-s $jc_p);
if($jc_test<3000){$er = " $jc_p が無い? ";&error;}
elsif($jc_test<10000){$er = $jc_p . ' のバージョンが2.0じゃ無い！！';&error;}
require $jc_p;

###  **.[4]ログのパスとFILE名#####################
$oj='.or.jp';$nj='.ne.jp';

if($ref =~ /$nj/i){$sv_n =~ s/$oj/$nj/i;}
if($ref =~ /$oj/i){$sv_n =~ s/$nj/$oj/i;}
$web='.3web.';$thr='.threewebnet.';

if($ref =~ /$web/i){$sv_n =~ s/$thr/$web/i;}
if($ref =~ /$thr/i){$sv_n =~ s/$web/$thr/i;}

$base_u='http://' .$sv_n;
$mine = $base_u . $sc_n;##これでCGIのURLが自動的に入るはず

#$mine = 'http://cgi.osk.threewebnet.or.jp/~ユーザー名/bbtyc/bbtyc.cgi';
##もしうまく行かないときは上のようにcgiのurlを直接書く

# 行の左側に#を付けるとその行は無効になります
$form= "<form method=\"GET\" action=\"$sc_n\">";# formタグ


$log_p = './';##CGIと同じDIRにログfileを入れる場合用
$htm_file = $log_p . 'bbtyc.htm';# ログのFILE名
$htmurl='http://www.hogehogenet/~tarou/input.htm';## 他に入力欄のあるURL(有れば)


$min_h = 50;  # ログの保存件数
$max_len = 1500;#文字列の長さ(長文書き込みを防ぐ)

$f_c = '<font size=3 color="#000000"> '; ##投稿文の文字指定(ここでは黒)

##設定は以上まで．．のはず
##
$max_br = '100';  ##これは全部の改行数、これを設定しないと１文字ずつ1000行の投稿とかされる
$max_cn = '500'; ##無限ループを防ぐ##
######以下は改変禁止です#########################33
$html_e[0] = '<!--COPY_LINE ここからしたは改変禁止です-->';
$html_e[1] = '<h5 align =right><!--配布URL-->';
$html_e[2] = 'CGI＆HTML：[<a href="http://www.threeweb.ad.jp/~tyukio/"><i>Tyukio</I></a>]';
$html_e[3] = '<p>[<a href="http://www.sosb.com/">SOSBbs</a>]';
$html_e[4] = '</h5>';
$html_e[5] = '</body></html>';
####### @html_eがHTMLの下部###############################################################

######入力でーたんの処理#####################
if($ENV{'REQUEST_METHOD'} eq "POST"){	read(STDIN, $inputf, $ENV{'CONTENT_LENGTH'});}
 else{	$inputf = $ENV{'QUERY_STRING'};}

##入力がされてないときエラ−&削除選択モード##############
if($inputf !~ /[a-z]/i){$er = '無記入です。';&inpterror;}

$host = $ENV{'REMOTE_HOST'};

###特定のホストからのアクセスを制限不要ならば &の前に#をつけて無効化する
# &host_check;
$ip = $ENV{'REMOTE_ADDR'};
$hoip = "<!--$host - $ip -->";

@pairs = split(/&/,$inputf);
$mgn_ch =0;
foreach $pair (@pairs)
{	$mgn_ch++;if($mgn_ch > $max_cn ){$er='mgn';&error;}
 ($name, $value) = split(/=/, $pair);
 $value =~ tr/+/ /;

	#####２重投稿防止######
if ($name eq 't_m'|| $name eq 't_msg')
	{#if($ht_fn !~ /htm/i||$ht_fn =~ /\\/){$er = "\$ref=$ref <br>ログの指定が不明です";&error;}
	$value_c = $value;
	$value_c =~ s/\*/8196/g;
	$value_c =~ s/\%//g;

	@check_l = split( // ,	$value_c );
	$cx_cn = '0';$cx_1 = '48';if($cx_1>$#check_l){$cx_1 = $#check_l;}
	$cx_2 = '52';if($cx_2 > $#check_l){$cx_2 = $#check_l;}

	$mgn_ch =0;
	while($cx_cn<= $cx_1)
		{$mgn_ch++;if($mgn_ch > $max_cn ){$er='mgn';&error;}
		$ch_1 = $ch_1 .$check_l[$cx_cn];$cx_cn++
		}
	$ch_2 = $ch_1;

	$mgn_ch =0;
	while($cx_cn<= $cx_2)
		{$mgn_ch++;if($mgn_ch > $max_cn ){$er='mgn';&error;}
		$ch_2 = $ch_2 .$check_l[$cx_cn];$cx_cn++
		}

	$er = "$htm_file のパスまたはFILE名が違います(設定の［５］番)";
	open( READ_NEW , $htm_file )||die &error;
		$_ = <READ_NEW>;
		close(READ_NEW);
	@re_n = split(/\*/,$_);
		$ip_o = $re_n[2];
		$ch_o2 = $re_n[3];


	if($ip_o =~/$ip/ && $ch_o2 =~/$ch_1/){$er = " さっきのと同じ文章みたいですけど？？";&error;}


	}	###作成memo変数## $log_ch_cntはlogの入れ替えカウント
	## $ip_oは前回投稿者のIP　$ch_1は今回処理中の投稿文の先頭から４０バイト
	## $ch_o2は前回投稿の先頭から５０バイト　$ch_2はそれに新しく入れる５０バイト

  $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
  &jcode'convert(*value, 'sjis');
  &jcode'h2z_sjis(*value); ####jcode.plは必ずver2.0以上を使うこと
 &htmldead;if($name eq t_msg){&htmlmask;}# タグ制限
 $FORM{$name} = $value;
}

# 変数############################################
$n = $FORM{'n'};#####
$n =~ s/\*/＊/g;
$e = $FORM{'e'};
$u = $FORM{'u'};
$t_msg = $FORM{'t_msg'};
$t_m = $FORM{'t_m'};

$t_a = $t_msg . $t_m;

$passwrd = $FORM{'passwrd'};
if($passwrd){
	if($passwrd eq $master_pwd)
	 {&delip;}
	 else{$er="パスワードが違います";&inpterror;}
		}
$pass_ww = $FORM{'pass_ww'};
$_ ="";

##不正なアクセスを禁止する

if($ref =~ /[a-z]/i)
	{$ref =~ s/%7e/\~/ig;
	$ref =~ s/\:80\//\//;
	if (($ref !~ /$mine/i && $ref !~ /$htmurl/i )
	||($ref =~ /^file\:/i ||$ref =~ /^[a-z]\:/i || $ref =~ /\\/) )
	{$er = "[ $ref ]からじゃ書けないんです〜〜！！";&error;exit;}
	}
&time;# 現在の時刻取得これは海外サーバーでも日本時間になるはず

###削除作業####
if($pass_ww eq $master_pwd){&delwork;exit;}
if(!($t_a)){$er = 'なんか書いてよ〜〜！';&error;exit;}
if ($n eq ''||$n eq ' '||$n eq '　'){$er = '名前が有りません！';&error;}

####################mail and url###############
 if ( $e ne "" ) {$e_f = "<A HREF=\"mailto:$e\">&lt; $e &gt;</A><br> ";}
  if ($u eq "http://"){$u ="";}
  if($u ne ""){$u_f = "<A HREF=\"$u\">$u</A><br>";}

#########投稿文を一行にまとめる##
$gs_txt = "$time $f_c <b>$n <br> $e_f $u_f </b> $t_a </font><hr> \n";

######文字列の長さチェック##
if(length($gs_txt)>$max_len){$er="$max_len	バイト以内でお願いします。 もう少し短くしてね〜〜";&error;}

####htmファイル読み込み##############
$htm_log = $htm_file;
&log_read;
######HTMfile書き込み文への代入####';
&guest_num; ##今までの入場者数を記録する
$guesttext = "$guest_num" . "$hoip" ."　"."$gs_txt";

$top_l[0] = '<!---*'.$guest_num .'*' .$ip .'*' .$ch_2 . '*この行のようなコメントタグは処理に使いますのでいじらないで下さい--->'."\n";

unshift(@log_l ,$guesttext);##配列@log_lの先頭に新しい投稿を差し込む
$_ =pop(@log_l);##最後の行を消す

while($#log_l >= $min_h)
	{$mgn_ch++;if($mgn_ch > $max_cn ){$er='mgn';&error;}
	$_ =pop(@log_l);
	}

#######HTMLに書き込む######
$er = " $htm_file のパーミッションが書き込み禁止？？";
	open(HTML_WRITE , ">$htm_file")||die &error;
	flock(HTML_WRITE,2);
	print HTML_WRITE @top_l;
	print HTML_WRITE @log_l;
	print HTML_WRITE @html_e;

	flock(HTML_WRITE ,8);
	close(HTML_WRITE);

$cook_value="$n\*$e\*$u";

print "Set-Cookie: name=$cook_value; expires=$cook_exp; domain=$sv_n\n";
print "Location: $location\n\n";exit;##メインルーチン終了

############以上までがメインしたはサブルーチン########################################
####################################################################################
sub time
{
($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime(time+9*60*60);
$mon++;

	###書き込み終了後urlに?と時間を足して自動リロードにする
$location = $mine . '?' . $sec . $min . $hour;
	##自動リロードさせたくないときは	$location = $htmurl;  ##とする
@week = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
$wday = $week[$wday];
$sec= sprintf("%.2d",$sec);
$min= sprintf("%.2d",$min);
$hour= sprintf("%.2d",$hour);
$mday= sprintf("%.2d",$mday);
$mon= sprintf("%.2d",$mon);
$time = "<font size=2 color=\"#990000\">$year\/$mon\/$mday ［$wday］$hour：$min：$sec</font><br>";

####ここから下cookie用のtime
($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime(time+30*24*60*60);
#$mon++;
$year=1900+$year;
@week = ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Satday');
$cwday = $week[$wday];
@mont=('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sept','Oct','Nov','Dec');
$cmon =$mont[$mon];

$sec= sprintf("%.2d",$sec);
$min= sprintf("%.2d",$min);
$hour= sprintf("%.2d",$hour);
$mday= sprintf("%.2d",$mday);
$mon= sprintf("%.2d",$mon);
$cook_exp = "$cwday\, $mday\-$cmon\-$year $hour\:$min\:$sec \GMT";
####$er=$cook_exp;&error;
}
####ファイル読み込み##############
sub log_read
{
$er = 'h_nr';
$ll_f = 'top';
$top_c = '0';$log_c = '0';
@top_l = ();@log_l = ();$_ = '';
	open( READ_LOG , $htm_log )||die &error;
	$mgn_ch =0;
	while(<READ_LOG>)
	{	$mgn_ch++;if($mgn_ch > $max_cn ){$er='mgn';&error;}

	 if($ll_f eq 'top'){$top_l[$top_c] = $_;$top_c++;}
	 if($ll_f eq 'log'){$log_l[$log_c] = $_;$log_c++;}
	 if($_ =~/<!--TOP_HTML_LINE/){$ll_f = 'log';}
	 }
	close(READ_LOG);
$er ="";
if ($ll_f eq 'top'){$er = "$htm_file が変です？？";&error;}
}
####作成memo $top_lはhtmlTOP部分(TOP_LINEのつもり)$log_lはログ##$top_cはカウント######
sub guest_num
{
@guest_sp = split( /\*/ ,  $top_l[0] );
$guest_num = ($guest_sp[1] + 1);

}
############削除選択モード###################
sub delip
{
$htm_log =$htm_file; ##投稿と表示のhtmページ
&time;

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

print<<"DELETE_HEAD";
<html><head><title>削除の選択モード( $htm_log )</title><body>
<h2>削除の選択モード</h2>
( $htm_log )<br>
 $time
 古いキャッシュが残っている時はリロードして下さい<br>
  (formを送り直しますか？と言う警告が出ますがそのままOKを押して下さい)<br>
 削除したい記事にチェックを入れてから下の[削除]ボタンを押して下さい

<form method=post action="$sc_n">
<input type="hidden" name="pass_ww" value="$passwrd">
<input type="hidden" name="del_log_file" value="$htm_file">
DELETE_HEAD
&log_read;
  $del_max = @log_l;
  $del_cnt = 0;
	$mgn_ch =0;
  while($del_max)
  { $mgn_ch++;if($mgn_ch > $max_cn ){$er='mgn';&error;}
  @del_sp = split( /</ ,  $log_l[$del_cnt] );
	if($del_sp[0] =~ /[0-9]/)
	{print"<input type=\"checkbox\" name=\"$del_cnt\" value=\"$del_sp[0]\">";}
  print"$log_l[$del_cnt]";
  $del_max--;$del_cnt++;
  }
	print "<input type=\"hidden\" name=\"del_wcnt\" value=\"$del_cnt\">\n";
	print '<input type=submit value=" 削除する">' . "\n";
	print '<input type=reset value=" やっぱやめとく">' . "\n";

print '<p><hr></body></html>';exit;
}
############削除作業##########
sub delwork
{
$htm_log = $htm_file;
print "Content-type: text/html\n\n";
print ' 削除作業にかかります<br>';
&log_read;
print ' ログを読み込みました<br>';
$_ = pop(@log_l);
$del_wcnt = @log_l;$wh_c = '0';

	$mgn_ch =0;
	while($del_wcnt)
	{	$mgn_ch++;if($mgn_ch > $max_cn ){$er='mgn';&error;}
	$d_n = $FORM{"$wh_c"};
	if ($d_n ne ''){$d_f[$d_n] = 'del';}
	$wh_c++;$del_wcnt--;
	}
$del_wcnt = @log_l;$wh_c = '0';
	$mgn_ch =0;
	while($del_wcnt)
	{	$mgn_ch++;if($mgn_ch > $max_cn ){$er='mgn';&error;}
  @del_sp = split( /</ ,  $log_l[$wh_c] );
	if($d_f[$del_sp[0]] eq 'del')
		{
		$log_l[$wh_c] = '';print "<br>$del_sp[0] 番の記事を消去します <br>\n";
				}
		else{$htm_l[$wh_c] = $log_l[$wh_c] ;}
	$wh_c++;$del_wcnt--;
	}
######削除済みの文章を書き込む######
	$er = "$htm_log  に書き込めません";
	open(DEL_WRITE , ">$htm_log")||die &error;
	 flock(DEL_WRITE,2);
	print DEL_WRITE @top_l;
	print DEL_WRITE @htm_l;
	print DEL_WRITE @html_e;
	 flock(DEL_WRITE ,8);
	close(DEL_WRITE);

print "$htm_log  の更新作業終了<br> ";

print "<h2>削除作業は終了しました</h2> <a href=\"$sc_n\">投稿ページへ</a>";exit;
}
exit;
#########名前欄やmail欄にタグが有ったらエラー######
sub htmldead
{if($name ne 't_msg' && ($value =~ /</ ||$value =~ />/|| $value =~ /\"/ ))
	{$er = '本文以外にタグは禁止です';&error;}
	$value =~ s/\r\n/\n/g;
	$value =~ s/\r/\n/g;
	$value =~ s/\n/<br>/g;
	$value =~ s/\&/\&amp;/g;
	$value =~ s/</&lt;/g;
	if ($value){if ($name eq 'u'||$name eq 'e'){&yaba_href;}}
}
exit;
######3個以上改行が有るときは１行だけにする
sub br_seigen
{
$mgn_ch =0;
while($value =~/<br><br><br>/ig)
	{	$mgn_ch++;if($mgn_ch > $max_cn ){$er='mgn';&error;}
	$value =~ s/<br><br><br>/<br>/ig;
	}

@br_check = split( /<br>/,$value);
if($#br_check > $max_br){$er = " 改行が多すぎるわ〜〜";&error;}
}
###HTMLのチェック###########
sub htmlmask
{	$value =~ s/&lt;\//<\//g;
	$value =~ s/<\/body/\d/ig;
	$value =~ s/<\/html/\d/ig;
	$value =~ s/&lt;br&gt;/<br>/ig;

	$value =~ s/&lt;br/<br/ig;

	##本文中に使えるのはFONTとBRタグだけ
	$value =~ s/&lt;font/<font/ig; ##許可させないときは頭に#をつけます(この行fontタグ)
&br_seigen;
if ($value =~ /\"/){$value = $value . '<!--"-->';}	####  ""の閉じ忘れ防止##
}
###やばいリンク
sub yaba_href
{	$yabaurl = $value;
	  if ( $yabaurl  =~ /mailbox\:/i || $yabaurl  =~ /\.lnk/i || $yabaurl  =~ /location/i
	|| $yabaurl  =~ /[a-n]\:/i || $yabaurl =~ /\.bat/i || $yabaurl	=~ /file\:/i
	|| $yabaurl  =~ /\.isp/i || $yabaurl =~ /\.url/i|| $yabaurl =~ /\.reg/i||$yabaurl =~ /\\/i	)
	{$er="[ $1 ] にリンクさせないで〜〜";&error;}
	elsif($yabaurl =~ /\?/ ){$er = " リンクの中に？は使わないで〜";&error;}
	elsif($yabaurl =~ /\&/ ){$er = " リンクの中に＆は使わないで〜";&error;}
}
###ホストチェック(ダイヤルQ2からのアクセス制限とか)
sub host_check
{
 if (!( $host =~ /[a-z]/i)) {$er = "ドメイン名を取得できませんでした";&error;}
  ####	[1２]の(1)上のはHOST名を取得出来なかった場合にエラ−に成ります############
  ##海外サーバーなどではそもそも取得できないかも知れません
   @ho_c = split(/\./ ,$host);@ho_c = reverse(@ho_c );$ho_ch = $ho_c[2];

	#if (!( $ho_c[0] eq 'jp' )) {$er = "jpドメイン以外の場所からの書き込みは禁止です";&error;}
		###  [1２]番の(2)##上のはJPドメイン以外からの書き込みを出来なくします(今は無効化してある)

 if (length($ho_c[0])>2){$ho_ch = $ho_c[1];}
  ##comの場合は、末尾から２番目と言うこと#########

  #  [1２]ばんの(3)ここから下はダイヤルQ2からの書き込み禁止です############
  %q2 = ();  ##連想配列にQ2プロバイダ名を入れる
   %q2 =('ingnet','n','interq','n','luvnet','n','jangle','n','eznet','n','baynet','n',
  'crisscross','n','ifnet','n','interwave','n','zzz','n','aif','n','awa','n','cyberoz','n',
  'synapse','n','chitanet','n','focus','n');

##他に制限したいプロバイダが有ったら 例：bekkoameの場合カッコの中に ,'bekkoame', 'n' と入れる
##

if($q2{"$ho_ch"}){$er = " あなたのプロバイダからの書き込みは出来ナインです";&error;}

}

#######error処理#####
sub error
{
if($er eq 'mgn'){$er= ' 無限ループの可能性があります';}
if($er eq 'h_nr'){$er= " $htm_log が読めないんですけど〜〜？？パスまたはFILE名を確認して下さい";}

print"Content-type: text/html\n\n";
print <<"ERROR_MESSE";
<html><head><title>$er</title></HEAD><body bgcolor="#ffffcc"text="#660000">
<H3>お知らせです</h3>
 <h3>$er</H3>
<a href="javascript:history.back()">戻る</a><br>
 JAVAスクリプトが使えないときはブラウザのバックボタンを押して戻ってね(^^)/~。<br>
ERROR_MESSE
exit;
}
exit;
####何も入力されていないとき＆削除の入り口###
sub inpterror
{

@cook =split(/\; /,$ENV{'HTTP_COOKIE'});
foreach(@cook)
	{
	($c_n,$c_v)=split(/=/,$_);
	if($c_n =~ /name/){($cook_n,$cook_e,$cook_u)=split(/\*/,$c_v);}
	}



$htm_log = $htm_file;
&log_read;
$_ =pop(@log_l);

$for=0;
foreach(@top_l)
{
if(/<form(.*)>/){$top_l[$for] =~ s/<form(.*)>/$form/ ;}
if(/name="n"/){ s/$&/$& value="$cook_n"/ ;}

if(/name="e"/){ s/$&/$& value="$cook_e"/ ;}

if(($cook_u)&&(/value="http:\/\/"/)){ s/$&/value="$cook_u"/ ;}

$for++;
}


$br_br= '<br>' x35;
if($ht_fn1 !~ /\.htm/i){$ht_fn1 = 'bbty.htm';}

print"Content-type: text/html\n\n";
print <<"ERROR_MES1";
@top_l
@log_l
$html_e[1]$html_e[2]$html_e[3]$html_e[4]
$br_br
<form method="POST"action="$sc_n">
<input type="password"name="passwrd" size=20>パスワードを入れてください
<p><input type="submit"value="送信"></form>
@html_e

ERROR_MES1
exit;
}
