#!/usr/bin/perl

#┌─────────────────────────────────
#│ Web Forum : wforum.cgi - 2013/05/31
#│ Copyright (c) KentWeb
#│ http://www.kent-web.com/
#└─────────────────────────────────

# モジュール宣言
use strict;
use CGI::Carp qw(fatalsToBrowser);
use lib "./lib";
use CGI::Minimal;

# 外部ファイル取込み
require './init.cgi';
my %cf = init();

# データ受理
CGI::Minimal::max_read_size($cf{maxdata});
my $cgi = CGI::Minimal->new;
error('容量オーバー') if ($cgi->truncated);
my %in = parse_form($cgi);

# アクセス制限
&passwd(%in) if ($cf{enter_pwd} ne '');

# 処理分岐
my $mode = $in{mode};
if ($mode eq "read") { read_log(); }
elsif ($mode eq "relate") { relate_log(); }
elsif ($mode eq "find") { find_form(); }
elsif ($mode eq "note") { note_page(); }
elsif ($mode eq "past") { past_page(); }
bbs_list();

#-----------------------------------------------------------
#  リスト表示
#-----------------------------------------------------------
sub bbs_list {
	# ツリー展開
	my ($list,$i) = open_tree($cf{logfile},'cur');

	# クッキー取得
	my @cook = get_cookie();
	$cook[2] ||= 'http://';

	# プルダウン作成（メール表示）
	my $op_smail = make_ops($cook[3]);

	# ページ移動ボタン
	my $pgbtn = page_btn($i,'cur');

	# テンプレート認識
	open(IN,"$cf{tmpldir}/list.html") or error("open err: list.html");
	my $tmpl = join('', <IN>);
	close(IN);

	# 画像認証作成
	my ($str_plain,$str_crypt);
	if ($cf{use_captcha} > 0) {
		require $cf{captcha_pl};
		($str_plain, $str_crypt) = cap::make($cf{captcha_key},$cf{cap_len});
	} else {
		$tmpl =~ s/<!-- captcha_begin -->.+<!-- captcha_end -->//s;
	}

	# 画像投稿
	if (!$cf{image_upl}) {
		$tmpl =~ s/<!-- image_begin -->.+<!-- image_end -->//s;
	}

	# 過去ログ
	if ($cf{pastkey} == 0) {
		$tmpl =~ s/<!-- pastlog_begin -->.+<!-- pastlog_end -->//s;
	}

	# home or logoff
	my $home = $cf{enter_pwd} eq '' ? $cf{homepage} : "$cf{bbs_cgi}?mode=logoff";

	# 文字置き換え
	$tmpl =~ s/<!-- list_tree -->/$list/g;
	$tmpl =~ s/<!-- page_btn -->/$pgbtn/g;
	$tmpl =~ s/!([a-z]+_cgi)!/$cf{$1}/g;
	$tmpl =~ s/!str_crypt!/$str_crypt/g;
	$tmpl =~ s/!homepage!/$home/g;
	$tmpl =~ s/!new_mark!/$cf{new_mark}/g;
	$tmpl =~ s/!new_time!/$cf{new_time}/g;
	$tmpl =~ s/!treehead!/$cf{treehead}/g;
	$tmpl =~ s/!bbs_title!/$cf{bbs_title}/g;

	# クッキー表示
	$tmpl =~ s/!name!/$cook[0]/;
	$tmpl =~ s/!email!/$cook[1]/;
	$tmpl =~ s/!url!/$cook[2]/;
	$tmpl =~ s/<!-- op_smail -->/$op_smail/;

	# 表示
	print "Content-type: text/html; charset=shift_jis\n\n";
	footer($tmpl);
}

