#!/usr/local/bin/perl

require './jcode.pl';

#----------------------------
$ver="BBS-i v3.4";
# (i-mode向け簡易掲示板/日記)
#----------------------------
# Copyright(C) りゅういち
# E-Mail:ryu@cj-c.com
# W W W :http://www.cj-c.com/

#-- 設定ファイル -------------*

# 同じようにいくつでも増やせます。
# [ ]内の数字を使いCGIにアクセスするとその設定ファイルで動作します。
# $set[12] の設定ファイルを使う場合: http://www.xxx.com/cgi-bin/bi.cgi?no=12
$set[0]="./set.cgi";
$set[1]="./set1.cgi";
$set[2]="./set2.cgi";

# 禁止文字列 同じようにいくつでも指定可能
@NW=('死ね','バカ','アホ');

#--- 設定ここまで---------------*
$j_=0; $i_=0; $a_=0; $e_=0;
$Imode=$ENV{'HTTP_USER_AGENT'};
$Jskyw=$ENV{'HTTP_X_JPHONE_MSNAME'};
if($Jskyw ne ""){$j_=1;}
if($Imode=~ /DoCoMo/){$i_=1;}
elsif($Imode=~ /J-PHONE\/2/){$j_=1;}
elsif($Imode=~ /J-PHONE\/[3-9]/){$j_=2;}
elsif($Imode=~ /ASTEL/){$a_=1;}
elsif(index($Imode,"UP.Browser")==0){$e_=1;}
elsif(index($Imode,"UP.Browser") > 0){$e_=2;}
if($j_ || $i_ || $a_ || $e_){$PC=0;}else{$PC=1;}
$html="";
&d_code_;
if($no eq ""){$no=0;}
if($set[$no]){unless(-e $set[$no]){&er_('設定ファイルがありません!');}else{require "$set[$no]";}}
else{&er_('設定ファイルがCGIに設定されていません!');}
$nf="<input type=hidden name=no value=$no>\n";
if($diary){$Form1="天気";$Form2="日付け";}else{$Form1="ネーム";$Form2="メール";}
if($j_==1){$met="GET";}
if($j){$MAX=" maxlength=50";}else{$MAX="";}
if($mode eq "edit"){&Edit;}
if($mode eq "all"){&all_;}
if($mode eq "fom"){&fom_;}
if($mode eq "man"){&man_;}
if($mode eq "wri"){&wri_;}
if($mode eq "del"){&del_;}
if($mode eq "s_d"){&s_d_;}
if($mode eq "nam"){&hen_;}
if($mode eq "h_w"){&h_w_;}
if($access){
	if($access==1 && $j_==0){&er_("J-Sky端末でアクセスして下さい!");}
	elsif($access==2 && $i_==0){&er_("i-mode端末でアクセスして下さい!");}
	elsif($access==3 && $a_==0){&er_("ドットi端末でアクセスして下さい!");}
	elsif($access==5 && $e_==0){&er_("ezweb端末でアクセスして下さい!");}
	elsif($access==4 && $a_==0 && $i_==0 && $j_==0 && $e_==0){
		&er_("i-mode/J-Sky/ドットi/ezweb端末でアクセスして下さい!");
	}
}
&html_;
#
# [フォーム表示]
#
sub fom_ {
if($diary && $FORM{'pass'} ne "$pass"){&er_("パスワードが違います!");}
&get_;
if($diary){$c_email=$date;}
$c_max2=$c_max/2;
$n_max2=$n_max/2;
&hed_;
$html.= <<"_FORM_";
<center>[<a href="$cgi_f?no=$no">戻</a>]<br>
新規投稿フォーム</center><hr>
*半角カナは×
<form action="$cgi_f" method="$met">$nf
<input type=hidden name=mode value=wri>
$Form1┓<br><input type=text name=name value="$c_name" size=16 maxlength=$n_max><br>
$Form2┓<br><input type=text name=email value="$c_email" size=16$MAX><br>
コメント┓<br>
<textarea name=comment rows=4 cols=14 wrap=$wrap></textarea><br>
全角$c_max2文字まで<br>(URLは自動的に<br>リンクされます)<br>
<input type=submit value="送信">
<input type=reset value="リセット"></form>
_FORM_
&foot_;
}
#
# [トップページ]
#
sub html_ {
unless(-e $log){&l_m($log);}
if($cou){unless(-e $c_f){&l_m($c_f);}}

open(LOG,"$log") || &er_("Can't open $log");
@lines = <LOG>;
close(LOG);

&hed_;
$html.= "<center>\n";
$html.= "$title\n";
if($diary){$html.= "<hr>[<a href=\"$back\">戻</a>]</center><hr>$com<hr>\n";}else{
	$html.= <<"_HTML_";
<hr>
[<a href="$back">戻</a>|<a href="$cgi_f?mode=man&no=$no">説</a>|<a href="$cgi_f?mode=fom&no=$no">書</a>]
</center><hr>$com<hr>
_HTML_
}
$total=@lines;
$page_=int(($total-1)/$a_max);
if($FORM{'page'} eq ''){$page=0;}else{$page=$FORM{'page'};}
$end_data=@lines - 1;
$page_end=$page+($a_max-1);
if($page_end >= $end_data){$page_end=$end_data;}

foreach ($page .. $page_end) {
	($namber,$date,$name,$email,$comment) = split(/<>/,$lines[$_]);
	if($email ne "" && $diary==0){ $name="<a href=\"mailto:$email\">$name</a>"; }
	&auto_($comment);
	if($diary){$html.="$email<br>$name<br>$comment<hr>\n";}
	else{$html.= "$name<br>$comment<br>$date<hr>\n";}
}
$next_line=$page_end + 1;
$back_line=$page - $a_max;
if($back_line >= 0){$html.="\&lt\;<a href=\"$cgi_f?page=$back_line&no=$no\">前$a_max</a>|\n";}
if($page_end ne $end_data){$html.="<a href=\"$cgi_f?page=$next_line&no=$no\">次$a_max</a>\&gt\;\n";}
$html.="</center><div align=right><form action=\"$cgi_f\" method=$met>";
if($cou){ &con_; }
$html.= <<"_HTML_";
<input type=hidden name=mode value=del>$nf
<input type=password name=pass size=6>
<input type=submit value="管理"><br>
</form></div>
_HTML_
&foot_;
}
#
# [ログ書きこみ処理]
#
sub wri_ {
if($diary==0){
	if(length($name) > $n_max){&er_("名前が長すぎます!");}
	if(length($comment) > $c_max){&er_("コメントが長すぎます!");}
}
if($FORM{'name'} eq ""){&er_("お名前が未入力!");}
if($FORM{'comment'} eq ""){&er_("コメントが未入力!");}
if($locks){&lock_;}

open(LOG,"$log") || &er_("Can't open $log","1");
@lines = <LOG>;
close(LOG);

($knum,$kd,$kname,$kem,$kcom) = split(/<>/,$lines[0]);
if ($name eq $kname && $comment eq $kcom) { &er_("二重投稿は禁止です!","1"); }

&set_;

@new=();
for($i=0;$i<$max-1;$i++) {push(@new,$lines[$i]);}
$namber=$knum + 1;

unshift (@new,"$namber<>$date<>$name<>$email<>$comment<>\n");

open(LOG,">$log") || &er_("Can't write $log","1");
print LOG @new;
close(LOG);

if(-e $lockf){rmdir($lockf);}
if($t_mail && $mymail){&mail_;}
elsif($t_mail && $mailad ne "$email" && $mymail==0){&mail_;}
}
#
# [記事一括削除]
#
sub s_d_ {
if ($FORM{'pass'} ne "$pass") { &er_("パスワードが違います!"); }
open(DB,">$log");
print DB "";
close(DB);
}
#
# [説明書]
#
sub man_ {
&hed_;
$html.= <<"_HTML_";
[<a href="$cgi_f?no=$no">戻</a>]<br>
$titleマニュアル<hr>
-タグは使えません<br>
-記事は$maxコまで<br>
-他人の中傷記事は管理者の判断で削除します<br>
-半角カナは×<br>
-ネーム、コメントは必須項目です<br>
-クッキー対応(クッキー有効の場合)
_HTML_
&foot_;
}
#
# [ヘッダ表示]
#
sub hed_ {
$html.= <<"_HTML_";
<html><head><title>$title</title>
<!--$ver--><META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS">
</head>
$body
_HTML_
}
#
# [フッタ表示]
#
sub foot_ {
$html.= <<"_HTML_";
<hr><!--著作権表\示 削除不可-->
<a href="http://www.cj-c.com/i/" target=_top>BBS-i</a>
</body></html>
_HTML_
&htmlp;
}
#
# [フォームなどのデコード]
#
sub d_code_ {
if($ENV{'REQUEST_METHOD'} eq "POST"){
	if ($ENV{'CONTENT_LENGTH'} > 10000) { &er_("文章があまりに長すぎます!"); }
	read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else{ $buffer = $ENV{'QUERY_STRING'}; }

@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;
	&jcode'convert(*value,'sjis');
	$value =~ s/&/\&amp\;/g;
	$value =~ s/</\&lt\;/g;
	$value =~ s/>/\&gt\;/g;
	$value =~ s/\"/\&quot\;/g;
	$value =~ s/<>/\&lt\;\&gt\;/g;
	$value =~ s/<!--(.|\n)*-->//g;
	if(@NW){
		foreach (0..$#NW){if(index($value,$NW[$_]) >= 0){&er_("「$NW[$_]」は使用不可!");}}
	}
	$FORM{$name} = $value;
	if($name eq 'del'){push(@d_,$value);}
	if($name ne 'comment'){$value =~ s/\r|\n|\r\n/ /g;}
}
$name = $FORM{'name'};
$comment=$FORM{'comment'};$comment=~ s/\r\n|\r|\n/<br>/g;
$email= $FORM{'email'};
$mode = $FORM{'mode'};
$kiji = $FORM{'kiji'};
$namber=$FORM{'namber'};
$no   = $FORM{'no'};

$ENV{'TZ'} = "JST-9";
($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime(time);
$mon++;
if ($hour < 10) { $hour = "0$hour"; }
if ($min  < 10) { $min  = "0$min";  }
$date = "-$mon\/$mday $hour\:$min";
if($diary && $email){$date=$email; $email="";}
}
#
# [クッキー発行]
#
sub set_ { 
($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg,$ydayg,$isdstg) = gmtime(time + 30*24*60*60);
$yearg += 1900;
if ($secg  < 10) { $secg  = "0$secg";  }
if ($ming  < 10) { $ming  = "0$ming";  }
if ($hourg < 10) { $hourg = "0$hourg"; }
if ($mdayg < 10) { $mdayg = "0$mdayg"; }
$month = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[$mong];
$youbi = ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday')[$wdayg];
$date_gmt = "$youbi, $mdayg\-$month\-$yearg $hourg:$ming:$secg GMT";
$cook="name\:$name\,email\:$email";
print "Set-Cookie: LINEBBS=$cook; expires=$date_gmt\n";
}
#
# [クッキー取得]
#
sub get_ { 
	$cookies = $ENV{'HTTP_COOKIE'};
	@pairs = split(/;/,$cookies);
	foreach $pair (@pairs) {
		($name, $value) = split(/=/, $pair);
		$name =~ s/ //g;
		$DUMMY{$name} = $value;
	}
	@pairs = split(/,/,$DUMMY{'LINEBBS'});
	foreach $pair (@pairs) {
		($name, $value) = split(/:/, $pair);
		$COOKIE{$name} = $value;
	}
	$c_name =$COOKIE{'name'};
	$c_email=$COOKIE{'email'};

	if($FORM{'name'}) {$c_name =$FORM{'name'};}
	if($FORM{'email'}){$c_email=$FORM{'email'};}
}
#
# [管理用ページ]
#
sub del_ {
if($FORM{'pass'} ne "$pass"){&er_("パスワードが違います!");}
&hed_;
if($diary){$html.="[<a href=\"$cgi_f?mode=fom&pass=$FORM{'pass'}&no=$no\">書</a>]";}
$html.= <<"_HTML_";
[<a href="$cgi_f?no=$no">戻</a>]<br>
-管理モード-
_HTML_
open(DB,"$log");
@lines = <DB>;
close(DB);

if($FORM{'del'}){
	open(DB,"$log") || &er_("Can't open $log");
	@COMS = <DB>;
	close(DB);
	@CAS = ();
	foreach $COMS (@COMS) {
		$COMS =~ s/\n//g;
		($nam,$da,$na,$em,$com) = split(/<>/,$COMS);
		foreach $del (@d_) {if ($del eq $nam) {$COMS = "";}}
		if($COMS eq ""){ $n=""; }else{ $n="\n"; }
		push (@CAS,"$COMS$n");
	}
	open (DB,">$log");
	print DB @CAS;
	close(DB);
	@lines=@CAS;
}
if (-s $log) { $l_size = -s $log; }else{ $l_size = 0; }
$html.= <<"_HTML_";
<hr>ログサイズ/$l_size<br>
チェックを入れて削除<br>
編集はコメントをクリック
<form action="$cgi_f" method=$met>$nf
<input type=hidden name=mode value="del">
<input type=hidden name=pass value="$FORM{'pass'}">
_HTML_
$total=@lines;
$page_=int(($total-1)/$a_max);
if($FORM{'page'} eq ''){$page = 0;}else{$page=$FORM{'page'};}

$end_data=@lines - 1;
$page_end=$page + ($a_max - 1);
if($page_end >= $end_data){$page_end=$end_data;}

foreach ($page .. $page_end) {
	($namber,$date,$name,$email,$comment) = split(/<>/,$lines[$_]);
	$comment =~ s/<br>/ /g;
	if(length($comment)>16){$comment=substr($comment,0,14); $comment=$comment . '..'; }
	if($email ne "" && $diary==0){$name="<a href=\"mailto:$email\">$name</a>";}
	$html.= <<"_HTML_";
$namber/ <input type=checkbox name="del" value="$namber"><br>
$name<br>
<a href="$cgi_f?mode=nam&pass=$pass&kiji=$namber&no=$no">$comment</a><br><hr>
_HTML_
}
$html.= <<"_DEL_";
<br><br><input type=submit value="削除">
<input type=reset value="リセット"></form>
<form action="$cgi_f" method=$met>$nf
<input type=hidden name=mode value="del">
<input type=hidden name=pass value="$FORM{'pass'}">
No指定削除<br><input type=text size=4 name=del$MAX>半角数字
<br><input type=submit value="削除"></form>
<center>ページ<br>
_DEL_
$a=0;
for($i=0;$i<=$page_;$i++){
	$af=$page/$a_max;
	if($PC){$P=$page_; $M=0;}else{$P=$af+2; $M=$af-2;}
	if($i eq $af || $i > $P || $i < $M){$html.= "$i\n";}
	else{$html.= "<a href=\"$cgi_f?mode=del&page=$a&pass=$pass&no=$no\">$i</a>\n";}
	$a+=$a_max;
}
$html.= <<"_HTML_";
<hr><form action=$cgi_f method=$met>ログ初期化
<input type=hidden name=pass value="$FORM{'pass'}">$nf
<input type=hidden name=mode value="s_d"><input type=submit value="初期化する">
</form>
</center>
_HTML_
&foot_;
}
#
# [記事編集]
#
sub hen_ {
if ($FORM{'pass'} ne "$pass") { &er_("パスワードが違います!"); }
open(DB,"$log");
@lines = <DB>;
close(DB);

@new = ();
$flag = 0;
foreach $line (@lines) {
	($namber,$date,$name,$email,$comment) = split(/<>/,$line);
	if ($kiji eq "$namber") {
		&hed_;
		$comment =~ s/<br>/\n/g;
		if($tag){$comment=~ s/</&lt;/g; $comment=~ s/>/&gt;/g;}
		if($diary){$email=$date;}
		$html.= <<"_HTML_";
[<a href="$cgi_f?mode=del&pass=$pass&no=$no">戻</a>]<br>
-No.$namberの編集-
<form action="$cgi_f" method="$met">$nf
<input type=hidden name=pass value="$FORM{'pass'}">
<input type=hidden name=mode value=h_w>
<input type=hidden name=namber value=$namber>
$Form1<br><input type=text name="name" value="$name" size=16$MAX><br>
$Form2<br><input type=text name="email" value="$email" size=16$MAX><br>
コメント<br><textarea name="comment" rows=4 cols=16 wrap=$wrap>$comment</textarea><br><br>
<input type=submit value="編集">
<input type=reset value="リセット"></form>
_HTML_
&foot_;
	}
}
}
#
# [編集記事置換]
#
sub h_w_ {
open(DB,"$log");
@lines = <DB>;
close(DB);

@new = ();
$flag = 0;
foreach $line (@lines) {
	$line =~ s/\n//g;
	($knam,$kd,$kn,$kmail,$kcom) = split(/<>/,$line);
	if ($namber eq "$knam") {
		$line = "$namber<>$date<>$name<>$email<>$comment<>";
		$flag = 1;
	}
	push(@new,"$line\n");
}

if ($flag == 0) { &er_("編集記事ナンバーが不正です"); }
if ($flag == 1) {
	open (DB,">$log");
	print DB @new;
	close(DB);
}
}
#
# [ロック処理]
#
sub lock_ {
$lflag = 0;
foreach (1 .. 5) {if(mkdir($lockf, 0755)){$lflag=1; last;}else{sleep(1);}}
if ($lflag == 0) {
	if(-e $lockf){rmdir($lockf);}
	&er_("LOCK is BUSY (ロック中)","1");
}
}
#
# [URLリンク]
#
sub auto_ {
$_[0]=~ s/([^=^\"]|^)((http|ftp|https)\:[\w\.\~\-\/\?\&\+\=\:\@\%\;\#\,\|]+)/$1<a href=$2 target=_top>$2<\/a>/g;
}
#
# [カウンタ処理]
#
sub con_ {
if($locks){$lockf=$c_loc; &lock_;}
open(NO,"$c_f") || &er_("Can't open $c_f","1");
$cnt = <NO>;
close(NO);

if($FORM{'mode'} eq "" && $FORM{'page'} eq "" && $ENV{'HTTP_REFERER'} !~ /$cgi_f/){
	$cnt++;
	open(NO,">$c_f") || &er_("Can't write $c_f","1");
	print NO $cnt;
	close(NO);
}
if(-e $c_loc){rmdir($c_loc);}
if($mode eq ""){
	while(length($cnt) < $fig){ $cnt = 0 . $cnt; }
	@cnts = split(//,$cnt);
	$html.= "$cnt<br>";
}
}
#
# [エラー表示]
#
sub er_ {
if(-e $lockf && $_[1]==1){rmdir($lockf);}
&hed_;
$html.= "<center>[<a href=\"$cgi_f?no=$no\">戻</a>]<br>ERROR<br>$_[0]</center>\n";
&foot_;
}
#
# [メール機能]
#
sub mail_{
$subj="$title 投稿通知";

$Mail=<<"_MAIL_";
$subj
----------------
$name($email)
$date

$comment
-----------END--
_MAIL_
	if($email eq ""){ $email = 'nomail@xxx.xxx'; }
	$Mail=~ s/<br>/\n/g;
	$Mail=~ s/\&lt\;/</g;
	$Mail=~ s/\&gt\;/>/g;
	$Mail=~ s/\&quot\;/\"/g;
	$Mail=~ s/\&amp\;/&/g;
	&jcode'convert(*subj,'jis');
	&jcode'convert(*Mail,'jis');

	if(open(MAIL,"| $s_mail $mailad")){
	print MAIL 'X-Mailer: BBSI MAILER\n';
	print MAIL "To: $mailad\n";
	print MAIL "From: $email\n";
	print MAIL "Subject: $subj \n";
	print MAIL "MIME-Version: 1.0\n";
	print MAIL "Content-type: text/plain; charset=ISO-2022-JP\n";
	print MAIL "Content-Transfer-Encoding: 7bit\n\n";
	print MAIL "$Mail";
	close(MAIL);
	}
}
#
# [書き出し]
#
sub htmlp {
$len = length($html);
print "Content-type: text/html\n";
if($i_){print "Content-length: $len\n";}
print "\n";
print "$html";
exit;
}
#
# [ログ生成]
#
sub l_m {
open(DB,">$_[0]") || &er_("Can't write $_[0]","0");
print DB "";
close(DB);

chmod(0666,"$_[0]");
}
#
# [全設定ファイル先表示]
#
sub all_ {
&hed_;
$T=@set;
$html.="$T個のBBSが<br>利用可\能\<hr>";
foreach (0..$#set){
	if($set[$_]){
		unless(-e $set[$_]){$html.="$_)$set[$_]が無いです<br>";}
		else{
			require "$set[$_]"; $html.="$_)<a href=\"$cgi_f?no=$_\">$title</a><br>";
			if(-e $log){$html.=" ログ:○";}else{$html.=" ログ:×";}
			if($cou){if(-e $c_f){$html.="/カウンタ:○";}else{$html.="/カウンタ:×";}}
		}
	}
	$html.="<br><br>"
}
&foot_;
}
#
# [管理入室]
#
sub Edit {
&hed_;
$html.=<<_EDIT_;
<form action="$cgi_f" method=$met>
-認証-<br>
<input type=hidden name=mode value=del>$nf
Pass/<input type=password name=pass size=8><br>
<input type=submit value="認証">
</form>
_EDIT_
&foot_;
}
;# BBS-i SET UP FILE
;#
;# 新しい設定ファイルを作る場合、空のテキストを作成し以下の内容をコピーして設定してください。
;# ログファイルは自動で生成されます。
;#  *1) ログファイル、ロックファイルを作成するディレクトリのパーミッションは 777 or 755
;#  *2) 設定ファイルの拡張子はなるべく .cgi にしてください。
;#   *3) なるべくCGIと同じディレクトリに入れて下さい。

$met  = "POST";			# 送信形式(POST or GET(J-Skyの場合自動的にGETになります))
$back = "../index.html";	# 戻るURL(http://〜でもOK)
$pass = "7777";			# 管理用のパスワード
$title= "BBS-i";		# タイトル
$n_max= 16;			# 名前の限度(初期/半角16文字-全角8文字)
$c_max= 300;			# コメントの限度(初期/半角300文字-全角150文字)
$max  = 100;			# 最大記事保持件数
$a_max= 7;			# 1ページ表示件数
$locks= 0;			# ファイルをロックする?(1=YES 0=NO)
$body = '<body>';		# BODYタグ カラーに対応させる場合は text など設定可

# トップ上部のコメント(タグOK)
$com = <<"_COM_";

ページの感想を!

_COM_
# ↑は消しちゃダメ

$cou  = 0;			# カウンタの設置 (1=YES 0=NO)
$fig  = 5;			# カウンタの桁数
$c_f  = "./bic.dat";		# カウンタファイル
$c_loc= "./bic.loc";		# カウンタロック(使用は17行目に依存)
$wrap = "soft";			# フォームの改行形式(soft=手動 or hard=強制)
$cgi_f= "./bi.cgi";		# このファイル
$log  = "./bi.dat";		# 記録ファイル
$lockf= "./bi.loc";		# ロックファイル(使用は17行目に依存)
$t_mail= 0;			# 投稿があるとメール通知する?(1=YES 0=NO)
$mailad= 'user@host.ne.jp';	# 通知するメールアドレス
$s_mail= '/usr/lib/sendmail';	# sendmailパス
$mymail= 0;			# 自分の記事も送信する?(1=YES 0=NO)
$diary = 0;			# 日記モード?(1=YES 0=NO)

# アクセス対象は?
# => (0=とくに無し 1=J-Sky 2=i-mode 3=ドットi 4=対応携帯端末すべて 5=ezweb(簡易対応)
$access= 0;

1;#削除不可