#!/usr/bin/perl

## Light Board 補助プログラム
## 過去ログ表示・検索システム
## light2.cgi (1999/11/08)
## (c)1997-1999 KENT WEB

require './jcode.pl';			# jcode.plが同一ディレクトリの場合

## 基本設定
$script = './light2.cgi';		# スクリプト名
$bbsfile  = './light.cgi';		# 掲示板への戻り先
$body = '<body bgcolor="#F5F5F5">';	# bodyタグ
$method = 'POST';			# method形式 (POST or GET)
$pass = 'cai0803';				# 管理用パスワード
$logfile = './light.log';		# LIGHT BOARDログファイル
$lockkey = 0;				# ロック形式 (0=no 1=symlink 2=open)
$lockfile = './light.lock';		# ロックファイル名
$mail = 1;				# メール通知機能 (0=no 1=yes)
$tagkey = 0;				# タグの使用 (0=no 1=yes)

## 過去ログ設定
$nofile = './pastno.dat';		# 過去ログ用カウントファイル
$past_dir = ".";			# 過去ログのあるディレクトリ（フルパスだと / から）
$past_url = ".";			# 過去ログのあるＵＲＬディレクトリ
					# （フルパスだと http:// から）

## 設定完了

# 過去ログカウントファイルを読み込み
if (open(NUM,"$nofile")) {
$count = <NUM>;
close(NUM);
}

## -------- メイン処理 --------------------------------- ##

&get_form;
if (!$buffer) { &frame; }
&decode;

if ($mode eq 'ue_html') { &ue_html; }
if ($mode eq 'find_html') { &find_html; }
if ($mode eq 'do_find') { &do_find; }
if ($mode eq 'edit_in') { &edit_in; }
if ($mode eq 'edit') { &edit; }
if ($mode eq 'do_edit') { &do_edit; }
#if ($mode eq 'env') { &env_view; }
if ($mode eq 'env_edit') { &env_edit }

exit;

## --------- 処理完了 ---------------------------------- ##

## ログ編集モード入室処理
sub edit_in {
	&header;
	print "<table width=100%><tr><th bgcolor=#0000a0>\n";
	print "<font color=#FFFFFF>管 理 モ ー ド</font></th></tr></table>\n";
	print "<P><center><B>処理オプションを選択し、パスワードを入力して下さい</B><P>\n";
	print "<form action=\"$script\" method=$method>\n";
	print "<input type=radio name=opt value=\"edit\" checked>記事編集\n";
	print "<input type=radio name=opt value=\"del\">記事削除\n";
	print "<input type=radio name=opt value=\"env\">環境設定<P>\n";
	print "<input type=hidden name=mode value=\"edit\">\n";
	print "<input type=password name=pass size=8>";
	print "<input type=submit value=\"認証\">\n";
	print "</form>\n</body></html>\n";
}

