#!/usr/bin/perl # Copyright (c) CGIROOM. http://cgiroom.nu #======================================================================# # [Ver 2.34.1] ツリー掲示板 # # このプログラムによって起きた事にCGIROOMは責任を負いません。 # 利用契約に同意できない方のご利用は、遠慮下さい。 #======================================================================# #◆設定 #◇ jcode.plまでのパス require 'jcode.cgi'; #◇ ログの最高保存件数 $max = 200; #◇ 1ページ表示ツリー件数 $pmax = 15; #◇ タイトル $title="掲 示 板"; #◇ バック先URL $url="http://www.infoeddy.ne.jp/~hatake"; #◇ パスワード $pass="PASSWORD"; #======================================================================# # オプション #◇ Nnw!マークと色と数 $newf ="New!"; $newc ="#FF0000"; $new = 5; #◇ <-lastマークと色。表示しないなら 1 を 0 に。 $lastf ="<-last"; $lastc ="#888888"; $last = 1; #◇ 引用文の色 $m_color="#800000"; #◇ BODY $body=''; #◇ 書きこみフォームのバックカラー $bg='#E0E0E0'; #◇ 返信フォームに引用文字をあらかじめ表示するなら0を1に $FORM{'hens'}=0; #◇ フォームからURLを消す場合は 0 に $urls= 1 ; #◇ 発言時注意事項 $msg = <<'MSG';
◆注意点
◇題名は、短くわかりやすく書いてください。
◇過去に同じ内容が投稿されていないか検索してから書き込んで下さい。
◇管理人の判断により相応しくない投稿は削除します。
MSG #======================================================================# # フォームデータ処理 if($ENV{'REQUEST_METHOD'} eq "POST"){ read(STDIN, $QUERY, $ENV{'CONTENT_LENGTH'}); }else{ $QUERY = $ENV{'QUERY_STRING'}; } @QUERY = split(/&/,$QUERY); foreach (@QUERY){ ($n, $v) = split(/=/); $v =~ tr/+/ /; $v =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $v =~ s/&/&/g; $v =~ s/"/"/g; $v =~ s//>/g; $v =~ s/\r\r\n/
/g; $v =~ s/\r\n/
/g; $v =~ s/\r/
/g; $v =~ s/\n/
/g; $v =~ s/\t//g; &jcode'convert(*v,'sjis'); $FORM{$n} = $v; } #======================================================================# # その他設定 $links='treebbs.cgi?log='; $LOG = "treebbs.dat"; $ENV{'TZ'}="JST-9"; #======================================================================# # 書き込みデータ表示処理 if($FORM{'log'}){ open(LOG)||&err('ファイルをオープンできません'); $t=; chop $t; $news = $t - $new; $w=$t - $FORM{'log'} + 2; while(){ if($. == $w){ @data_log = split(/\t/,$_); undef $data_log[8] unless $urls == 1; last; } } close(LOG); &head; $mail="" if $data_log[5]; $cmsg = $data_log[7]; &link(*cmsg); print< URL print<
No.$data_log[0]  $data_log[3]
発言者:$mail$data_log[4]
発言日:$data_log[6]
$cmsg
$data_log[8]

▼関連発言
HTML
$i=0;
open(LOG)||&err('ファイルをオープンできません');
while (){
	if(/^(\d+)\t\d+\t$data_log[2]\t/){
		$F{$data_log[2]}=$1 if $F{$data_log[2]} eq "";
		push(@log,$_);
		last if $1 eq $data_log[2];
	}
}
close(LOG);

&tree(0);

if($data_log[3]=~ s/Re\[(\d+)\]:/"Re\[" . ($1 + 1) . "\]:"/e){
}elsif($data_log[3]=~ s/^Re:/Re\[2\]:/){
}else{$data_log[3]="Re:$data_log[3]";}

($cna,$maile,$curl)=split(/\t/,&get_cookie);
if($FORM{'hens'} == 1 && $FORM{'nhens'} eq ""){
	$data_log[7]=~ s/
/\r> /g; $hen="> $data_log[7]"; } $formurls=<
URL 省略可
 返信フォーム [引用] $formurls
名 前 保存
題 名
メール 省略可
発 言
書き込む
$msg
HTML &last; exit; #======================================================================# # スレッド表示 }elsif($FORM{'all'}){ &head; $all=$FORM{'all'}; print"
スレッド\n";
open(LOG)||&err('ファイルをオープンできません');
$news =  - $new;
while (){
	if(/^(\d+)\t\d+\t$all\t/){
		push(@log,$_);
		last if $1 eq $all;
	}
}
close(LOG);
$links='#';
&tree(0);
print"
\n

