#!/usr/bin/perl

;# -------------------------------------------------------------------
;# Copyright
;#
;#		Script   :  Mini Thread
;#		Homepage :  Flash CGI
;#		URL      :  http://www.flashcgi.net/
;#		Mail     :  webmaster@flashcgi.net
;#		Type     :  Free Ware(May Convert)
;# -------------------------------------------------------------------
;#
;# 設定ファイル名
;; require 'config.cgi';
;#
;# 変数の局所化
;; my ($method,$accesskey);
;#
;; &main;
;#
;# 初期ページ
;#
sub main {
	#
	# 送られたデータを変数に入れる
	#
	if ($ENV{'REQUEST_METHOD'} eq 'POST') {
		read(STDIN, $QUERY_DATA, $ENV{'CONTENT_LENGTH'});
	} else { $QUERY_DATA = $ENV{'QUERY_STRING'}; }
	#
	# サイズチェック
	#
	&error(__LINE__,'コメントを短くして再度投稿してください') if (length($QUERY_DATA) > $sobig);
	#
	# デコード
	#
	my @pairs = split(/&/,$QUERY_DATA);
	foreach $pair (@pairs) {
		my ($name, $value) = split(/=/,$pair);
		$value =~ tr/+/ /;
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
		$value =~ s/[\x00-\x0d\x10-\x1a\x1c-\x1f]+//g;
		$FORM{$name} = $value;
	}
	#
	# 板
	#
	if ($FORM{'bbs'} eq '') { &look($QUERY_DATA); }
	#
	# パスの設定
	#
	if (&checkBbs($FORM{'bbs'})) {
		&readsubset($pluspath.$FORM{'bbs'}.'/'.$subsetcgi);
	} else {
		&error(__LINE__,'板が見つかりません');
	}
	#
	# J-PHONEとi-modeで変化
	#
	if ($host =~ /\.jp-[a-z]\.ne\.jp$/i or $ENV{'HTTP_USER_AGENT'} =~ /^J-PHONE/i) {
		$method = 'get';
		$accesskey = 'directkey';
	} else {
		$method = 'post';
		$accesskey = 'accesskey';
	}
	#
	# 条件分岐
	#
	if ($FORM{'ac'} eq 'th') { &thread(); }
	elsif ($FORM{'ac'} eq 'rf') { &resform(); }
	elsif ($FORM{'ac'} eq 'del') { &delform(); }
	else { &page(); }
}
;#
;# タイトル一覧
;#
sub page {
	#
	# 変数代入
	#
	my $bbs  = $FORM{'bbs'};
	my $page = $FORM{'pg'};
	$FORM{'stay'} = $scripturl.'?bbs='.$bbs.'&page='.$page;
	$page = 0 if ($page eq '' or $page < 0);
	#
	# フォームチェック
	#
	if ($page and $page !~ /^[-0-9]+$/) {
		&error(__LINE__,'不正なデータです');
	}
	#
	# データファイルから記事を読みこみます
	#
	open(DATA,$pluspath.$bbs.'/'.$savefile) or &error(__LINE__,'題名一覧ファイルのオープンに失敗しました');
	#
	# HTML
	#
	&encode(1);
	print '<html><head><title>'.$board_name.'</title></head>';
	print '<body bgcolor="'.$cell_bgc.'" text="'.$cell_text.'" link="'.$cell_link.'">';
	print '<center><font color="#362E2B" size="2">-+■COME TOGETHER■+-</font><font size="1" color="#D8332B"><br>仲間探し掲示板<br><br></font></center>';

	#print '<font color="#FF0000" size="1">※2/1(火)RSR2011 OFFICIAL SITE ﾘﾆｭｰｱﾙUPに伴い､1/27(木)AM10:00~1/31(月)PM23:59までｻｰﾋﾞｽを一時停止させていただきます｡大変ご迷惑をおかけ致しますが､ご理解とご協を頂きます様お願い申し上げます｡<br><br></font>';

	print '<font color="#9E0B0E" size="1">※個人､団体への中傷､他者に不快を与える書込み､ﾁｹｯﾄ等の交換･売買､RSRFESに関係がない書込みは管理者の判断により削除させていただきます｡<br><br></font>';

	print $cellcom;
	#
	# スレッド数
	#
	my $count;
	$count++ while(<DATA>);
	#
	# スレッドが無ければ飛ばす
	#
	if (!$count) {
		print '<center><a href="http://www.flashcgi.net/">Flash CGI</a></center></body></html>';
		exit;
	}
	#
	# 大きすぎ
	#
	$page = $count-$cellthread if ($page >= $count);
	#
	# 末端が大きい場合
	#
	$readline = ($page+$cellthread) > $count ? $count-$page : $cellthread;
	#
	# 飛ばす
	#
	seek(DATA,0,0);
	<DATA> while($page--);
	#
	# 表示開始
	#
	my $i;
	while ($readline--) {
		++$i;
		#
		# ログファイル名指定
		#
		my @SUB = split(/<>/,scalar(<DATA>));
		my $key = substr($SUB[0],0,-4);
		my $no;
		chomp($SUB[1]);
		if ($SUBJ_LENGTH and length($SUB[1]) > $SUBJ_LENGTH) {
			$SUB[1] =~ /(\s\([0-9]+\)$)/;
			$no = $1;
			&divide(\$SUB[1],$SUBJ_LENGTH-length($no));
		}
		#
		# 表示
		#
		print '[<a href="'.$scripturl.$cellcgi.'?/'.$bbs.'/'.$key.'/l'.$cellres.'" '.$accesskey.'="'.$i.'">'.$i.'</a>] '.$SUB[1].$no.'<br>';
	}
	print '<br>';
	#
	# ページ処理
	#
	if (<DATA>) {
		my $next = $FORM{'pg'} + $cellthread;
		print '[<a href="'.$scripturl.$cellcgi.'?bbs='.$bbs.'&pg='.$next.'" '.$accesskey.'=#>#</a>] 次のページ<br>';
	}
	if ($FORM{'pg'} > 0) {
		my $back = $FORM{'pg'} - $cellthread;
		print '[<a href="'.$scripturl.$cellcgi.'?bbs='.$bbs.'&pg='.$back.'" '.$accesskey.'=*>*</a>] 前のページ<br>';
	}
	#
	# ファイル閉じる
	#
	close(DATA);
	print '[<a href="'.$scripturl.$cellcgi.'?bbs='.$bbs.'&ac=th" '.$accesskey.'=0>0</a>] スレッド作成';
	#
	# 著作と終端
	#
	print '<center><a href="http://www.flashcgi.net/">Flash CGI</a></center></body></html>';
	exit;
}
;#
;# 記事閲覧画面
;#
sub look {
	#
	# 変数取得
	#
	my $data = shift;
	$data =~ s/\?$//;
	$FORM{'stay'} = $scripturl.$data;
	my ($bbs,$key,$order);
	#
	# 汚染チェック
	#
	if ($data =~ m|/([-a-zA-Z0-9]+)/([0-9]+)/(l?[-+0-9]*n?)$|) {
		$bbs = $1;
		$key = $2;
		$order = $3;
	} else {
		&error(__LINE__,'不正なデータを受信しました');
	}
	#
	# パスの設定
	#
	if (&checkBbs($bbs)) {
		&readsubset($pluspath.$bbs.'/'.$subsetcgi);
	} else {
		&error(__LINE__,'板が見つかりません');
	}
	my $this = $scripturl.$cellcgi.'?/'.$bbs.'/'.$key.'/';
	#
	# 変数取得
	#
	my ($from,$to,$want,@resNo);
	if ($order =~ /^([+0-9]+)n?$/) {
		@resNo = split(/\+/,$1);
	} elsif ($order =~ /^([0-9]*)-?([0-9]*)(n?)$/) {
		$from = $1 ? $1 : 1;
		$to   = $2;
	} elsif ($order =~ /^l([0-9]+)(n?)$/) {
		$want = $1;
		$resNo[0] = 1 if (!$2);
	} else {
		&error(__LINE__,'データを取得できません');
	}
	#
	# ファイルチェック
	#
	my $filename = $pluspath.$bbs.'/'.$savedir.$key.'.dat';
	unless (-e $filename) {
		&error(__LINE__,'ファイルが見つかりません');
	}
	#
	# データファイルから記事を読みこみます
	#
	open(LOG,$filename) or &error(__LINE__,'データを開けません');
	$stop = (split(/<>/,scalar(<LOG>)))[9];
	seek(LOG,0,0);
	#
	# レス数
	#
	++$count while(<LOG>);
	#
	# 続いたレスを表示する場合
	#
	if ($from) {
		if ($from > $count) {
			if ($count - $someres > 0) {
				$from = $count - $someres + 1;
			} else {
				$from = 1;
			}
		}
		if (!$to or $to > $count) {
			$to = $count;
		}
		$want = $to - $from + 1;
		pop @resNo if ($from == $resNo[0]);
	}
	#
	# 最新xx件という指定の場合
	#
	elsif ($want) {
		$from = $count - $want + 1;
		$from = 1 if ($from <= 0);
		$to = $count;
		$want = $count if ($want > $count);
		pop @resNo if ($from == $resNo[0]);
	}
	#
	# タイトル取得
	#
	seek(LOG,0,0);
	my @TEMP = split(/<>/,scalar(<LOG>));
	#
	# HTML
	#
	&encode(1);
	print '<html><head><title>'.$TEMP[4].'</title></head>';
	print '<body bgcolor="'.$cell_bgc.'" text="'.$cell_text.'" link="'.$cell_link.'">';
	print '<a href="#link">下へ</a><hr><font color="'.$cell_subjclr.'">'.$TEMP[4].'('.$count.')</font>'.$stopping.$alert;
	#
	# ひとつずつ表示させていく
	#
	foreach $resno (@resNo) {
		#
		# 指定の位置からログを取得
		#
		next if ($resno == 0 or $resno > $count);
		seek(LOG,0,0);
		my $j = $resno;
		my $flag;
		while(--$j > 0) {
			<LOG>;
		}
		my @TEMP = split(/<>/,scalar(<LOG>));
		#
		# データを指定した形式に変換
		#
		&convertData(\@TEMP,'return'=>$pluspath,'link'=>$this,'count'=>$count,'print'=>0,'tag'=>0,'image'=>0);
		print '<hr>'.$resno.' 名前：';
		if ($TEMP[0] =~ /^</) {
			print $TEMP[0];
		} else {
			print '<font color="'.$cell_nameclr.'">'.$TEMP[0].'</font>';
		}
		print ' ('.$TEMP[2].')'.$TEMP[5].'<br>';
		$flag=1 if ($from eq '');
		&cellTag(\$TEMP[3],$this.$resno,$flag);
		print $TEMP[3].'<br><br>';
		print '[<a href="'.$scripturl.$cellcgi.'?ac=del&bbs='.$bbs.'&no='.$key.'&rn='.$resno.'&bq='.$data.'">del</a>]<br>';
	}
	#
	# ここからは連続したレス
	#
	if ($from) {
		seek(LOG,0,0);
		my $j = $from;
		my $no = --$j;
		my $sbt = $want;
		#
		# 早送り
		#
		while($j--) {
			<LOG>;
		}
		#
		# 出力開始
		#
		while (<LOG>) {
			last if ($sbt-- <= 0);
			++$no;
			#
			# 分割
			#
			my @TEMP = split(/<>/);
			#
			# データを指定した形式に変換
			#
			&convertData(\@TEMP,'return'=>$pluspath,'link'=>$this,'count'=>$count,'print'=>0,'tag'=>0,'image'=>0);
			print '<hr>'.$no.' 名前：';
			if ($TEMP[0] =~ /^</) {
				print $TEMP[0];
			} else {
				print '<font color="'.$cell_nameclr.'">'.$TEMP[0].'</font>';
			}
			print ' ('.$TEMP[2].')'.$TEMP[5].'<br>';
			&cellTag(\$TEMP[3],$this.$no);
			print $TEMP[3].'<br><br>';
			print '[<a href="'.$scripturl.$cellcgi.'?ac=del&bbs='.$bbs.'&no='.$key.'&rn='.$no.'&bq='.$data.'">del</a>]<br>';
		}
	}
	close(LOG);
	#
	# リンク
	#
	print '<hr><a name=link></a>';
	#
	# 次のページ
	#
	if ($to < $count) {
		my $f = $to + 1;
		my $t = $to + $cellres;
		print '[<a href="'.$this.$f.'-'.$t.'" '.$accesskey.'=#>#</a>] 次へ<br>';
	}
	#
	# 前のページ
	#
	if ($from > 1) {
		my $t   = $from - 1;
		my $f = $from - $cellres;
		$f = 1 if ($f < 0);
		print '[<a href="'.$this.$f.'-'.$t.'" '.$accesskey.'=*>*</a>] 前へ<br>';
	}
	print '[<a href="'.$scripturl.$cellcgi.'?bbs='.$bbs.'" '.$accesskey.'=0>0</a>] スレ一覧<br>';
	print '[<a href="'.$this.'1-'.$cellres.'" '.$accesskey.'=7>7</a>] 先頭'.$cellres.'<br>';
	print '[<a href="'.$this.'l'.$cellres.'" '.$accesskey.'=8>8</a>] 最新'.$cellres.'<br>';
	print '[<a href="'.$scripturl.$cellcgi.'?ac=rf&bbs='.$bbs.'&no='.$key.'&bq='.$data.'" '.$accesskey.'=9>9</a>] レスする';
	#
	# 著作と終端
	#
	print '<center><a href="http://www.flashcgi.net/">Flash CGI</a></center></body></html>';
	exit;
}
;#
;# スレッド作成画面
;#
sub thread {
	my $bbs = $FORM{'bbs'};
	&encode(1);
	print '<html><head><title>スレッド作成</title></head>';
	print '<body bgcolor="'.$cell_bgc.'" text="'.$cell_text.'" link="'.$cell_link.'">';
	print '<center><font color="#362E2B" size="2">-+■スレッド作成■+-<br></font></center>';
	print '<font size="1" color="#9E0B0E">※この掲示板はスレッドが50個しか立てられません。同じようなスレッドがないかよく確認しましょう。<br></font>';
	print '<center><a href="http://rsr.wess.co.jp/bbs/2011/come/RSR/i/index.html"><font size="1" color="#9E0B0E">スレッド内容を確認する</font></a></center><br>';
	print '<form action="'.$scripturl.$mainscript.'" method='.$method.' utn>';
	print '<input type=hidden name=bbs value='.$bbs.'>';
	print '<input type=hidden name=stay value="'.$scripturl.$cellcgi.'?bbs='.$bbs.'">';
	print 'タイトル:<br><input name=subject><br>';
	print '名前:<br><input name=FROM><br>';
	print 'メール:<br><input name=mail><br>';
	print 'ＵＲＬ:<br><input name=home><br>';
	print 'メッセージ:<br><textarea name=MESSAGE rows=3></textarea><br>';
	print 'パスワード:<br><input type=password name=pass><br>';
	print '<input type=submit name=submit value="新規スレッド作成"></form><br>';
	print '[<a href="'.$scripturl.$cellcgi.'?bbs='.$bbs.'" $accesskey=0>0</a>] スレ一覧';
	print '<center><a href="http://www.flashcgi.net/">Flash CGI</a></center></body></html>';
	exit;
}
;#
;# レスフォーム
;#
sub resform {
	#
	# チェック
	#
	my $bbs = $FORM{'bbs'};
	my $key = $FORM{'no'};
	$FORM{'stay'} = $scripturl.$cellcgi.'?'.$FORM{'bq'};
	#
	# フォームチェック
	#
	if ($key eq '') {
		&error(__LINE__,'送信されたデータにスレッド番号が存在しません');
	}
	if ($key =~ /\D/) {
		&error(__LINE__,'変な情報が送られてきました');
	}
	#
	# HTML
	#
	&encode(1);
	print '<html><head><title>レス投稿</title></head>';
	print '<body bgcolor="'.$cell_bgc.'" text="'.$cell_text.'" link="'.$cell_link.'">';
	print '<center><font color="#362E2B" size="2">-+■レス投稿■+-</font></center>';
	print '<form action="'.$scripturl.$mainscript.'" method='.$method.' utn>';
	print '<input type=hidden name=bbs value='.$bbs.'>';
	print '<input type=hidden name=key value='.$key.'>';
	print '<input type=hidden name=stay value="'.$FORM{'stay'}.'">';
	print '名前:<br><input name=FROM><br>';
	print 'メール:<br><input name=mail><br>';
	print 'ＵＲＬ:<br><input name=home><br>';
	print 'メッセージ:<br><textarea name=MESSAGE rows=3></textarea><br>';
	print 'パスワード:<br><input type=password name=pass><br>';
	print '<input type=submit name=submit value="書き込む">';
	print '<input type=checkbox name=sage value=1>sage';
	print '</form><br>';
	print '[<a href="'.$scripturl.$cellcgi.'?bbs='.$bbs.'" '.$accesskey.'=0>0</a>] スレ一覧<br>';
	print '[<a href="'.$scripturl.$cellcgi.'?/'.$FORM{'bq'}.'" '.$accesskey.'=*>*</a>] 戻る';
	print '<center><a href="http://www.flashcgi.net/">Flash CGI</a></center></body></html>';
	exit;
}
;#
;# レスフォーム
;#
sub delform {
	#
	# チェック
	#
	my $bbs = $FORM{'bbs'};
	my $key = $FORM{'no'};
	my $resno = $FORM{'rn'};
	$FORM{'stay'} = $scripturl.$cellcgi.'?'.$FORM{'bq'};
	#
	# フォームチェック
	#
	if ($key eq '') {
		&error(__LINE__,'送信されたデータにスレッド番号が存在しません');
	}
	if ($key =~ /\D/) {
		&error(__LINE__,'変な情報が送られてきました');
	}
	if ($resno eq '') {
		&error(__LINE__,'送信されたデータにレス番号が存在しません');
	}
	if ($resno =~ /\D/) {
		&error(__LINE__,'変な情報が送られてきました');
	}
	#
	# HTML
	#
	&encode(1);
	print '<html><head><title>記事削除</title></head>';
	print '<body bgcolor="'.$cell_bgc.'" text="'.$cell_text.'" link="'.$cell_link.'">';
	print '<center>記事削除</center>';
	print '<form action="'.$scripturl.$mainscript.'" method='.$method.' utn>';
	print '<input type=hidden name=action value=delete>';
	print '<input type=hidden name=bbs value='.$bbs.'>';
	print '<input type=hidden name=key value='.$key.'>';
	print '<input type=hidden name=resno value='.$resno.'>';
	print '<input type=hidden name=stay value="'.$FORM{'stay'}.'">';
	print 'パスワード:<br><input type=password name=pass><br>';
	print '<input type=submit name=submit value="削除する"><br><br>';
	print 'ＩＤ:<br><input name=id><br>';
	print '削除理由:<br><textarea name=MESSAGE rows=3></textarea><br>';
	print '</form><br>';
	print '[<a href="'.$scripturl.$cellcgi.'?bbs='.$bbs.'" '.$accesskey.'=0>0</a>] スレ一覧<br>';
	print '[<a href="'.$scripturl.$cellcgi.'?/'.$FORM{'bq'}.'" '.$accesskey.'=*>*</a>] 戻る';
	print '<center><a href="http://www.flashcgi.net/">Flash CGI</a></center></body></html>';
	exit;
}
;#
;# イメタグ解除等
;#
sub cellTag {
	#
	# 取得
	#
	my $string = shift;
	my $link = shift;
	my $flag = shift;
	#
	# <img>タグ許可
	#
	if ($allowimg) {
		$$string =~
		s{&lt;img[\s]+src=["']?http://([!-:A-~]+)\.(gif|jpg|jpeg|jpe|png)['"]?&gt;}
		{\[<a href="http://$1\.$2">IMG</a>\]}ig;
	}
	#
	# <font>タグ許可
	#
	if ($allowfont) {
		while ($$string =~
			s{&lt;font[\s]+(color|size)=["']?([-+#a-z0-9]+)["']?[\s]*([-+=a-z0-9"'#]*)&gt;(.*?)&lt;/font&gt;}
			{&fontTagC($1,$2,$3,$4)}ie
		) { 1; }
	}
	sub fontTagC {
		my $tag = shift;
		my $ent = shift;
		my $more= shift;
		my $str = shift;
		if ($tag eq 'color') {
			return ('<font color="'.$ent.'">'.$str.'</font>');
		} elsif ($tag eq 'size') {
			return ('<font color="'.$1.'">'.$str.'</font>') if ($more =~ /color=['"]?([#a-z0-9]+)["']?/i);
		}
		return($str);
	}
	#
	# <a>タグ許可
	#
	if ($allowa) {
		1 while $$string =~ s{&lt;a[\s]+href=["']?(https?://)([-_.!~*'()a-zA-Z0-9;/?:\@=+\$,%#]+)['"]?&gt;(.*?)&lt;/a&gt;}{<a href="$1$2">$3</a>}i;
	}
	#
	# その他
	#
	foreach (@TAG) {
		1 while $$string =~ s{&lt;$_&gt;(.*?)&lt;/$_&gt;}{<$_>$1</$_>}i;
	}
	#
	# 判定
	#
	return if ($flag or !$cellomis or length($$string) < $cellomis);
	#
	# 省略
	#
	&divide($string,$cellomis);
	#
	# タグの途切れ判定
	#
	my $r1 = rindex($$string,'<');
	my $r2 = rindex($$string,'>');
	if ($r1 > $r2) {
		$$string = substr($$string,0,$r1);
	}
	#
	# タグ修復
	#
	my $n;
	if ($allowa) {
		$n=&comparison($$string,'<a href','</a>');
		if ($n) {
			$$string .= '</a>'x$n if($n > 0);
		}
	}
	if ($allowfont) {
		if ($n=&comparison($$string,'<font','</font>')) {
			$$string .= '</font>'x$n if($n > 0);
		}
	}
	foreach $tag (@TAG) {
		if ($n=&comparison($$string,'<'.$tag.'>','</'.$tag.'>')) {
			$$string .= ('</'.$tag.'>')x$n if($n > 0);
		}
	}
	$$string .= '...<br><br><a href="'.$link.'">全文表\示</a>';
}
;#
;# 文字列をカットする
;# ２バイト文字に対応
;#
sub divide {
	#
	# 対象文字と数を取得
	#
	my $str = shift;
	my $n = shift;
	#
	# とりあえずカット
	#
	$$str = substr($$str,0,$n);
	#
	# 文字化け対策
	#
	my ($i,$byte);
	for ($i=$n-1;$i>=0;$i--){
		my $c = ord(substr($$str, $i, 1));
		if (($c <= 0x7F) or ((0xA0 <= $c) and ($c <= 0xDF))){ last; }
		$byte ^= 1;
	}
	chop $$str if ($byte);
	$$str =~ s/&[#a-zA-Z0-9]*$//;
}