## ログ編集画面
sub edit {
	# パスワード認証
	if ($pass ne "$FORM{'pass'}") { &error("パスワードが違います。"); }

	open(DB,"$logfile") || &error("Can't open $logfile");
	@lines = <DB>;
	close(DB);

	$init = $lines[0];
	shift(@lines);

	&header;
	print "[<a href=$bbsfile target=_top>掲示板へ戻る</a>]\n";
	print "<table width=100%><tr><th bgcolor=#0000a0>\n";
	print "<font color=#FFFF00>管 理 モ ー ド</font></th></tr></table>\n";
	print "<P><center>\n";

	if ($mode ne 'do_edit') {
		if ($chk && $opt eq 'edit') { &form_edit; }
		elsif ($chk && $opt eq 'del') { &do_del; }
		elsif ($opt eq 'env') { &env_view; }
	}

	if ($opt eq 'edit') { print "編集する記事をチェックして編集ボタンを押して下さい。\n"; }
	else { print "削除する記事をチェックして削除ボタンを押して下さい。\n"; }

	print "<P><form action=\"$script\" method=$method>\n";
	print "<input type=hidden name=mode value=\"edit\">\n";
	print "<input type=hidden name=opt value=\"$opt\">\n";
	print "<input type=hidden name=pass value=\"$FORM{'pass'}\">\n";
	print "<table border=1>\n";
	print "<tr><th>CHK</th><th>投稿日</th><th>題名</th>\n";
	print "<th>なまえ</th><th>メール</th><th>コメント</th></tr>\n";

	foreach $line (@lines) {
		($num,$date,$name,$email,$sub,$com,$url,$host) = split(/<>/,$line);
		if (length($com) > 60) { $com=substr($com,0,58); $com=$com . '..'; }
		  $com =~ s/\</&lt\;/g;
		  $com =~ s/\>/&gt\;/g;
		  $com =~ s/\"/&quot\;/g;

		if ($email) { $email = "<a href=mailto:$email>$email</a>"; }
		if ($url) { $name = "<a href=http://$url target=_top>$name</a>"; }
		if ($sub eq "") { $sub = "(無題)"; }

		if ($opt eq 'edit') {
		  print "<tr><th><input type=radio name=chk value=$num>$num</th>";
		} else {
		  print "<tr><th><input type=checkbox name=chk value=$num>$num</th>";
		}

		print "<td>$date</td><td>$sub</td><td>$name</td><td>$email</td>\n";
		print "<td>$com <font color=#800000>[$host]</font></td></tr>\n";
	}

	print "</table><P><input type=submit value=\"メンテ処理を行う\">";
	print "<input type=reset value=\"リセット\">\n";
	print "</form></center>\n";
	print "</body></html>\n";
}

## 編集フォーム
sub form_edit {
	foreach $line (@lines) {
		($num,$date,$name,$email,$sub,$com,$url,$host,$pwd) = split(/<>/,$line);
		if ($chk eq "$num") { last; }
	}

	# タグ処理
	if ($tagkey == 0) {
		$com =~ s/&lt\;/\</g;
		$com =~ s/&gt\;/\>/g;
		$com =~ s/&quot\;/\"/g;
	} else {
		$com =~ s/\</&lt\;/g;
		$com =~ s/\>/&gt\;/g;
		$com =~ s/\"/&quot\;/g;
	}

	$com =~ s/<br>/\r/g;
	if ($url) { $url = "http://$url"; }

	print <<"EOM";
<center><b>変更する部分のみ修正して下さい</b><P>
<form action="$script" method="$method">
<input type=hidden name=mode value="do_edit">
<input type=hidden name=opt value="$opt">
<input type=hidden name=pass value="$FORM{'pass'}">
<input type=hidden name=chk value="$chk">
<table border=1>
<tr><td><b>おなまえ</b></td><td><input type=text name=name value="$name" size=25></td></tr>
<tr><td><b>Ｅメール</b></td><td><input type=text name=email value="$email" size=25></td></tr>
<tr><td><b>タイトル</b></td><td><input type=text name=sub value="$sub" size=30>
<input type=submit value="修正する"><input type=reset value="リセット"></td></tr>
<tr><td colspan=2><b>コメント</b><br><textarea cols=65 rows=7 name=com>$com</textarea></td></tr>
<tr><td><b>ＵＲＬ</b></td><td><input type=text name=url value="$url" size=50></td></tr>
</table>
</form>
</center>
</body></html>
EOM
	exit;
}

## 編集実行処理
sub do_edit {
	# パスワード認証
	if ($pass ne "$FORM{'pass'}") { &error("パスワードが違います。"); }

	# ロック開始
	if ($lockkewy == 1) { &lock1; }
	elsif ($lockkey == 2) { &lock2; }

	open(DB,"$logfile") || &error("Can't open $logfile");
	@lines = <DB>;
	close(DB);

	$init = $lines[0];
	shift(@lines);

	if ($tagkey) {
		$FORM{'com'} =~ s/<>/&lt;&gt;/g;
	} else {
		$FORM{'com'} =~ s/</&lt;/g;
		$FORM{'com'} =~ s/>/&gt;/g;
		$FORM{'com'} =~ s/\"/&quot;/g;
	}
	$FORM{'com'} =~ s/\r\n/<br>/g;
	$FORM{'com'} =~ s/\r|\n/<br>/g;
	$FORM{'url'} =~ s/^http\:\/\///;

	@new=();
	foreach $line (@lines) {
		($num,$date,$name,$email,$sub,$com,$url,$host,$pwd) = split(/<>/,$line);
		if ($chk eq "$num") {
			$line = "$num<>$date<>$FORM{'name'}<>$FORM{'email'}<>$FORM{'sub'}<>$FORM{'com'}<>$FORM{'url'}<>$host<>$pwd<>\n";
		}
		push(@new,$line);
	}

	unshift(@new,$init);

	open(DB,">$logfile") || &error("Can't write $logfile");
	print DB @new;
	close(DB);

	unlink($lockfile) if (-e $lockfile);

	&edit;
}