\n"; foreach ( reverse @log){ @data=split(/\t/);$data[4]="
$data[4]" if $data[5]; $datass=$data[7]; &link(*datass); print< $data[0]● $data[3][ $data[4] ] $data[6]
$datass
コメントを書く(引用) | スレッド一覧
HTML } &last; exit; #======================================================================# # 書き込み処理 }elsif($FORM{'ha'}){ &err('不正エラー') if $FORM{'re'} eq ""; $err=1 if $FORM{'dai'} eq ""; $err=1 if $FORM{'name'} eq ""; $err=1 if $FORM{'t'} eq ""; &ha("記入不足です") if $err; &ha("只今混雑しているので30秒ほどお待ちになってください。","1") if &lock == 0; open(LOG)||&err('ファイルをオープンできません'); @open=; close(LOG); $sss=$open[0]+1; $FORM{'s'}=$sss unless $FORM{'s'}; ($sec,$min,$hour,$day,$mon)=localtime(time); $day ="0$day" if $day < 10; $hour="0$hour" if $hour < 10; $min ="0$min" if $min < 10; $mon++; if((split(/\t/,$open[1]))[7] eq "$FORM{'t'}"){ open(C,">lock.txt")&&close(C); &err('2重投稿防止機能が作動しました'); } $data[0] = $sss ; #投稿記事番号 $data[1] = $FORM{'re'} ; #レス先記事番号 $data[2] = $FORM{'s'}; #スレッド元記事番号 $data[3] = $FORM{'dai'} ; #題名 $data[4] = $FORM{'name'} ; #投稿者名 $data[5] = $FORM{'email'} ; #メールアドレス $data[6] = "$mon/$day $hour:$min"; #日付 $data[7] = $FORM{'t'} ; #発言内容 $data[8] = $FORM{'url'} ; #URL $data[9] = ""; #未定(自由) $data[10]= ""; #未定(自由) $data[11]= ""; #未定(自由) $data[12]= ""; #未定(自由) $data[13]= "\n"; #改行 splice(@open,0,1,"$sss\n",join("\t",@data)); $back = pop(@open) if $max < $#open; open(A,"> $LOG")||&err('ログファイルをオープンできません'); print A @open; close(A); if($back && open(OUT,">>$BACK")){ print OUT $back; close OUT; } open(C,">lock.txt")&&close(C); print "Set-Cookie: CGIROOMTREE=$FORM{'name'}\t$FORM{'email'}\t$FORM{'url'}; expires=Fri, 31-Dec-2010 00:00:00 GMT\n" if $FORM{'cookie'}; #======================================================================# # 新規発言 }elsif($FORM{'new'}){ &ha(''); #======================================================================# # 最新発言順 }elsif($FORM{'last'}){ &head; print"
"; open(LOG)||&err('ファイルをオープンできません'); $i="00"; while(){ if(/^\d+\t\d+\t/){ last if $i++ >= 20; @data=split(/\t/); print""; print"$data[0]:$data[3] [$data[4]] $data[6]
\n"; } } print"
"; &last; exit; #======================================================================# # 検索処理 }elsif($FORM{'seek'}){ &head; print"
"; print<
▼検索:
HTML if(($FORM{'next'} - 1) >= 0){ $back=$FORM{'next'} - 1; print"▲ BACK

\n"; } $FORM{'seek'}=~ s/ / /og; $FORM{'seek'}=~ s/([\\\+\?\.\*\(\)\[\]\{\}\|])/\\$1/og; @seek=split(/ /,$FORM{'seek'}); foreach (@seek){ push(@key,$_); } $log=$FORM{'next'} * 20; open(LOG) || &error("エラー"); $dummy=; while(){ $i=0; $word=$_; foreach (@key){ next if $word =~ /$_/i; $i = 1; last; } next if $i == 1; $no++; next if $log-- > 0; if($log < - 20){ $f=$FORM{'next'} + 1; last; } @data=split(/\t/,$word); print"$data[0]:$data[3] [$data[1]] $data[6]
\n"; } close(LOG); print"

▼ NEXT\r\n" if $f > 0; print"$FORM{'seek'} に該当する投稿記事はありません" if $no == 0; print"

"; &last; exit; #======================================================================# # 書き込み削除処理 }elsif($FORM{'del'} >= 1 && $FORM{'pass'} eq $pass){ &err("只今混雑しているので30秒ほどお待ちになってください。") if &lock == 0; open(LOG)||&err('ファイルをオープンできません'); @open=; close(LOG); $sss=$open[0]; chop $sss; $ss = $sss - $FORM{'del'} + 1; ($log_c,$log_n,$log_s,$log_d,$log,$log_e,$log_h)=split(/\t/,$open[$ss]); $open[$ss]="$log_c\t$log_n\t$log_s\t---\t---\t\t$log_h\tこの記事は何らかの理由で削除されました\n"; open(LOG,">$LOG")||&err('ログファイルをオープンできません'); print LOG @open; close(LOG); open(C,">lock.txt")&&close(C); } #======================================================================# # 書き込みリスト表示ヘッダー部分 &head; print<
▼検索: HTML $i=$FORM{'logs'}; $i=1 unless $i; $back=$i - $pmax; open(LOG)||&err('ファイルをオープンできません'); $open = ; $news = $open - $new; while (){ if(/^\d+\t\d+\t(\d+)\t/){ next if $f{$1}; $f{$1}=1; $s++; next if $i > $s ; if( $s >= $i + $pmax){ $next = $s; last; } push(@lists,$1); } } close(LOG); foreach $dummy (@lists){ open(LOG)||&err('ファイルをオープンできません'); while (){ if(/^(\d+)\t\d+\t$dummy\t/){ $F{$dummy}=$1 if $F{$dummy} eq ""; push(@log,$_); last if $1 eq $dummy; } } close(LOG); } &tree(0); print"\n"; print"<< BACK  " if ($FORM{'logs'} && 0 < $back); print"NEXT >>\n" if $next; print<
No/Pass:   
HTML &last; exit; #======================================================================# # ツリー表示処理 sub tree{ local($log,$c,$n)=@_; local(@aaa,$a); foreach (@log){ last if /^$log\t/; if(/^\d+\t$log\t/){ push(@aaa,$_); } } close(LOG); if($n eq "└"){ $c.=" "; }elsif($n){ $c.="│"; } while(@aaa){ if($log == 0){ @data=split(/\t/,shift(@aaa)); }else{ @data=split(/\t/,pop(@aaa)); } $n="├"; $n="└" unless @aaa; print"
│\n
$c$n" if 0 eq $data[1]; print"
$c$n◇" if 0 ne $data[1]; print"$data[0]:"; if($FORM{'log'} ne $data[0]){ print"$data[3] [$data[4]] $data[6]"; }else{ print"$data[3] [$data[4]] $data[6]"; } print"$lastf" if $last == 1 && $F{$data[2]} eq $data[0]; print"$newf" if $news < $data[0]; print"\n"; &tree($data[0],$c,$n); undef $dat; } undef @aaa; undef $a; } #======================================================================# # HTML ヘッダー表示 sub head{ print"Content-type: text/html\n\n"; print< $title $body

$title

新規発言 | 一覧 | 最新発言 | HOME

HTML } #======================================================================# # 書き込みフォーム sub ha{ @dummy=@_; &head; $li="" if $FORM{'s'}; $FORM{'re'}="0" unless $FORM{'re'}; ($FORM{'name'},$FORM{'email'})=split(/\t/,&get_cookie) if $FORM{'name'} eq ""; $FORM{'t'}=~ s/
/\r/g if $FORM{'t'}; $formurls= < URL 省略可 URL print<
  発言フォーム $dummy[0] $li$formurls
