#!/usr/bin/perl ## WEB FORUM v2.64 (00/05/31) ## Copyright(C) KENT WEB 2000 ## E-MAIL: webmaster@kent-web.com ## WWW: http://www.kent-web.com/ $ver = 'Web Forum v2.64'; # バージョン情報 #--- [注意事項] ------------------------------------------------# # 1. このスクリプトはフリーソフトです。このスクリプトを使用した # # いかなる損害に対して作者は一切の責任を負いません。 # # 2. 設置に関する質問はサポート掲示板にお願いいたします。 # # 直接メールによる質問は一切お受けいたしておりません。 # #---------------------------------------------------------------# # [設置例] かっこ内はパーミッション # # public_html / index.html (ホームページ) # | # +-- bbs [777] / wforum.cgi [755] # wforum.log [666] # wf_admin.cgi [755] # jcode.pl [644] # fold.pl [644] # index.html # index.cgi [755] .. (過去ログ用) # 1.html [666] .. (過去ログ用) # pastno.dat [666] .. (過去ログ用) #============# # 基本設定 # #============# # ライブラリ取込み require './jcode.pl'; require './fold.pl'; # 掲示板タイトル名 $title = ""; # 掲示板の場所 $web= "http://lets-move.jp/BBS"; # タイトルの色 $t_color = "#004080"; # タイトルの大きさ(ポイント数:スタイルシート) $t_point = '18'; # タイトル文字のタイプ $t_face = 'MS Pゴシック'; # タイトル画像を使用するとき $t_gif = ""; $t_wid = 0; # 画像の横サイズ(ピクセル) $t_hgt = 0; # 画像の縦サイズ(ピクセル) # 本文の文字大きさ(ポイント数:スタイルシート) $pt = '10'; # 最大記事数 $max = 100; # 戻り先のURL(index.htmlなど) $home = "../index.html"; # 説明ページ $howto = "./index.html"; # メール配信ページ #$haishin = "../ML/index.html"; # 壁紙・背景色・文字色など $bground = ""; # 壁紙の指定 $bgcolor = "#99CC66"; # テキスト色 $text = "#004080"; # 文字色 $link = "#0000E3"; # リンク色(未訪問) $vlink = "#008080"; # リンク色(既訪問) $alink = "#DD0000"; # リンク色(訪問中) # 管理ファイル $admin = "./wf_admin.cgi"; # スクリプト名 $script = "./wforum.cgi"; $scrip = "/wforum.cgi"; # ログファイル名 $logfile = "./wforum.log"; # タグの許可 (0=no 1=yes) $tagkey = 0; # ロックファイル機構 # 0 : no # 1 : yes : symlink関数 # 2 : yes : open関数 $lockkey = 0; # ロックファイル名 # ---> このディレクトリのパーミッションは777にすること $lockfile = "./wforum.lock"; # URL自動リンク (0=no 1=yes) $autolink = 1; # 記事の [題名] の色 $sub_color = "#DD0000"; # 記事下地の色(一括表示時等) $tbl_color = "#FFFFFF"; # 記事にNEWマークを付ける時間 $new_time = 48; # NEWマークの色 $new_color = "#FF80FF"; # 記事NOの色 $no_color = "#800000"; # 新着記事一括の記事数 $sortcnt = 10; # 頁あたりツリー表示数 $p_tree = 15; # リストに表示する「記事タイトル」の長さ(文字数:半角文字換算) $sub_length = 32; # メールアドレスの入力を必須 (0=no 1=yes) $in_email = 0; # レスがついたらツリー毎トップへ移動 (0=no 1=yes) $top_sort = 1; # 引用部色変更 # 1) ここに色指定を行うと「引用部」を色変更します # (その分表示動作が遅くなります) # 2) 必ずタグは禁止処理にしてください ($tagkey=1;) # 3) この機能を使用しない場合は何も記述しないで下さい ($refcolor="";) $refcolor = "#804000"; # methodの形式 (POST/GET) $method = 'POST'; # 投稿があるとメール通知する : sendmail必須 # 0 : 通知しない # 1 : 通知する(自分の記事は送信しない) # 2 : 通知する(自分の記事も送信する) $mailing = 1; # メール通知する際のメールアドレス #差出人 $mailfrom = 'moveBBS'; #投稿者が差出人の場合 #$mailfrom = $in{'email'} #送信先 $mailto = 'horie@kiss.or.jp'; # sendmailパス(メール通知する時) $sendmail = '/usr/lib/sendmail'; # ツリーのヘッダー $treehead = "★"; # ホスト名取得モード # --> 0 : $ENV{'REMOTE_HOST'} で取得できる場合 # --> 1 : gethostbyaddr で取得できる場合 $get_remotehost = 0; # 過去ログ機能 (0=no 1=yes) $pastkey = 1; # 過去ログ用補助ファイル $hojofile = "./index.cgi"; # 過去ログカウントファイル $past_num = "./pastno.dat"; # 過去ログのディレクトリ $past_dir = "."; # 過去ログ1ページ当りの最大行数 $max_line = 170; # アクセス制限(ホスト名を記述) @deny = ( '*.hogehoge.ne.jp', 'xxx.proxy.com', '', '', '', '', ''); #============# # 設定完了 # #============# # bodyタグの定義 $body = "\n"; # ////////// 基本処理 ///////////////////////////////// # &decode; &axs_check; if ($mode eq "regist") { ®ist; } elsif ($mode eq "form" && $in{'pview'} eq "on") { &preview; } elsif ($mode eq "form" && $in{'pview'} ne "on") { ®ist; } elsif ($mode eq "msgview") { &msgview; } elsif ($mode eq "allread") { &allread; } elsif ($mode eq "new_sort") { &new_sort; } elsif ($mode eq "usr_del") { &usr_del; } elsif ($mode eq "find") { &find; } &list_view; #----------------# # アクセス制限 # #----------------# sub axs_check { if ($deny[0]) { # ホスト名を取得 &get_host; $h_flag=0; foreach (@deny) { if ($_ eq '') { last; } $_ =~ s/\*/\.\*/g; if ($host =~ /$_/) { $h_flag=1; last; } } if ($h_flag) { # エラー表示 &header; print "あなたと同一のホストの方が過去不適切な発言を行ったため
現在アクセスができません\n"; print "\n"; exit; } } } #----------------# # デコード処理 # #----------------# sub decode { if ($ENV{'REQUEST_METHOD'} eq "POST") { if ($ENV{'CONTENT_LENGTH'} > 51200) { &error("投稿量が大きすぎます"); } read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/, $buffer); foreach (@pairs) { ($name,$value) = split(/=/, $_); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # シフトJIS変換 &jcode'convert(*value, "sjis", "", "z"); if ($tagkey == 0) { $value =~ s/&/&/g; $value =~ s//>/g; } else { $value =~ s///g; $value =~ s/<>/<>/g; } # 改行処理 if ($name eq "message") { $value =~ s/\r\n/
/g; $value =~ s/\r/
/g; $value =~ s/\n/
/g; } else { $value =~ s/\r//g; $value =~ s/\n//g; } $in{$name} = $value; } $in{'url'} =~ s/^http\:\/\///; if ($in{'sub'} eq "") { $in{'sub'} = "無題"; } $mode = $in{'mode'}; $page = $in{'page'}; if ($page eq "") { $page = 0; } # 強制改行処理 if (($mode eq "form" && $in{'pview'} ne "on" && $in{'wrap'} eq "hard") || ($mode eq "regist" && $in{'wrap'} eq "hard")) { &get_agent; $bytes = $com_wid; if ($in{'action'} eq "res_msg") { $bytes += 6; } local($tmp) = ''; while (length $in{'message'}) { ($folded, $in{'message'}) = &fold ($in{'message'},$bytes); $tmp .= "$folded
"; } $in{'message'} = $tmp; } # 改行処理 while ($in{'message'} =~ /
$/) { $in{'message'} =~ s/
$//g; } } #----------------# # 書き込み処理 # #----------------# sub regist { # フォームチェック if ($in{'name'} eq "" || $in{'message'} eq "") { &error("名前又はメッセージに記入モレがあります"); } # E-Mail入力 if ($in_email && $in{'email'} !~ /(.+)\@(.+)\.(.+)/) { &error("E-Mailの入力が不正です"); } # if ($in{'no'} eq 'new' && !$in{'url'}) # { &error("設置スクリプトのURL記述は必須です"); } # ホスト情報を取得 &get_host; # ロック処理 if ($lockkey == 1) { &lock1; } elsif ($lockkey == 2) { &lock2; } # ログファイル読み込み open(IN,"$logfile") || &error("Open Error : $logfile"); @lines = ; close(IN); # カウントファイルをアップ $count = shift(@lines); chop($count); $count++; # 二重投稿の禁止 $flag=0; foreach (@lines) { ($kno,$kre,$kx,$ktt,$kem,$kurl,$kname,$kdate,$kmsg) = split(/<>/); if ($in{'name'} eq $kname && $in{'message'} eq $kmsg) { $flag=1; last; } } if ($flag) { &error("二重投稿は禁止です"); } # クッキーを発行 &set_cookie; # パスワード暗号化 if ($in{'pwd'} ne "") { $ango = &encrypt($in{'pwd'}); } # 時間を取得 &get_time; # 親記事の場合 if ($in{'no'} eq 'new') { unshift (@lines,"$count<>no<>0<>$in{'sub'}<>$in{'email'}<>$in{'url'}<>$in{'name'}<>$date<>$in{'message'}<>$times<>$host<>$ango<>$in{'wrap'}<>$count<>\n"); @new = @lines; # レス記事の場合 } else { ## ツリーソート「あり」の場合 ## if ($top_sort) { @new=(); @tmp=(); foreach (@lines) { local($no,$reno,$lx,$t,$e,$u,$n,$d,$m,$tm,$h,$a,$w,$OYA) = split(/<>/, $_); if ($OYA eq "$in{'oya'}") { push(@new,$_); } else { push(@tmp,$_); } if ($no eq "$in{'no'}") { $lx++; push(@new,"$count<>$no<>$lx<>$in{'sub'}<>$in{'email'}<>$in{'url'}<>$in{'name'}<>$date<>$in{'message'}<>$times<>$host<>$ango<>$in{'wrap'}<>$in{'oya'}<>\n"); } } push(@new,@tmp); } ## ツリーソート「なし」の場合 ## else { @new = (); foreach (@lines) { ($no,$reno,$lx) = split(/<>/, $_); push (@new,$_); if ($no eq "$in{'no'}") { $lx++; push (@new,"$count<>$no<>$lx<>$in{'sub'}<>$in{'email'}<>$in{'url'}<>$in{'name'}<>$date<>$in{'message'}<>$times<>$host<>$ango<>$in{'wrap'}<>$in{'oya'}<>\n"); } } } } # 最大記事数処理 @PAST = (); if (@new > $max) { foreach (0 .. $#new) { # 最終尾ファイルを配列から抜き出す local($p_file) = pop(@new); # 過去ログ配列 @PASTに格納 unshift(@PAST,$p_file); local($no,$reno,$lx) = split(/<>/, $p_file); if ($#new+1 <= $max && $reno eq 'no') { last; } } } # カウントログ付加 unshift(@new,"$count\n"); # ログを更新 open(OUT,">$logfile") || &error("Can't write $logfile"); print OUT @new; close(OUT); # 過去ログ処理 if ($pastkey) { &past_log; } # ファイルロック解除 if (-e $lockfile) { unlink($lockfile); } # メール通知 if ($mailing == 2) { &mail_to; } elsif ($mailing == 1 && $in{'email'} ne "$mailto") { &mail_to; } # 書きこみ後処理 if ($in{'pview'} ne "on") { &after; } else { &list_view; } } #------------------------# # 書きこみ後メッセージ # #------------------------# sub after { if ($in{'url'}) { $in{'url'} = "http://$in{'url'}"; } # ツリートップ移動処理の場合は書き込み後はトップページ if ($top_sort) { $page = 0; } if ($in{'wrap'} eq "pre") { $in{'message'} = "
$in{'message'}
"; } &header; print <<"EOM";
正常に書きこみが完了しました

おなまえ:$in{'name'}
Eメール:$in{'email'}
URL :$in{'url'}
タイトル:$in{'sub'}
メッセージ

$in{'message'}

EOM exit; } #--------------# # リスト表示 # #--------------# sub list_view { # 時間を取得 &get_time; &header; print "\n"; print "\n"; print "\n"; print "\n"; print "
\n"; print "
"; if ($t_gif) { print "\n"; } else { print "$title\n"; } #print "
\n"; print "[もどる]\n"; print "[新規投稿]\n"; if ($in{'list'} ne "new") { print "[新規順表\示]\n"; } else { print "[ツリー表\示]\n"; } print "[新着記事]\n"; print "[説明]\n"; #print "[メール配信]\n"; print "[ワード検索]\n"; if ($pastkey) { print "[過去ログ]\n"; } print "[管理用]\n"; #print "
\n"; print "
\n"; print "
  • $new_time時間以内の記事は NEW で表\示されます。
    \n"; if ($in{'list'} eq "new") { print "
  • 以下は新規投稿順のリスト表\示です。
    \n"; } else { print "
  • ツリー先頭部の $treehead をクリックすると関連記事を一括講読できます。
    \n"; } print "
  • \n"; print "
    \n"; print "

     

    \n"; print "
    \n"; # ログを開く if ($in{'list'} eq "new") { &ListNewOpen; } else { &ListTreeOpen; } print "[ページ移動]\n"; print "
    \n"; # メッセージ投稿フォ−ムを表示 &msg_form; exit; } #--------------------# # リストツリー表示 # #--------------------# sub ListTreeOpen { # ページ区切り処理 $x = 0; $start = $page + 1; $end = $page + $p_tree; print "
    \n"; open(IN,"$logfile") || &error("Open Error : $logfile"); $top = ; $i=0; while () { local($no,$reno,$lx,$sub,$email,$url, $name,$dat,$msg,$timek,$h,$p,$w,$oya) = split(/<>/); if ($reno == 0) { $i++; } if ($i < $start) { next; } if ($i > $end) { next; } while ($x > $lx) { print "\n"; $x--; } while ($x < $lx) { print "
      \n"; $x++; } # 所定時間以内の投稿は[NEWマーク]表示 if (($times - $timek) > $new_time*3600) { $newsign = ""; } else { $newsign = "NEW"; } if ($lx != 0) { $pointer = '
    • '; } else { $pointer="
      $treehead - "; } # 長い題名は後半をカット if (length($sub) > $sub_length) { $sub = substr($sub,0,30); $sub = $sub . '...'; } print "$pointer $sub - $name $dat No\.$no $refsign $newsign\n"; while ($x > 0) { print "
    \n"; $x--; } } close(IN); print "
    \n"; # ページ移動ボタン表示 $x=1; $y=0; while ($i > 0) { if ($page eq "$y") { print "[$x]\n"; } else { print "[$x]\n"; } $x++; $y = $y + $p_tree; $i = $i - $p_tree; } } #--------------------# # リスト新着順表示 # #--------------------# sub ListNewOpen { # ページ区切り処理 $x = 0; $p_tree *= 3; $start = $page + 1; $end = $page + $p_tree; open(IN,"$logfile") || &error("Open Error : $logfile"); $top = ; while () { local($no,$reno,$xl,$sub,$email,$url,$name, $date,$msg,$time,$h,$p,$wrap,$oya) = split(/<>/); $count{$no} = $time; $re{$no} = $reno; $d{$no} = $date; $na{$no} = $name; $no{$no} = $no; $ttl{$no} = $sub; $oya{$no} = $oya; $time{$no} = $time; } close(IN); print "
      \n"; # ソート処理 $i=0; foreach (sort { ($count{$b} <=> $count{$a}) || ($a cmp $b)} keys(%count)) { $i++; if ($i < $start) { next; } if ($i > $end) { next; } # 所定時間以内の投稿は[NEWマーク]表示 if (($times - $time{$_}) > $new_time*3600) { $newsign = ""; } else { $newsign = "NEW"; } print "
    • $ttl{$_} - $na{$_} $d{$_} No\.$_ $newsign\n"; } print "
    \n"; # ページ移動ボタン表示 $x=1; $y=0; while ($i > 0) { if ($page eq "$y") { print "[$x]\n"; } else { print "[$x]\n"; } $x++; $y = $y + $p_tree; $i = $i - $p_tree; } } #------------------# # プレビュー画面 # #------------------# sub preview { &get_agent; if ($in{'name'} eq "" || $in{'message'} eq "") { &error("名前又はメッセージに記入モレがあります"); } # E-Mail入力 if ($in_email && $in{'email'} !~ /(.+)\@(.+)\.(.+)/) { &error("E-Mailの入力が不正です"); } # if ($in{'no'} eq 'new' && !$in{'url'}) # { &error("設置スクリプトのURL記述は必須です"); } &header; print <<"HTML";
    - 以下の内容でメッセージを投稿しますが、よろしいですか? -

    HTML if ($in{'action'} eq "res_msg") { print "\n"; print "\n"; $width = $com_wid + 2; } else { print "\n"; $width = $com_wid; } $in{'message'} =~ s/
    /\r/g; $in{'message'} =~ s/\t//g; if ($in{'url'}) { $in{'url'} = "http://$in{'url'}"; } print <<"HTML"; 投稿者名$in{'name'}
    Eメール : $in{'email'}
    URL  : $in{'url'}
    タイトル$in{'sub'}

    [投稿フォームに戻る] HTML exit; } #------------------------# # メッセージ内容を表示 # #------------------------# sub msgview { # ファイルを読み込む open(IN,"$logfile") || &error("Open Error : $logfile"); $top = ; $flag=0; @new=(); $match=0; while () { local($no,$reno,$lx,$sub,$email,$url, $name,$dat,$msg,$lt,$ho,$pw,$wrap,$oya) = split(/<>/); if ($oya eq "$in{'oya'}") { push(@new,$_); } if ($no eq "$in{'no'}" && $reno eq "$in{'reno'}") { $flag=1; $v_date=$dat; $v_name=$name; $v_email=$email; $v_url=$url; $v_msg=$msg; $v_sub=$sub; $v_oya=$oya; $v_no=$no; $v_wrap=$wrap; } } close(IN); if ($v_email) { $v_email = "$v_email"; } if ($v_url) { $v_url = "http://$v_url"; } # レスメッセージ $res_msg = "> $v_msg"; $res_msg =~ s/
    /\r> /g; # レスタイトル $res_sub = $v_sub; if ($res_sub =~ /^Re\^(\d+)\:(.*)/) { $renum = $1 + 1; $res_sub = "Re\^$renum\:$2"; } elsif ($res_sub =~ /^Re\:(.*)/) { $res_sub = "Re\^2:$1"; } else { $res_sub = "Re: $res_sub"; } # HTMLを出力 &header; print "

    \n"; if ($t_gif) { print "\n"; } else { print "$title\n"; } print "
    \n"; print "[記事リスト]\n"; print "[新規投稿]\n"; print "[新着記事]\n"; print "[ワード検索]\n"; if ($pastkey) { print "[過去ログ]\n"; } print "[管理用]\n"; print "

    \n"; # 引用部色変更 if ($refcolor) { @vmsg = split(/
    /, $v_msg); $message=""; foreach (@vmsg) { $_ =~ s/^>(.*)/>$1<\/font>/ig; $message .= "$_
    "; } $v_msg = $message; } # 自動リンク if ($autolink) { &auto_link($v_msg); } # PREタグ if ($v_wrap eq 'pre') { $v_msg = "
    $v_msg
    "; } print "

    \n"; print "投稿時間:$v_date
    \n"; print "投稿者名:$v_name
    \n"; print "Eメール:$v_email
    \n"; print "URL :$v_url
    \n"; print "タイトル:$v_sub\n"; print "

    $v_msg

    \n"; if (@new > 1) { print "


    \n
    \n"; print "- 以下は関連一覧ツリーです -\n"; $x = 0; print "
    \n"; foreach (@new) { local($no,$reno,$lx,$sub,$email,$url, $name,$dat,$msg,$lt,$ho,$p,$w,$oya) = split(/<>/, $_); while ($x > $lx) { print ""; $x--; } while ($x < $lx) { print "
      "; $x++; } # 長い題名は後半をカット if (length($sub) > $sub_length) { $sub = substr($sub,0,30); $sub = $sub . '...'; } if ($lx != 0) { $pointer = "
    • "; } else { $pointer="$treehead - "; } print "
      $pointer $sub - $name $dat"; if ($v_no eq "$no") { print " No\.$no\n"; } else { print " No\.$no\n"; } while ($x > 0) { print "
    "; $x--; } } print "
    \n
    \n"; } # 返信フォーム &msg_form; exit; } #----------------# # 一括講読機能 # #----------------# sub allread { open(DB,"$logfile") || &error("Open Error : $logfile"); @lines = ; close(DB); # HTMLを出力 &header; print "[リストへもどる]
    \n"; print "
    \n"; print "一 括 講 読
    \n"; # 親記事を出力 $x = 0; print "
      \n"; $flag=0; $i=0; foreach (1 .. $#lines) { ($no,$reno,$lx,$sub,$email,$url, $name,$dat,$msg,$t,$h,$p,$wrap,$oya) = split(/<>/, $lines[$_]); if ($in{'no'} eq "$oya") { $i++; $flag=1; push(@new,$lines[$_]); while ($x > $lx) { print "
    "; $x--; } while ($x < $lx) { print "
      "; $x++; } # 長い題名は後半をカット if (length($sub) > $sub_length) { $sub = substr($sub,0,30); $sub = $sub . '...'; } print "
    • $sub - $name $dat"; print " No\.$no\n"; while ($x > 0) { print "
    "; $x--; } } elsif ($flag && $in{'no'} ne "$oya") { last; } } print "\n
    \n"; $i=0; foreach (@new) { $i++; ($no,$reno,$lx,$sub,$email,$url,$name, $dat,$msg,$t,$ho,$p,$wrap,$oya) = split(/<>/); if ($url) { $url="http://$url"; } if ($email) { $email="$email"; } # 引用部色変更 if ($refcolor) { @vmsg = split(/
    /, $msg); $message=""; foreach (@vmsg) { $_ =~ s/^>(.*)/>$1<\/font>/ig; $message .= "$_
    "; } $msg = $message; } # 自動リンク if ($autolink) { &auto_link($msg); } # 図表モード if ($wrap eq 'pre') { $msg = "
    $msg
    "; } print "\n"; print "\n"; print "
    \n"; print "\n"; print "投稿時間:$dat
    投稿者名:$name
    \n"; print "Eメール:$email
    URL :$url
    \n"; print "タイトル:$sub
    \n"; print "
    $msg
    \n"; print "
    \n"; print "
    \n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
    \n"; print "

    \n"; } print "
    \n"; &footer; exit; } #----------------------------# # 記事を新着順にソート表示 # #----------------------------# sub new_sort { &header; print "[リストへもどる]\n"; print "
    \n"; print "新着記事($sortcnt件)
    \n"; print "
    \n"; print "新着記事$sortcnt件を表\示しました

    \n"; open(IN,"$logfile") || &error("Open Error : $logfile"); $top = ; while () { ($no,$reno,$x,$sub,$email,$url,$name, $date,$msg,$time,$h,$p,$wrap,$oya) = split(/<>/); $count{$no} = $time; $d{$no} = $date; $na{$no} = $name; $em{$no} = $email; $url{$no} = $url; $no{$no} = $no; $reno{$no} = $reno; $ttl{$no} = $sub; $oya{$no} = $oya; if ($wrap eq 'pre') { $msg{$no} = "

    $msg
    "; } else { $msg{$no} = $msg; } } close(IN); # ソート処理 $i=0; foreach (sort { ($count{$b} <=> $count{$a}) || ($a cmp $b)} keys(%count)) { $i++; if ($i > $sortcnt) { last; } # ループを抜ける # 新着記事を出力 if ($em{$_}) { $em{$_} = "$em{$_}"; } if ($url{$_}) { $url{$_} = "http://$url{$_}"; } # 引用部色変更 if ($refcolor) { @vmsg = split(/
    /, $msg{$_}); $message=""; foreach (@vmsg) { $_ =~ s/^>(.*)/>$1<\/font>/ig; $message .= "$_
    "; } $msg{$_} = $message; } # 自動リンク if ($autolink) { &auto_link($msg{$_}); } print "\n"; print "
    \n"; print "\n"; print "投稿時間:$d{$_}
    投稿者名:$na{$_}
    \n"; print "Eメール:$em{$_}
    URL :$url{$_}
    \n"; print "タイトル:$ttl{$_}\n"; print "
    $msg{$_}
    \n"; print "
    \n"; print "
    \n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
    \n"; print "

    \n"; } print "
    \n"; &footer; exit; } #------------------# # HTMLのヘッダー # #------------------# sub header { $pt_b = $pt + 2 . 'pt'; $pt_s = $pt - 2 . 'pt'; $pt .= pt; $t_point .= pt; print "Content-type: text/html\n\n" if (!$HeadFlag); $HeadFlag = 1; print <<"EOM"; $title $body EOM } ## --- HTMLのフッター sub footer { # 著作権表示(削除しないで下さい) print "

    \n"; print "- Web Forum -\n"; print "
    \n"; print "\n"; } ## --- エラー処理 sub error { if (-e $lockfile) { unlink($lockfile); } &header; print "

    ERROR !

    \n"; print "

    $_[0]

    \n"; print "


    \n"; &footer; exit; } #------------------# # 投稿フォーム部 # #------------------# sub msg_form { &get_cookie; &get_agent; print "


    \n"; if ($mode eq 'msgview') { $width = $com_wid + 2; print "

    このメッセージに返信する場合は下記フォームから投稿して下さい。

    \n"; print "
    \n"; print "\n"; print "\n"; print "\n"; print "\n"; } else { $width = $com_wid; print "メッセージをどうぞ・・

    \n"; print "\n"; print "\n"; print "\n"; print "\n"; } # プレビューのチェック if ($c_pview eq "on") { $checked = "checked"; } print <<"HTML";

    おなまえ
    Eメール
    題   名
    メッセージ    手動改行 強制改行 図表\モード
    URL
    削除キー (記事削除時に使用。英数字で8文字以内)
    プレビュー

    以下のフォームから自分の投稿した記事を削除できます
    ■記事No ■削除キー

    HTML &footer; } #----------------# # 記事削除処理 # #----------------# sub usr_del { # フォーム内容のチェック if ($in{'usr_no'} eq '' || $in{'usr_key'} eq '') { &error("記事NOまたは削除キーの記入モレがあります"); } # ロック開始 if ($lockkey == 1) { &lock1; } elsif ($lockkey == 2) { &lock2; } # ログを読み込む open(DB,"$logfile") || &error("Can't open $logfile"); @lines = ; close(DB); # カウンタ値を退避 $cnt = shift(@lines); # 親記事対策のため逆順へ @lines = reverse(@lines); @new = (); $no_del = 0; ## 削除キーによる記事削除 ## @new=(); $oflag=0; foreach $line (@lines) { local($no,$reno,$lx,$tl,$em,$ur,$na, $dt,$msg,$tm,$ho,$ango,$w,$oya) = split(/<>/,$line); if ($no ne "$oya" && $in{'usr_no'} eq "$oya") { $oflag=1; } $flag = 0; if ($in{'usr_no'} eq "$no") { if ($ango eq "") { $no_del = 1; last; } $match = &decrypt("$in{'usr_key'}", "$ango"); if ($match eq "yes") { if ($oflag) { $line="$no<>$reno<>$lx<>(削除)<><><>(削除)<>$dt<>(削除されました)<>$tm<>$ho<><>$w<>$oya<>\n"; } else { $flag = 1; } } else { $no_del = 2; last; } } if ($flag == 0) { push(@new,$line); } } if ($no_del == 1) { &error("削除キーが設定されていません"); } elsif ($no_del == 2) { &error("パスワードが違います"); } # カウンタ値を付加 @new = reverse(@new); unshift(@new,$cnt); # ログを更新 open(DB,">$logfile") || &error("Can't write $logfile"); print DB @new; close(DB); # ロック解除 if (-e $lockfile) { unlink($lockfile); } # リスト表示部にもどる &list_view; } #----------------------# # 投稿フォームを調整 # #----------------------# sub get_agent { # ブラウザ情報を取得 $agent = $ENV{'HTTP_USER_AGENT'}; if ($agent =~ /MSIE 3/i) { $nam_wid = 30; $sub_wid = 40; $com_wid = 64; $url_wid = 46; } elsif ($agent =~ /MSIE 4/i || $agent =~ /MSIE 5/i) { $nam_wid = 30; $sub_wid = 40; $com_wid = 64; $url_wid = 70; } else { $nam_wid = 20; $sub_wid = 27; $com_wid = 62; $url_wid = 52; } # 返信フォームは1文字広く取る #if ($mode eq "msgview") { $com_wid = $com_wid + 2; } } #--------------------------------# # ロックファイル : 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) { if (-e $lockfile) { sleep(1); } else { $flag = 1; open(LOCK,">$lockfile"); close(LOCK); last; } } if ($flag == 0) { &error("LOCK is BUSY"); } } #--------------# # メール送信 # #--------------# sub mail_to { # メールタイトル $MailSub = "$title$count:$in{'sub'}"; $in{'message'} =~ s/<//g; $in{'message'} =~ s/&/&/g; $in{'message'} =~ s/
    /\n/g; if ($in{'url'}) { $in{'url'} = "http://$in{'url'}"; } # メール本文 $MailBody = <<"EOM"; $titleに$in{'name'}さんから投稿がありました。 $in{'message'} このメッセージの返信は $web$scrip へ ---------------------------------------------------- $date/$host $ENV{'HTTP_USER_AGENT'} $in{'email'} $in{'url'} EOM &jcode'convert(*MailSub,'jis'); &jcode'convert(*MailBody,'jis'); if ($in{'email'} eq "") { $in{'email'} = 'nomail@xxx.xxx'; } if (!open(MAIL,"| $sendmail -t")) { &error("メール送信に失敗しました"); } print MAIL "To: $mailto\n"; print MAIL "From: $mailfrom\n"; print MAIL "Subject: $MailSub\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"; print MAIL "X-Mailer: $ver\n\n"; print MAIL "$MailBody\n"; close(MAIL); } #------------------# # クッキーの発行 # #------------------# sub set_cookie { ($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg) = gmtime(time + 60*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 = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat') [$wdayg]; $date_gmt = "$youbi, $mdayg\-$month\-$yearg $hourg:$ming:$secg GMT"; $cook="name\:$in{'name'}\,email\:$in{'email'}\,url\:$in{'url'}\,pwd\:$in{'pwd'}\,pview\:$in{'pview'}"; print "Set-Cookie: WebForum=$cook; expires=$date_gmt\n"; } #------------------# # クッキーを取得 # #------------------# sub get_cookie { @pairs = split(/;/, $ENV{'HTTP_COOKIE'}); foreach (@pairs) { local($name, $value) = split(/=/); $name =~ s/ //g; $DUMMY{$name} = $value; } @pairs = split(/,/, $DUMMY{'WebForum'}); foreach (@pairs) { local($name, $value) = split(/:/); $COOKIE{$name} = $value; } $c_name = $COOKIE{'name'}; $c_email = $COOKIE{'email'}; $c_url = $COOKIE{'url'}; $c_pwd = $COOKIE{'pwd'}; $c_pview = $COOKIE{'pview'}; if ($in{'name'}) { $c_name = $in{'name'}; } if ($in{'email'}) { $c_email = $in{'email'}; } if ($in{'url'}) { $c_url = $in{'url'}; } if ($in{'pwd'}) { $c_pwd = $in{'pwd'}; } if ($in{'pview'}) { $c_pview = $in{'pview'}; } } #----------------------# # パスワード暗号処理 # #----------------------# sub encrypt { local($inpw) = $_[0]; local(@SALT, $salt, $encrypt); @SALT = ('a'..'z', 'A'..'Z', '0'..'9', '.', '/'); srand; $salt = $SALT[int(rand(@SALT))] . $SALT[int(rand(@SALT))]; $encrypt = crypt($inpw, $salt) || crypt ($inpw, '$1$' . $salt); return $encrypt; } #----------------------# # パスワード照合処理 # #----------------------# sub decrypt { local($inpw, $logpw) = @_; local($salt, $key, $check); $salt = $logpw =~ /^\$1\$(.*)\$/ && $1 || substr($logpw, 0, 2); $check = "no"; if (crypt($inpw, $salt) eq "$logpw" || crypt($inpw, '$1$' . $salt) eq "$logpw") { $check = "yes"; } return $check; } #------------# # 検索機能 # #------------# sub find { &header; print <<"EOM"; [リストにもどる]
    ワード検索

    • 検索したいキーワードを入力し、検索条件を選択し「検索する」を押してください。
    • 複数のキーワードを入力するときは、半角スペースで区切って下さい。 EOM if ($pastkey) { print "
    • 過去ログは新着順に5ファイル毎に区切っています。\n"; } print <<"EOM";
    EOM # 過去ログ表示 if ($pastkey) { print "\n"; print "\n"; } else { print "\n"; } print "\n"; print "
    キーワード
    検索条件 AND OR
    検索領域現行ログ\n"; open(NO,"$past_num"); $no = ; close(NO); $part = $no / 5; $part = int($part+1); # $i=0; $j=$part; foreach (1 .. $part) { # $i++; # if ($i == 3) { print "
    "; $i=0; } if ($in{'log'} == $j) { $selected = " selected"; } else { $selected = ""; } # print "過去ログ$j\n"; print "
    "; print "
    \n"; # ワード検索の実行と結果表示 if ($in{'word'} ne "") { # 入力内容を整理 $cond = $in{'cond'}; $word = $in{'word'}; $word =~ s/ / /g; $word =~ s/\t/ /g; @pairs = split(/ /,$word); # 現行ログのとき if ($in{'log'} == 0) { # ファイルを読み込み open(DB,"$logfile") || &error("Can't open $logfile"); @lines = ; close(DB); shift(@lines); # 過去ログのとき } else { # 検索領域を定義 $start = 5 * $in{'log'} - 4; @lines = (); foreach ($start .. $start+4) { unless(-e "$past_dir\/$_\.html") { last; } open(DB,"$past_dir\/$_\.html"); @temp = ; close(DB); push(@lines,@temp); } } # 検索処理 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; } } } if ($flag == 1) { push(@new,$line); } } # 検索終了 $count = @new; print "
    検索結果:$count件

    \n"; print "

      \n"; if ($in{'log'} == 0) { foreach (@new) { ($num,$reno,$x,$sub,$email, $url,$name,$date,$msg,$time) = split(/<>/); if ($email) { $name = "$name"; } if ($url) { $url = "http://$url"; } # 結果を表示 print "
    1. [$num] $sub\n"; print "投稿者:$name 投稿日:$date\n"; print "

      $msg

      $url


      \n"; } } else { foreach (@new) { ($p1,$p2) = split(/<\!--T-->/); print "
    2. $p1 \- $p2\n"; } } } print "
    \n"; &footer; exit; } #--------------# # 自動リンク # #--------------# sub auto_link { $_[0] =~ s/([^=^\"]|^)(http\:\/\/[\w\.\~\-\/\?\&\=\;\#\:\%]+)/$1$2<\/a>/g; } #--------------# # 時間の取得 # #--------------# sub get_time { # タイムゾーンを日本時間に合わせる $ENV{'TZ'} = "JST-9"; $times = time; ($sec,$min,$hour,$day,$mon,$year,$wday,$dmy,$dmy) = localtime($times); $year += 1900; $year = substr($year,-2,2); # 日時のフォーマット @week = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); $date = sprintf("%02d\/%02d\/%02d(%s) %02d\:%02d", $year,$mon+1,$day,$week[$wday],$hour,$min); } #----------------# # ホスト名取得 # #----------------# sub get_host { $host = $ENV{'REMOTE_HOST'}; $addr = $ENV{'REMOTE_ADDR'}; if ($get_remotehost) { if ($host eq "" || $host eq "$addr") { $host = gethostbyaddr(pack("C4", split(/\./, $addr)), 2); } } if ($host eq "") { $host = $addr; } } #------------# # 過去ログ # #------------# sub past_log { # カウントファイル読み込み open(NO,"$past_num") || &error("Can't open $past_num"); $no = ; close(NO); # 過去ログを定義 $pastfile = "$past_dir\/$no\.html"; # 過去ログがない場合、新規に自動生成する unless(-e $pastfile) { &new_log; } @temp=(); foreach (@PAST) { ($pno,$pre,$plx,$ptitle,$pem, $purl,$pna,$pda,$pmsg,$pt2,$ph) = split(/<>/, $_); if ($pem) { $pna = "$pna"; } if ($purl) { $purl = "<URL>"; } # 自動リンク if ($autolink) { &auto_link($pmsg); } # 記事をフォーマットし配列化 push(@temp,"[$pno] $ptitle 投稿者:$pna 投稿日:$pda $purl
    $pmsg

    \n"); } # HTMLログを開く open (DB,"$pastfile") || &error("Can't open $pastfile"); @past = ; close(DB); # 規定の行数をオーバーすると、次ファイルを自動生成する if ($#past > $max_line) { &next_log; } @news = (); $i = 1; foreach $line (@past) { if ($line =~ //i) { last; } push (@news,$line); if ($line =~ //i) { push (@news,@temp); } } push (@news,"\n\n"); # ログを更新 open (DB,">$pastfile") || &error("Can't write $pastfile"); print DB @news; close(DB); } #--------------------------# # 過去ログ次ファイル生成 # #--------------------------# sub next_log { # 次ファイルのためのカウントアップ $no++; # カウントファイル更新 open(NUM,">$past_num") || &error("Can't write $past_num"); print NUM "$no"; close(NUM); $pastfile = "$past_dir\/$no\.html"; &new_log; } #----------------------------# # 新規過去ログファイル生成 # #----------------------------# sub new_log { $new_flag = 1; $past[0] = "過去ログ\n"; $past[1] = "$body
    \n"; $past[2] = "<\!--BEGIN-->\n"; $past[3] = "<\!--FINISH-->\n"; $past[4] = "\n"; # 新規過去ログファイルを生成更新 open(DB,">$pastfile") || &error("Can't write $pastfile"); print DB @past; close(DB); # パーミッションを666へ chmod(0666,"$pastfile"); }