## 削除処理
sub do_del {
	@new=();
	foreach $line (@lines) {
		($num,$date,$name,$email,$sub,$com,$url,$host,$pwd) = split(/<>/,$line);
		$flag=0;
		foreach $chk (@dels) {
			if ($chk eq "$num") { $flag=1; next; }
#			else { next; }
		}
		if ($flag == 0) { push(@new,$line); }
	}

	@lines = @new;

	unshift(@new,$init);

	open(DB,">$logfile") || &error("Can't write $logfile");
	print DB @new;
	close(DB);

	unlink($lockfile) if (-e $lockfile);
}

## 環境設定画面
sub env_view {
	($head,$title,$t_color,$t_size,$t_face,$bgr,$bgc,$text,$link,$vlink,$alink,$home,
	$max,$subj_color,$name_color,$mail1,$mail2) = split(/<>/,$init);

	print <<"EOF";
</center><blockquote>
<UL>
<LI>設定ファイル <font color=#CE0067><b>$room</b></font> の修正を行います。
<LI>変更したい個所を修正し、送信キーを押してください。
<LI>タグは書き込まないようにしてください。
</UL>
<form action="$script" method="$method">
<table>
<tr><td colspan=2><hr></td></tr>
<tr><td>タイトル</td><td><input type=text name=title size=25 value="$title"></td></tr>
<tr>
  <td>サイズ</td>
  <td>
    <select name=t_size>
    <option value=$t_size>$t_size
    <option value=8>8
    <option value=7>7
    <option value=6>6
    <option value=5>5
    <option value=4>4
    </select>
  </td>
</tr>
<tr><td>タイトル色</td><td><input type=text name=t_color size=25 value="$t_color"></td></tr>
<tr><td>文字スタイル</td><td><input type=text name=t_face size=25 value="$t_face"></td></tr>
<tr><td colspan=2><hr></td></tr>
<tr><td>壁紙</td><td><input type=text name=bgr size=25 value="$bgr"></td></tr>
<tr><td>背景色</td><td><input type=text name=bgc size=25 value="$bgc"></td></tr>
<tr><td>文字色</td><td><input type=text name=text size=25 value="$text"></td></tr>
<tr><td>リンク色</td><td><input type=text name=link size=25 value="$link">(link)</td></tr>
<tr><td>リンク色</td><td><input type=text name=vlink size=25 value="$vlink">(vlink)</td></tr>
<tr><td>リンク色</td><td><input type=text name=alink size=25 value="$alink">(alink)</td></tr>
<tr><td colspan=2><hr></td></tr>
<tr><td>記事 [題名] 色</td><td><input type=text name=subj_color size=25 value="$subj_color"></td></tr>
<tr><td>記事 [名前] 色</td><td><input type=text name=name_color size=25 value="$name_color"></td></tr>
<tr><td colspan=2><hr></td></tr>
<tr><td>戻り先</td><td><input type=text name=home size=50 value="$home"></td></tr>
<tr><td>最大記事数</td><td><input type=text name=max size=25 value="$max"></td></tr>
<tr><td colspan=2><hr></td></tr>
EOF
	if ($mail) {
		print "<tr><td>メール送信 1.</td><td><input type=text name=mail1 size=25 value=\"$mail1\"></td></tr>\n";
		print "<tr><td>メール送信 2.</td><td><input type=text name=mail2 size=25 value=\"$mail2\"> (2つ目以降はここに記述)</td></tr>\n";
		print "<tr><td colspan=2><LI>ここにメールアドレスを記入すると投稿記事を送信します。</td></tr>\n";
		print "<tr><td colspan=2><hr></td></tr>\n";
	}

	print "<tr><th colspan=2><input type=submit value=\"送信する\"><input type=reset value=\"リセット\"></th></tr>\n";
	print "<input type=hidden name=mode value=\"env_edit\">\n";
	print "<input type=hidden name=pass value=\"$FORM{'pass'}\">\n";
	print "</form></table></blockquote>\n";
	print "</body></html>\n";
	exit;
}