#-----------------------------------------------------------
#  リストツリー表示
#-----------------------------------------------------------
sub open_tree {
	my ($file,$stat) = @_;

	my $param;
	if ($stat eq 'cur') {
		$param = "mode";
	} else {
		$in{pno} =~ s/\D//g;
		$param = "mode=past&pno=$in{pno}&job";
	}

	# ページ数
	$in{page} ||= 0;

	# 時間取得
	my $time = time;

	# リストタグ開始
	my $list;
	$list .= "<dl>\n" if ($stat eq 'cur');
	$list .= "<ul>\n";

	# ファイル展開
	my $i = 0;
	my $x = 0;
	open(IN,"$file") or error("open err: $file");
	my $top = <IN> if ($stat eq "cur");
	while (<IN>) {
		my ($no,$reno,$lx,$sub,$email,$url,$name,$dat,$msg,$tm,$h,$pw,$w,$oya) = split(/<>/);
		if ($reno == 0) { $i++; }
		next if ($i < $in{page} + 1);
		next if ($i > $in{page} + $cf{p_tree});

		while ($x > $lx) {
			$list .= "</ul>\n";
			$x--;
		}
		while ($x < $lx) {
			$list .= "<ul>\n";
			$x++;
		}
		if ($reno == 0) {
			while ($x > 0) {
				$list .= "</ul>\n";
				$x--;
			}
		}

		# 所定時間以内の投稿は[NEWマーク]表示
		my $newsign;
		if ($stat eq "cur" && $time - $tm < $cf{new_time} * 3600) {
			$newsign = $cf{new_mark};
		}

		# 削除記事
		if ($pw eq 'DEL') {
			if ($lx == 0) {
				if ($stat eq 'cur') {
					$list .= qq|<dt class="p"><a href="$cf{bbs_cgi}?$param=relate&no=$no&page=$in{page}">$cf{treehead}</a> - |;
				} else {
					$list .= "<li>";
				}
				$list .= qq|$sub - $dat <span class="num">No.$no</span>\n|;
			} else {
				$list .= qq|<li>$sub - $dat <span class="num">No.$no</span>\n|;
			}

		# レス記事
		} elsif ($lx != 0) {
			$list .= qq|<li><a href="$cf{bbs_cgi}?$param=read&no=$no&reno=$reno&oya=$oya&page=$in{page}#$no">$sub</a> - <b>$name</b> $dat <font color="$cf{num_st_col}">No.$no</font> $newsign\n|;

		# 親記事
		} else {
			if ($stat eq 'cur') {
				$list .= qq|<dt class="p"><a href="$cf{bbs_cgi}?$param=relate&no=$no&page=$in{page}">$cf{treehead}</a> - |;
			} else {
				$list .= qq|<li>|;
			}
			$list .= qq|<a href="$cf{bbs_cgi}?$param=read&no=$no&reno=$reno&oya=$oya&page=$in{page}#$no">$sub</a> - <b>$name</b> $dat <font color="$cf{num_st_col}">No.$no</font> $newsign\n|;
		}
	}
	close(IN);

	# リストタグ閉じ処理
	while ($x > 0) {
		$list .= "</ul>\n";
		$x--;
	}
	$list .= "</ul>\n";
	$list .= "</dl>\n" if ($stat eq 'cur');

	# 返り値
	return ($list,$i);
}