名 前 名前保存
題 名
メール 省略可
発 言
書き込む
$msg
HTML &last; exit; } #======================================================================# # HTML フッター表示 sub last{ print'

HATAKE-HOME

'; } #======================================================================# # クッキー獲得 sub get_cookie{ @cookie=split(/;/,$ENV{'HTTP_COOKIE'}); foreach (@cookie){ ($name,$value) = split(/=/); $name =~ s/ //g; return $value if $name eq "CGIROOMTREE"; } } #======================================================================# # エラー表示 sub err{ local($err)=@_; print"Content-type: text/html\n\n$body

ERROR

$err
"; print"ブラウザの戻るボタンから戻ってください
CGIROOM"; exit; } #======================================================================# # ロック処理 sub lock{ &error('ツリー掲示板は使えません。') if length($$) <= 0; foreach (1..10){ if(-z "lock.txt"){ if(!open(LOCK,">>lock.txt")){ &err("lock.txtに書き込めません"); exit; } print LOCK $$; close(LOCK); if(!open(LOCK,"lock.txt")){ &err("lock.txt開けません"); exit; } $dummy=; close(LOCK); if($dummy eq $$){ return 1; } } $times=(stat("lock.txt"))[9]; $timer=time - 60; if($times <= $timer){ open(LOCK,">lock.txt")&&close(LOCK); }else{ sleep 1; } } return 0; } #======================================================================# # コメント装飾 sub link{ local(*_) = @_; s/("|>|<)/ $1/g; s/
/\n/g; s/([\x81-\x9F|\xE0-\xEF][\x40-\x7E|\x80-\xFC])*([\x21-\x7E]+\@[\x21-\x7E]+\.[\x21-\x7E]+)/$1$2<\/a>/g; s/(http:\/\/[\x21-\x7E]+)/$1<\/a>/g; s/ ("|>|<)/$1/g; @PAGE=split(/\n/); foreach $iii (@PAGE){ if($iii =~ /^>|^>|^\||^|/){ $iii = "$iii"; } } $_ = join("
\n",@PAGE); } __END__ 1999/06/01 Ver 2.10 1999/08/18 Ver 2.20 1999/09/07 Ver 2.21 1999/10/16 Ver 2.30 1999/11/15 Ver 2.31 1999/11/07 Ver 2.32 1999/12/19 Ver 2.33 2000/01/07 Ver 2.34 最終版予定 2000/01/21 Ver 2.34.1 予定といいつつ・・・