## 環境設定更新処理
sub env_edit {
	# パスワード認証
	if ($pass ne "$FORM{'pass'}") { &error("パスワードが違います。"); }

	# ロック開始
	if ($lockkewy == 1) { &lock1; }
	elsif ($lockkey == 2) { &lock2; }

	open(DB,"$logfile") || &error("Can't open $logfile");
	@lines = <DB>;
	close(DB);

	($head,$title,$t_color,$t_size,$t_face,$bgr,$bgc,$text,$link,$vlink,$alink,$home,$max,$subj_color,$name_color,$mail1,$mail2) = split(/<>/,$lines[0]);

	$lines[0] = "$head<>$FORM{'title'}<>$FORM{'t_color'}<>$FORM{'t_size'}<>$FORM{'t_face'}<>$FORM{'bgr'}<>$FORM{'bgc'}<>$FORM{'text'}<>$FORM{'link'}<>$FORM{'vlink'}<>$FORM{'alink'}<>$FORM{'home'}<>$FORM{'max'}<>$FORM{'subj_color'}<>$FORM{'name_color'}<>$FORM{'mail1'}<>$FORM{'mail2'}<>\n";

	# ログを更新
	open(DB,">$logfile") || &error("Can't write $logfile");
	print DB @lines;
	close(DB);

	unlink($lockfile) if (-e $lockfile);

	# 完了メッセージ
	&header;
	print "<br><br><center><hr><h3>環境設定の変更が完了しました。</h3><hr>\n";
	print "<P>[<a href=\"$bbsfile\">掲示板へもどる</a>]</center>\n";
	print "</body></html>\n";

	exit;
}

## 検索処理ルーチン
sub do_find {
	# カウントファイルを読み込み
	open(NUM,"$nofile") || &error("Can't open $nofile");
	$count = <NUM>;
	close(NUM);

	@lines = ();
	foreach (1 .. $count) {
		open(DB,"$past_dir\/$_\.html");
		@new_data = <DB>;
		close(DB);

		push(@lines,@new_data);
	}

	$word =~ s/　/ /g;
	$word =~ s/\t/ /g;
	@pairs = split(/ /,$word);

	# 過去ログファイルを読み込み
	foreach $line (@lines) {
		$flag = 0;
		foreach $pair (@pairs){
			if (index($line,$pair) >= 0){
				$flag = 1;
				if ($cond eq 'or') { last ; }
			} else {
				if ($cond eq 'and'){ $flag = 0; last; }
			}
		}
		# ヒットした行を新規配列(@new)に格納
		if ($flag) { push(@new,$line) ; }
	}

	# 検索結果の配列数を数える
	$count = @new;

	# 該当なしの場合
	if ($count == 0) { &nainai; }

	# 結果を出力
	&header;
	print <<"HTML";
<center><table border=1>
<tr bgcolor=#FFFFFF>
<td>[<a href="$script?mode=find_html">検索画面に戻る</a>]</td>
<td nowrap>キーワード <font color=#FF0080><b>$word</b></font> は
<b>$count</b>件見つかりました。</td></tr></table>
</center><hr>
HTML

	foreach $new_line (@new) {
		($title,$msg) = split(/\<\!\-\-T\-\-\>/,$new_line);
		print "$title $msg\n";
	}
	print "</body></html>\n";
	exit;
}

## フレーム部
sub frame {
	# 過去ログ用カウントファイルをチェック
	unless (-e $nofile) { &error("Don't exist $nofile"); }

	print "Content-type: text/html\n\n";
	print <<"HTML";
<html>
<frameset rows="95\,*" FRAMEBORDER=no BORDER=0>
<frame name="ue" src="$script?mode=ue_html" target="sita">
<frame name="sita" src="$past_url\/$count\.html">
<noframes>
$body
<h3>フレーム非対応のブラウザの方は利用できません。</h3>
</body></noframes></frameset>
</html>
HTML
	exit;
}