#-----------------------------------------------------------
#  記事閲覧
#-----------------------------------------------------------
sub read_log {
	my ($flg,@new,%r,%v);
	open(IN,"$cf{logfile}") or error("open err: $cf{logfile}");
	my $top = <IN>;
	while (<IN>) {
		chomp;
		my ($no,$re,$lx,$sub,$eml,$url,$nam,$dat,$msg,$lt,$ho,$pw,$wrap,$oya,$sml,$res,$ex,$w,$h) = split(/<>/);

		if ($in{oya} == $oya) { push(@new,$_); }
		elsif ($flg && $in{oya} != $oya) { last; }

		if ($in{no} == $no) {
			$flg = 1;
			$r{name}  = $nam;
			$r{email} = $eml;
			$r{url} = $url;
			$r{msg} = $msg;
			$r{tim} = $lt;
			$r{sub} = $sub;
			$r{sml} = $sml;
			$r{ext} = $ex;
			$r{w}   = $w;
			$r{h}   = $h;
		}
	}
	close(IN);

	# レスメッセージ
	my %c;
	$c{message} = "\n&gt; $r{msg}";
	$c{message} =~ s/<br>/\n&gt; /g;

	# レスタイトル
	if ($r{sub} =~ /^Re\^(\d+)\:(.*)/) {
		my $renum = $1 + 1;
		$c{sub} = "Re\^$renum:$2";
	}
	elsif ($r{sub} =~ /^Re\:(.*)/) { $c{sub} = "Re\^2:$1"; }
	else { $c{sub} = "Re: $r{sub}"; }

	# 自動リンク
	$r{msg} = autolink($r{msg}) if ($cf{autolink});

	# 引用部色変更
	if ($cf{ref_col}) {
		$r{msg} =~ s/([\>]|^)(&gt;[^<]*)/$1<font color="$cf{ref_col}">$2<\/font>/g;
	}

	# 画像付加
	$r{msg} = put_image($in{no},$r{msg},$r{ext},$r{w},$r{h}) if ($r{ext});

	# 投稿日時
	$r{date} = get_time($r{tim});

	# e-mail表記
	if ($r{email} && $r{sml} eq '0') {
		$r{email} = qq|&nbsp; &lt;<a href="mailto:$r{email}" class="num">$r{email}</a>&gt;|;
	} else {
		$r{email} = '';
	}

	# URL表記
	$r{url} &&= qq|<a href="$r{url}" target="_top" class="num">$r{url}</a>|;

	# 関連ツリー作成
	my $tree;
	my $x = 0;
	$tree .= "<ul>\n";
	foreach (@new) {
		my ($no,$re,$lx,$sub,$eml,$url,$nam,$dat,$msg,$lt,$ho,$pw,$wrap,$oya,$sml,$res,$ex,$w,$h) = split(/<>/);

		while ($x > $lx) { $tree .= "</ul>\n"; $x--; }
		while ($x < $lx) { $tree .= "<ul>\n"; $x++; }

		if ($lx != 0) {
			$tree .= qq|<li><a href="$cf{bbs_cgi}?no=$no&reno=$re&oya=$oya&mode=read&page=$in{page}">$sub</a> - <B>$nam</B> $dat |;
		} else {
			$tree .= qq|<a href="$cf{bbs_cgi}?mode=relate&no=$no&page=$in{page}">$cf{treehead}</a> - <a href="$cf{bbs_cgi}?no=$no&reno=$re&oya=$oya&mode=read&page=$in{page}">$sub</a> - <B>$nam</B> $dat|;
		}

		if ($in{no} == $no) {
			$tree .= qq| <b style="color:$cf{num_em_col}">No.$no</b>\n|;
		} else {
			$tree .= qq| <span style="color:$cf{num_st_col}">No.$no</span>\n|;
		}
	}
	while ($x > 0) { $tree .= "</ul>\n"; $x--; }
	$tree .= "</ul>\n";

	# クッキー取得
	($c{name},$c{email},$c{url},$c{smail}) = get_cookie();
	$c{url} ||= 'http://';

	# プルダウン作成（メール表示）
	my $op_smail = make_ops($c{smail});

	# 記事番号
	$c{num} = $in{no};
	$c{oya} = $in{oya};

	# テンプレート認識
	open(IN,"$cf{tmpldir}/read.html") or error("open err: read.html");
	my $tmpl = join('', <IN>);
	close(IN);

	# 画像認証作成
	my ($str_plain,$str_crypt);
	if ($cf{use_captcha} > 0) {
		require $cf{captcha_pl};
		($str_plain, $str_crypt) = cap::make($cf{captcha_key},$cf{cap_len});
	} else {
		$tmpl =~ s/<!-- captcha_begin -->.+<!-- captcha_end -->//s;
	}

	# 画像投稿
	if (!$cf{image_upl}) {
		$tmpl =~ s/<!-- image_begin -->.+<!-- image_end -->//s;
	}

	# 過去ログ
	if ($cf{pastkey} == 0) {
		$tmpl =~ s/<!-- pastlog_begin -->.+<!-- pastlog_end -->//s;
	}

	# 文字置き換え
	$tmpl =~ s/!bbs_title!/$cf{bbs_title}/g;
	$tmpl =~ s/!treehead!/$cf{treehead}/g;
	$tmpl =~ s/!([a-z]+_cgi)!/$cf{$1}/g;
	$tmpl =~ s/<!-- tree -->/$tree/g;
	$tmpl =~ s/!str_crypt!/$str_crypt/g;
	$tmpl =~ s/!r_(\w+)!/$r{$1}/g;
	$tmpl =~ s/!(\w+)!/$c{$1}/g;
	$tmpl =~ s/<!-- op_smail -->/$op_smail/;

	# 表示
	print "Content-type: text/html; charset=shift_jis\n\n";
	footer($tmpl);
}