## 上フレーム（メニュー部）
sub ue_html {
	&header;
	print <<"HTML";
<table width=100%>
<tr><th bgcolor=#8080C0>
<font color=#FFFFFF>過去ログ</font>
</th></tr></table>
<hr size=1><center>
[<a href="$bbsfile" target="_top">掲示板へもどる</a>]
[<a href="$script\?mode=find_html" target="sita">過去ログ検索</a>]
[<a href="$past_url\/$count\.html" target="sita">最新</a>]
HTML
	# 過去ログの[リンク]を新規順に表示
	for ($i=$count-1; $i>0; $i--) {
		print "\[<a href=\"$past_url\/$i\.html\" target=\"sita\">$i</a>\]\n";
	}
	print "</center><hr size=1>\n";
	exit;
}

## フォーム取得
sub get_form {
	if ($ENV{'REQUEST_METHOD'} eq "POST") {read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});}
	else { $buffer = $ENV{'QUERY_STRING'}; }
}

## フォームからのデータ処理
sub decode {
	@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');

		if ($name eq 'chk') { push(@dels,$value); }

		$FORM{$name} = $value;
	}
	$word = $FORM{'word'};
	$cond = $FORM{'cond'};
	$mode = $FORM{'mode'};
	$opt  = $FORM{'opt'};
	$chk  = $FORM{'chk'};
}

## 検索該当なし
sub nainai {
	&header;
	print "<center>見つかりませんでした。<hr>\n";
	print "<b>$word</b></center>\n";
	print "</body></html>\n";
	exit;
}

## 検索初期画面
sub find_html {
	&header;
	print <<"HTML";
<table width=100%>
<tr><th bgcolor=#8080C0>
<font color=#FFFFFF>過去ログ検索</font>
</th></tr></table>
<P><center>
<table width=80%><td>
<font color=#006400>
<OL>
<LI>「過去ログ」を<b>キーワード</b>から該当記事を検索します。
<LI><b>半角スペース</b>で区切って複数のキーワード指定が可\能\です。
<LI><b>検索条件</b>を選択し「検索する」ボタンを押して下さい。
</OL>
</font>
</td></table>
<form action="$script" method="$method">
<input type=hidden name=mode value="do_find">
<table border=1>
<tr><td>キーワード</td><td><input type=text name=word size=30></td></tr>
<tr><td>検索条件</td><td><input type=radio name=cond value="and" checked>AND
<input type=radio name=cond value="or">OR</td></tr>
<tr><th colspan=2><input type=submit value="検索する"></th></tr>
</table>
</form></center>
<hr>
<body></html>
HTML
	exit;
}

## HTMLヘッダー部
sub header {
	print "Content-type: text/html\n\n";
	print "<html>\n<head>\n";
	print "<META HTTP-EQUIV=\"Content-type\" CONTENT=\"text/html; charset=x-sjis\">\n";
	print "<title>編集ファイル</title></head>\n";
	print "$body\n";
}

## エラー処理
sub error {
	unlink($lockfile) if (-e $lockfile);
	&header;
	print "<center><hr width=75%><h3>システムエラー発生！</h3>\n";
	print "<P><font color=#DD0000><B>$_[0]</B></font>\n";
	print "<P><hr width=75%></center>\n";
	print "</body></html>\n";
	exit;
}

### --- ロックファイル（symlink関数）--- ###
sub lock1 { 
	local($retry) = 5;
	while (!symlink(".", $lockfile)) {
		if (--$retry <= 0) { &error("LOCK is BUSY"); }
		sleep(1);
	}
}

## --- ロックファイル（open関数）処理サブルーチン
sub lock2 {
	local($flag) = 0;
	foreach (1 .. 5) {
		unless (-e $lockfile) {
			open(LOCK,">$lockfile");
			close(LOCK);
			$flag = 1;
			last;
		} else {
			sleep(1);
		}
	}
	if ($flag == 0) { &error("LOCK is BUSY"); }
}