#-----------------------------------------------------------
#  一括表示
#-----------------------------------------------------------
sub relate_log {
	my ($obi_ttl,$tree,$count);

	if ($in{job} eq "new") {
		$obi_ttl = '新着表示';
	} else {
		$obi_ttl = '一括表示';
		$tree .= "<ul>\n";
	}

	# 親記事を出力
	my $x = 0;
	my ($flg,@data,@sort,@file);
	open(IN,"$cf{logfile}") or error("open err: $cf{logfile}");
	my $top = <IN>;
	while (<IN>) {
		chomp;
		my ($no,$re,$lx,$sub,$eml,$url,$nam,$dat,$msg,$time,$ho,$pw,$wrap,$oya,$sml,$res,$ex,$w,$h) = split(/<>/);

		## 新着一括のとき
		if ($in{job} eq "new") {
			push(@file,$_);
			push(@sort,$time);

		## ツリー一括のとき
		} else {
			# 関連記事スタート
			if ($in{no} == $oya) {
				$flg = 1;
				push(@data,$_);

				while ($x > $lx) { $tree .= "</ul>\n"; $x--; }
				while ($x < $lx) { $tree .= "<ul>\n"; $x++; }

				if ($pw eq 'DEL') {
					$tree .= qq|<li>$sub - $dat <span class="num">No.$no</span>\n|;
				} else {
					$tree .= qq|<li><a href="#$no">$sub</a> - <B>$nam</B> $dat <span class="num">No.$no</span>\n|;
				}

			# 関連記事完了
			} elsif ($flg && $in{no} != $oya) {
				last;
			}
		}
	}
	close(IN);

	# 移動ボタン変数
	my $pgbtn;

	# 新着
	if ($in{job} eq "new") {
		my $i;
		foreach ( @file[ sort{ $sort[$b] <=> $sort[$a] } 0 .. $#sort ] ) {
			$i++;
			next if ($i < $in{page} + 1);
			next if ($i > $in{page} + $cf{new_pgbtn});

			push(@data,$_);
		}

		# ページ移動ボタン
		$pgbtn = new_pgbtn($i);

	# ツリー一括
	} else {
		while ($x > 0) { $tree .= "</ul>\n"; $x--; }
		$tree .= qq|</ul>\n<div align="center">\n|;
	}

	# テンプレート認識
	open(IN,"$cf{tmpldir}/relate.html") or error("open err: relate.html");
	my $tmpl = join('', <IN>);
	close(IN);

	# テンプレート分割
	my ($head,$loop,$foot) = $tmpl =~ /(.+)<!-- msg_begin -->(.+)<!-- msg_end -->(.+)/s
			? ($1,$2,$3) : &error("テンプレート不正");

	# 文字置き換え
	foreach ($head,$foot) {
		s/!obi_ttl!/$obi_ttl/g;
		s/<!-- tree -->/$tree/g;
		s/!bbs_cgi!/$cf{bbs_cgi}/g;
		s/!page_btn!/$pgbtn/g;
	}

	# 画面展開
	print "Content-type: text/html; charset=shift_jis\n\n";
	print $head;

	foreach (@data) {
		my ($no,$reno,$lx,$sub,$eml,$url,$name,$dat,$msg,$t,$ho,$pw,$wrap,$oya,$sml,$res,$ex,$w,$h) = split(/<>/);
		next if ($pw eq 'DEL');

		# 自動リンク
		$msg = autolink($msg) if ($cf{autolink});

		# 引用部色変更
		if ($cf{ref_col}) {
			$msg =~ s/([\>]|^)(&gt;[^<]*)/$1<font color="$cf{ref_col}">$2<\/font>/g;
		}
		# 画像付加
		$msg = put_image($no,$msg,$ex,$w,$h) if ($ex);

		# 日付
		my $date = get_time($t);

		# e-mail
		if ($eml && $sml eq '0') { $name = qq|<a href="mailto:$eml">$name</a>|; }
		# URL
		$url &&= qq|<a href="$url" target="_blank"><img src="$cf{ico_home}" class="icon"></a>|;

		my $tmp = $loop;
		$tmp =~ s/!sub!/$sub/g;
		$tmp =~ s/!num!/$no/g;
		$tmp =~ s/!date!/$date/g;
		$tmp =~ s/!name!/$name/g;
		$tmp =~ s/!url!/$url/g;
		$tmp =~ s/!msg!/$msg/g;
		$tmp =~ s/!bbs_cgi!/$cf{bbs_cgi}/g;
		$tmp =~ s/!reno!/$reno/g;
		$tmp =~ s/!oya!/$oya/g;
		print $tmp;
	}

	# フッタ
	footer($foot);
}

#-----------------------------------------------------------
#  留意事項
#-----------------------------------------------------------
sub note_page {
	open(IN,"$cf{tmpldir}/note.html") or error("open err: note.html");
	my $tmpl = join('', <IN>);
	close(IN);

	$tmpl =~ s/!treehead!/$cf{treehead}/g;

	print "Content-type: text/html; charset=shift_jis\n\n";
	print $tmpl;
	exit;
}

#-----------------------------------------------------------
#  検索フォーム
#-----------------------------------------------------------
sub find_form {
	my ($i,$pgbtn,@data) = search($cf{logfile},'cur') if ($in{word});

	# プルダウン作成（検索条件）
	my %op = make_op();

	# テンプレート認識
	open(IN,"$cf{tmpldir}/find.html") or error("open err: find.html");
	my $tmpl = join('', <IN>);
	close(IN);

	# テンプレート分割
	my ($head,$loop,$foot) = $tmpl =~ /(.+)<!-- msg_begin -->(.+)<!-- msg_end -->(.+)/s
			? ($1,$2,$3) : error("テンプレート不正");

	# 文字置き換え
	foreach ($head,$foot) {
		s/!bbs_cgi!/$cf{bbs_cgi}/g;
		s/!word!/$in{word}/g;
		s/<!-- op_(\w+) -->/$op{$1}/g;

		# ワード検索
		if ($in{word}) {
			s/!result!/$i/g;
			s/!page_btn!/$pgbtn/g;
		} else {
			s/<!-- find_begin -->.+<!-- find_end -->//s;
		}
	}

	# 画面展開
	print "Content-type: text/html; charset=shift_jis\n\n";
	print $head;

	foreach my $data (@data) {
		my ($no,$reno,$lx,$sub,$eml,$url,$name,$date,$msg,$t,$ho,$pw,$wrap,$oya,$sml,$res,$ex,$w,$h) = split(/<>/, $data);
		$msg = autolink($msg) if ($cf{autolink});

		# 引用部色変更
		if ($cf{ref_col}) {
			$msg =~ s/([\>]|^)(&gt;[^<]*)/$1<font color="$cf{ref_col}">$2<\/font>/g;
		}
		# 画像付加
		$msg = put_image($no,$msg,$ex,$w,$h) if ($ex);

		# 日時
		$date = get_time($t);


		my $tmp = $loop;
		$tmp =~ s/!sub!/$sub/g;
		$tmp =~ s/!num!/$no/g;
		$tmp =~ s/!date!/$date/g;
		$tmp =~ s/!name!/$name/g;

		$tmp =~ s/!msg!/$msg/g;
		$tmp =~ s/!bbs_cgi!/$cf{bbs_cgi}/g;
		$tmp =~ s/!reno!/$reno/g;
		$tmp =~ s/!oya!/$oya/g;
		print $tmp;
	}

	# フッタ
	footer($foot);
}

#-----------------------------------------------------------
#  検索実行
#-----------------------------------------------------------
sub search {
	my ($file,$stat) = @_;

	# 入力内容を整理
	if ($cf{conv_code} == 1) {
		require Jcode;
		$in{word} = Jcode->new($in{word})->sjis;
	}
	$in{word} =~ s/\x81\x40/ /g;
	my @wd = split(/\s+/, $in{word});

	# 表示数
	$in{view} =~ s/\D//g;
	$in{view} ||= 10;

	# ページ数
	$in{page} =~ s/\D//g;
	$in{page} ||= 0;

	# キーワード検索準備（Shift-JIS定義）
	my $ascii = '[\x00-\x7F]';
	my $hanka = '[\xA1-\xDF]';
	my $kanji = '[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC]';

	# ファイル展開
	my $i = 0;
	my @data;
	open(IN,"$file") or error("open err: $file");
	my $top = <IN> if ($stat eq 'cur');
	while (<IN>) {
		chomp;
		my ($no,$reno,$lx,$sub,$eml,$url,$name,$date,$msg,$t,$ho,$pw,$wrap,$oya,$sml,$res,$ex,$w,$h) = split(/<>/);
		next if ($pw eq 'DEL');

		# 検索
		my $flg;
		foreach my $wd (@wd) {
			if ("$sub $name $msg $url" =~ /^(?:$ascii|$hanka|$kanji)*?\Q$wd\E/i) {
				$flg++;
				if (!$in{cond}) { last; } # OR
			} else {
				if ($in{cond}) { $flg = 0; last; } # AND
			}
		}
		# 一致の場合
		if ($flg) {
			$i++;
			next if ($i < $in{page} + 1);
			next if ($i > $in{page} + $in{view});

			push(@data,$_);
		}
	}
	close(IN);

	# ページ移動ボタン
	my $pgbtn = &find_pgbtn($i,$stat);

	return ($i,$pgbtn,@data);
}

#-----------------------------------------------------------
#  検索用ページ移動ボタン
#-----------------------------------------------------------
sub find_pgbtn {
	my ($i,$stat) = @_;

	# 繰り越しページ定義
	my $next = $in{page} + $in{view};
	my $back = $in{page} - $in{view};

	# キーワードエンコード化
	my $enwd = url_enc($in{word});

	# パラメータ
	my $param;
	if ($stat eq 'cur') {
		$param = $mode;
	} else {
		$param = "$mode&pno=$in{pno}&find=1";
	}

	# ページ移動ボタン作成
	my ($x,$y,$z) = (1,0,0);
	my $pgbtn;
	while ($i > 0) {
		if ($in{page} == $y) {
			$pgbtn .= qq{| <b>$x</b>\n};
		} else {
			$z++;
			$pgbtn .= qq{| <a href="$cf{bbs_cgi}?mode=$param&page=$y&word=$enwd&view=$in{view}&cond=$in{cond}">$x</a>\n};
		}
		$x++;
		$y += $in{view};
		$i -= $in{view};
	}

	if ($z) {
		$pgbtn .= "|\n";
		return $pgbtn;
	} else {
		return;
	}
}

#-----------------------------------------------------------
#  新着用ページ移動ボタン
#-----------------------------------------------------------
sub new_pgbtn {
	my $i = shift;

	my $next = $in{page} + $cf{new_pgbtn};
	my $back = $in{page} - $cf{new_pgbtn};

	# ページ移動ボタン表示
	my ($x,$y,$z) = (1,0,0);
	my $pgbtn;
	while ($i > 0) {
		if ($in{page} == $y) {
			$pgbtn .= "| <b>$x</b>\n";
		} else {
			$z++;
			$pgbtn .= qq{| <a href="$cf{bbs_cgi}?mode=relate&job=new&page=$y">$x</a>\n};
		}
		$x++;
		$y += $cf{new_pgbtn};
		$i -= $cf{new_pgbtn};
	}

	if ($z) {
		$pgbtn .= "|\n";
		return $pgbtn;
	} else {
		return;
	}
}

#-----------------------------------------------------------
#  過去ログ画面
#-----------------------------------------------------------
sub past_page {
	# 過去ログ番号
	open(IN,"$cf{nofile}") or error("open err: $cf{nofile}");
	my $pastnum = <IN>;
	close(IN);

	my $pastnum = sprintf("%04d", $pastnum);
	$in{pno} =~ s/\D//g;
	$in{pno} ||= $pastnum;

	# プルダウンタグ作成
	my $op_pno;
	for ( my $i = $pastnum; $i > 0; $i-- ) {
		$i = sprintf("%04d", $i);

		if ($in{pno} == $i) {
			$op_pno .= qq|<option value="$i" selected>$i\n|;
		} else {
			$op_pno .= qq|<option value="$i">$i\n|;
		}
	}

	# 初期化
	my ($list,$i,$pgbtn,@tree);

	# 記事閲覧
	if ($in{job} eq 'read') {

		@tree = past_read();

		$list = "<hr>\n<ul>\n";
		my $x = 0;
		foreach (@tree) {
			my ($no,$re,$lx,$sub,$eml,$url,$nam,$dat,$msg,$lt,$ho,$pw,$wrap,$oya,$sml) = split(/<>/);

			while ($x > $lx) { $list .= "</ul>\n"; $x--; }
			while ($x < $lx) { $list .= "<ul>\n"; $x++; }

			$list .= qq|<li><a href="#$no">$sub</a> - <B>$nam</B> $dat |;
			if ($in{no} == $no) {
				$list .= qq| <b style="color:$cf{num_em_col}">No.$no</b>\n|;
			} else {
				$list .= qq| <span style="color:$cf{num_st_col}">No.$no</span>\n|;
			}
		}
		while ($x > 0) { $list .= "</ul>\n"; $x--; }
		$list .= "</ul>\n";

	# ワード検索
	} elsif ($in{find} && $in{word} ne '') {

		# 対象ログ定義
		my $file = "$cf{pastdir}/" . sprintf("%04d", $in{pno}) . ".cgi";

		# 検索
		($i,$pgbtn,@tree) = &search($file, 'past');

		# 結果
		$list = "<blockquote>検索結果：<b>$i</b>件 &nbsp;&nbsp; $pgbtn</blockquote>\n";

	# 過去ログTOPリスト
	} else {

		# ツリー展開
		($list,$i) = open_tree("$cf{pastdir}/$in{pno}.cgi",'past');

		# ページ移動ボタン
		$pgbtn = page_btn($i,'past');
	}

	# プルダウン作成（検索条件）
	my %op = make_op();

	# テンプレート認識
	open(IN,"$cf{tmpldir}/past.html") or error("open err: past.html");
	my $tmpl = join('', <IN>);
	close(IN);

	# テンプレート分割
	my ($head,$loop,$foot) = $tmpl =~ /(.+)<!-- article_begin -->(.+)<!-- article_end -->(.+)/s
			? ($1,$2,$3) : &error("テンプレート不正");

	# 文字置き換え
	foreach ($head,$foot) {
		s/!past_num!/$in{pno}/g;
		s/<!-- op_pno -->/$op_pno/g;
		s/!bbs_cgi!/$cf{bbs_cgi}/g;
		s/<!-- list_tree -->/$list/g;
		s/<!-- page_btn -->/$pgbtn/g;
		s/!word!/$in{word}/g;
		s/<!-- op_(\w+) -->/$op{$1}/g;
	}

	# 画面展開
	print "Content-type: text/html; charset=shift_jis\n\n";
	print $head;

	my %p;
	foreach my $tree (@tree) {
		($p{num},$p{sub},$p{email},$p{url},$p{name},$p{date},$p{msg},$p{sml}) = (split(/<>/,$tree))[0,3..8,14];
		$p{msg} = &autolink($p{msg}) if ($cf{autolink});

		# 引用色
		if ($cf{ref_col}) {
			$p{msg} =~ s/([\>]|^)(&gt;[^<]*)/$1<font color="$cf{ref_col}">$2<\/font>/g;
		}

		# e-mail
		if ($p{email} && $p{sml} eq '0') {
			$p{email} = qq|&lt;<a href="mailto:$p{email}" class="num">$p{email}</a>&gt;|;
		} else {
			$p{email} = '';
		}
		# URL
		if ($p{url}) {
			$p{url} = qq|<a href="$p{url}" class="num">$p{url}</a>|;
		}

		my $tmp = $loop;
		$tmp =~ s/!(\w+)!/$p{$1}/g;
		print $tmp;
	}

	# フッタ
	footer($foot);
}

#-----------------------------------------------------------
#  フッター
#-----------------------------------------------------------
sub footer {
	my $foot = shift;

	# 著作権表記（削除・改変禁止）
	my $copy = <<EOM;
<p style="margin-top:2.5em;text-align:center;font-family:Verdana,Helvetica,Arial;font-size:10px;">
- <a href="http://www.kent-web.com/" target="_top">WebForum</a> -
</p>
EOM

	if ($foot =~ /(.+)(<\/body[^>]*>.*)/si) {
		print "$1$copy$2\n";
	} else {
		print "$foot$copy\n";
		print "</body></html>\n";
	}
	exit;
}

#-----------------------------------------------------------
#  過去記事閲覧
#-----------------------------------------------------------
sub past_read {
	my ($flg,@tree);
	open(IN,"$cf{pastdir}/$in{pno}.cgi");
	while(<IN>) {
		my ($no,$reno,$lx,$sub,$eml,$url,$name,$date,$msg,$t,$ho,$pw,$wrap,$oya,$sml) = split(/<>/);

		if ($in{oya} == $oya) { push(@tree,$_); }
		elsif ($flg && $in{oya} != $oya) { last; }
	}
	close(IN);

	return @tree;
}

#-----------------------------------------------------------
#  ページ移動ボタン
#-----------------------------------------------------------
sub page_btn {
	my ($i,$stat) = @_;

	# 繰り越しページ
	my $next = $in{page} + $cf{p_tree};
	my $back = $in{page} - $cf{p_tree};

	# ページ移動ボタン表示
	my ($x,$y,$z) = (1,0,0);
	my $pgbtn;
	while ($i > 0) {
		if ($in{page} == $y) {
			$pgbtn .= "| <b>$x</b>\n";

		} elsif ($stat eq 'past') {
			$z++;
			$pgbtn .= qq{| <a href="$cf{bbs_cgi}?page=$y&mode=past&pno=$in{pno}">$x</a>\n};

		} else {
			$z++;
			$pgbtn .= qq{| <a href="$cf{bbs_cgi}?page=$y">$x</a>\n};
		}
		$x++;
		$y += $cf{p_tree};
		$i -= $cf{p_tree};
	}

	if ($z) {
		$pgbtn .= "|\n";
		return $pgbtn;
	} else {
		return;
	}
}

#-----------------------------------------------------------
#  URLエンコード
#-----------------------------------------------------------
sub url_enc {
	local($_) = @_;

	s/(\W)/'%' . unpack('H2', $1)/eg;
	s/\s/+/g;
	$_;
}

#-----------------------------------------------------------
#  プルダウン作成 [ 検索条件 ]
#-----------------------------------------------------------
sub make_op {
	my %op;
	my %cond = (1 => 'AND', 0 => 'OR');
	foreach (1,0) {
		if ($in{cond} eq $_) {
			$op{cond} .= qq|<option value="$_" selected>$cond{$_}\n|;
		} else {
			$op{cond} .= qq|<option value="$_">$cond{$_}\n|;
		}
	}
	for ( my $i = 10; $i <= 30; $i += 5 ) {
		if ($in{view} == $i) {
			$op{view} .= qq|<option value="$i" selected>$i件\n|;
		} else {
			$op{view} .= qq|<option value="$i">$i件\n|;
		}
	}
	return %op;
}

#-----------------------------------------------------------
#  プルダウン作成 [ メール表示 ]
#-----------------------------------------------------------
sub make_ops {
	my $sml = shift;

	my %ops = (0 => '表示', 1 => '非表示');
	my $op_sml;
	foreach (1) {
		if ($sml eq $_) {
			$op_sml .= qq|<option value="$_" selected>$ops{$_}\n|;
		} else {
			$op_sml .= qq|<option value="$_">$ops{$_}\n|;
		}
	}
	return $op_sml;
}

#-----------------------------------------------------------
#  自動リンク
#-----------------------------------------------------------
sub autolink {
	my $text = shift;

	$text =~ s/(s?https?:\/\/([\w-.!~*'();\/?:\@=+\$,%#]|&amp;)+)/<a href="$1" target="_blank">$1<\/a>/g;
	return $text;
}

#-----------------------------------------------------------
#  クッキー取得
#-----------------------------------------------------------
sub get_cookie {
	# クッキー取得
	my $cook = $ENV{HTTP_COOKIE};

	# 該当IDを取り出す
	my %cook;
	foreach ( split(/;/, $cook) ) {
		my ($key,$val) = split(/=/);
		$key =~ s/\s//g;
		$cook{$key} = $val;
	}

	# URLデコード
	my @cook;
	foreach ( split(/<>/, $cook{$cf{cookie_id}}) ) {
		s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("H2", $1)/eg;
		s/[&"'<>]//g;

		push(@cook,$_);
	}
	return @cook;
}


