#!/usr/local/bin/perl ## SPHINX BOARD v2.42 (2000/12/29) ## Copyright(C) Kent Web 1997-2000 ## webmaster@kent-web.com ## http://www.kent-web.com/ $ver = 'SPHINX v2.42'; #--- [注意事項] ------------------------------------------------# # 1. このスクリプトはフリーソフトです。このスクリプトを使用した # # いかなる損害に対して作者は一切の責任を負いません。 # # 2. 設置に関する質問はサポート掲示板にお願いいたします。 # # 直接メールによる質問は一切お受けいたしておりません。 # #---------------------------------------------------------------# #============# # 設定項目 # #============# # jcode.plが同一ディレクトリにある場合 require './jcode.pl'; # タイトル名 $title = "Townmag Partner's掲示板"; # タイトル文字の色 $t_color = "#008080"; # タイトル文字の大きさ $t_size = 6; # bodyタグ $body = ''; # 戻り先のURL (index.htmlなど) $homepage = '../talkboard/index.html'; # 最大記事数 $max = 100; # 管理者用マスタパスワード(英数字) $pass = '11t3m214'; # 上下のID/PASS配列はコンマで区切っていくつでも指定可。(必ずペアで指定) @userid = ('town200102'); # ユーザID @userpwd = ('w46uc3r'); # ユーザPASSWORD # タグの許可 (0=no 1=yes) $tagkey = 0; # スクリプトファイル名 $script = "./sphinx.cgi"; # ログファイル名 $logfile = "./townmag1.log"; # methodの形式 (POST or GET) $method = 'POST'; # 1ページ当たりの記事表示数 $pagelog = 10; # ロック形式 (0=no 1=symlink 2=open) $lockkey = 2; # ロックファイル名 $lockfile = "./townmag1.lock"; # 投稿があるとメール通知する (0=no 1=yes) : sendmail必須 $mailing = 1; # メールアドレス (メール通知する時) $mailto = 'editor@townmag.com'; # sendmailパス(メール通知する時) $sendmail = '/usr/lib/sendmail'; # コメント部 [題名] の色 $sub_color = "#008040"; # コメント部 [名前] の色 $name_color = "#0000EC"; # ホスト名取得モード # --> 0 : $ENV{'REMOTE_HOST'} で取得できる場合 # --> 1 : gethostbyaddr で取得できる場合 $get_remotehost = 0; #============# # 設定完了 # #============# $agent = $ENV{'HTTP_USER_AGENT'}; # ブラウザ情報を取得 ## --- メイン処理 &form_deco; if ($buffer eq "") { ✓ } &pass_chk; if ($mode eq "howto") { &howto; } if ($mode eq "find") { &find; } if ($mode eq "usr_del") { &usr_del; } if ($mode eq "msg") { ®ist; } &html_log; ## --- パスワード画面 sub check { &get_cookie('IN'); print "Content-type: text/html\n\n"; print <<"HTML"; $title


ネットワークパスワードの入力
認証情報を入力してください。

リソ\ース: $title
ユーザ名
パスワード
このパスワードを保存する
HTML exit; } ## --- パスワードエラー処理 sub pass_error { print "Content-type: text/html\n\n"; print <<"HTML"; 401 Authorization Required

Authorization Required

This server could not verify that you are authorized to access the document you requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required.

HTML exit; } ## --- ID/PASSチェック処理 sub pass_chk { # ID/PASSをチェックする $flag = 0; foreach (0 .. $#userid) { if ($usrid eq "$userid[$_]" && $inpwd eq "$userpwd[$_]") { $flag = 1; next; } } # 該当なしの場合はエラー処理 if ($flag == 0) { &pass_error; } # ID/PASS情報をクッキー格納 if ($in{'chk'} eq 'on') { &set_cookie('IN'); } } ## --- HTMLのヘッダー sub header { print "Content-type: text/html\n\n"; print "\n\n"; print "\n"; print "$title\n"; print "$body\n"; } ## --- 記事表示部 sub html_log { &get_cookie; &get_agent; open(IN,"$logfile") || &error("Can't open $logfile"); @DATA = ; close(IN); # 返信の場合 if ($mode eq "res") { foreach (@DATA) { ($no,$date,$name,$email,$rsub,$rcom,$url,$host,$pw) = split(/<>/, $_); if ($no eq "$in{'resno'}") { last; } } $rcom =~ s/
/\r> /ig; $rcom = "> $rcom"; if (!$rsub) { $rsub = '無題'; } $rsub =~ s/^Re//g; $rsub = "Re[$no]: $rsub"; } &header; print <<"EOM";

$title
[トップにもどる] [掲示板の使い方] [ワード検索]
おなまえ
Eメール
題  名  
コメント
URL
削除キー (自分の記事を削除することが可能\)

EOM if ($in{'page'} eq '') { $page = 0; } else { $page = $in{'page'}; } # 記事数を取得 $end_data = @DATA - 1; $page_end = $page + ($pagelog - 1); if ($page_end >= $end_data) { $page_end = $end_data; } foreach ($page .. $page_end) { ($no,$date,$name,$email,$sub,$com,$url,$host,$pw) = split(/<>/, $DATA[$_]); if ($email) { $name="$name"; } if (!$sub) { $sub = "無題"; } if ($url) { $url = "http://$url\n"; } print "\n"; print "\n"; print "
[$no] $sub "; print "投稿者:$name "; print "投稿日:$date
\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
\n"; print "
$com

$url


\n"; } print "\n"; # 改頁処理 $next_line = $page_end + 1; if ($page_end ne $end_data) { print "\n"; } # ユーザ記事削除フォーム print <<"HTML";
\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
以下のフォームから自分の投稿した記事を削除できます
■記事No ■削除キー
HTML # 著作権表示 (削除不可) print "
\n"; print "- SPHINX BOARD -\n"; print "
\n"; print "\n"; exit; } ## --- ログ書き込み処理 sub regist { # 名前とコメントは必須 if ($in{'name'} eq "") { &error("名前が入力されていません"); } if ($in{'comment'} eq "") { &error("コメントが入力されていません"); } # クッキーを格納 &set_cookie; # ファイルロック if ($lockkey == 1) { &lock1; } elsif ($lockkey == 2) { &lock2; } # ログを開く open(LOG,"$logfile") || &error("Can't open $logfile"); @lines = ; close(LOG); # 二重投稿の禁止 ($knum,$kdate,$kname,$kemail,$ksub,$kcom) = split(/<>/, $lines[0]); if ($name eq $kname && $comment eq $kcom) { &error("二重投稿は禁止です"); } # 記事Noカウント及び最大記事数超を切り捨て @new = (); for($i=0;$i<$max-1;$i++) { push (@new,$lines[$i]); } $number = $knum + 1; # 削除キーを暗号化 if ($in{'usr_pwd'}) { &passwd_encode; } # 時間を取得 &get_time; # ホスト名を取得 &get_host; # ログをフォーマット unshift (@new,"$number<>$date<>$name<>$email<>$subj<>$comment<>$url<>$host<>$encode_pwd<>\n"); # ログを更新 open(LOG,">$logfile") || &error("Can't write $logfile"); print LOG @new; close(LOG); # ロック解除 if (-e $lockfile) { unlink($lockfile); } # メール処理 if ($mailing && $in{'email'} ne "$mailto") { &mail_to; } } ## --- フォームからのデータ処理 sub form_deco { 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 $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 ($tagkey == 0) { $value =~ s/\"/"\;/g; $value =~ s//>\;/g; } else { $value =~ s///g; $value =~ s/<>/<\;>\;/g; } $in{$name} = $value; } $name = $in{'name'}; $comment = $in{'comment'}; $comment =~ s/\r\n/
/g; $comment =~ s/\r/
/g; $comment =~ s/\n/
/g; $email = $in{'email'}; $url = $in{'url'}; $url =~ s/^http\:\/\///; $mode = $in{'mode'}; $pwd = $in{'pwd'}; $subj = $in{'subj'}; $usr_pwd = $in{'usr_pwd'}; $usrid = $in{'usrid'}; $usrid =~ s/\s*//g; $inpwd = $in{'inpwd'}; $inpwd =~ s/\s*//g; } ## --- 掲示板の使い方メッセージ sub howto { if($tagkey == 0) { $tag_msg = "投稿内容には、タグは一切使用できません。\n"; } else { $tag_msg = "コメント欄には、タグ使用をすることができます。\n"; } &header; print <<"HTML"; ▲ BBS
掲示板の利用上の注意

  1. この掲示板はクッキー対応です。1度記事を投稿いただくと、おなまえ、Eメール、URL、削除キーの情報は2回目以降は自動入力されます。(ただし利用者のブラウザがクッキー対応の場合)

  2. $tag_msg

  3. 記事を投稿する上での必須入力項目は「おなまえ」「メッセージ」です。Eメール、URL、題名、削除キーは任意です。

  4. 記事には、半角カナは一切使用しないで下さい。文字化けの原因となります。

  5. 記事の投稿時に「削除キー」にパスワード(英数字で8文字以内)を入れておくと、その記事は次回削除キーによって削除することができます。

  6. 記事の保持件数は最大 $max件です。それを超えると古い順に自動削除されます。

  7. 既存の記事に「返信」することができます。各記事にある「返信」ボタンを押すと返信用フォームとなります。

  8. 過去の投稿記事から「キーワード」によって簡易検索ができます。トップメニューの「ワード検索」のリンクをクリックすると検索モードとなります。

  9. 管理者が著しく不利益と判断する記事や他人を誹謗中傷する記事は\予\告\なく削除することがあります。
HTML exit; } ## --- ワード検索サブルーチン sub find { &header; print <<"HTML"; ▲BBS
ワード検索

検索したいキーワードを入力し、検索領域を選択して「検索ボタン」 を押してください。

キーワード
検索条件 AND OR
HTML # ワード検索の実行と結果表示 if($in{'word'} ne ""){ # 入力内容を整理 $cond = $in{'cond'}; $word = $in{'word'}; $word =~ s/ / /g; $word =~ s/\t/ /g; @pairs = split(/ /,$word); # ファイルを読み込み open(DB,"$logfile") || &error("Can't open $logfile"); @lines = ; close(DB); # 検索処理 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"; foreach $line (@new) { ($num,$date,$name,$email,$sub,$comment,$url) = split(/<>/,$line); if (!$sub) { $sub = "無題"; } if ($email) { $name = "$name"; } if ($url) { $url = "http://$url"; } # 結果を表示 print "
  1. [$num] $sub 投稿者:$name\n"; print "投稿日:$date

    \n"; print "

    $comment

    $url


    \n"; } print "
\n"; } print "\n"; exit; } ## --- ブラウザを判断しフォーム幅を調整 sub get_agent { if ($agent =~ /MSIE 3/i) { $nam_wid = 30; $subj_wid = 40; $com_wid = 65; $url_wid = 48; } elsif ($agent =~ /MSIE 4/i || $agent =~ /MSIE 5/i) { $nam_wid = 30; $subj_wid = 40; $com_wid = 65; $url_wid = 78; } else { $nam_wid = 20; $subj_wid = 25; $com_wid = 56; $url_wid = 50; } } ## --- クッキーの発行 sub set_cookie { # IDを区分け if ($_[0] eq 'IN') { $cookie_id = SPX1; } else { $cookie_id = SPX2; } ($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\:$name\,email\:$email\,url\:$url\,pwd\:$usr_pwd\,inpwd\:$inpwd\,usrid\:$usrid"; print "Set-Cookie: $cookie_id=$cook; expires=$date_gmt\n"; } ## --- クッキーを取得 sub get_cookie { # IDを区分け if ($_[0] eq 'IN') { $cookie_id = SPX1; } else { $cookie_id = SPX2; } $cookies = $ENV{'HTTP_COOKIE'}; @pairs = split(/\;/, $cookies); foreach $pair (@pairs) { local($name, $value) = split(/=/, $pair); $name =~ s/ //g; $DUMMY{$name} = $value; } @pairs = split(/\,/, $DUMMY{$cookie_id}); foreach $pair (@pairs) { local($name, $value) = split(/\:/, $pair); $COOKIE{$name} = $value; } $c_name = $COOKIE{'name'}; $c_email = $COOKIE{'email'}; $c_url = $COOKIE{'url'}; $c_pwd = $COOKIE{'pwd'}; $c_usrid = $COOKIE{'usrid'}; $c_inpwd = $COOKIE{'inpwd'}; if ($_[0] eq 'IN') { if ($in{'usrid'}) { $c_usrid = $in{'usrid'}; } if ($in{'inpwd'}) { $c_inpwd = $in{'inpwd'}; } } else { if ($in{'name'}) { $c_name = $in{'name'}; } if ($in{'email'}) { $c_email = $in{'email'}; } if ($in{'url'}) { $c_url = $url; } if ($in{'usr_pwd'}) { $c_pwd = $in{'usr_pwd'}; } } } ## --- エラー処理 sub error { if (-e $lockfile) { unlink($lockfile); } &header; print "

ERROR !

\n"; print "

$_[0]\n"; print "


\n"; print "\n"; exit; } ## --- 記事削除処理 sub usr_del { # ロック開始 if ($lockkey == 1) { &lock1; } elsif ($lockkey == 2) { &lock2; } # ログを読み込む open(DB,"$logfile") || &error("Can't open $logfile"); @lines = ; close(DB); @new = (); $no_del = 0; ## マスターパスワードによる記事削除 ## if ($in{'usr_key'} eq "$pass"){ foreach $line (@lines){ ($number,$date,$name,$email,$subj,$comment, $url,$host,$encode_pwd) = split(/<>/, $line); $flag=0; if ($in{'usr_no'} eq "$number"){$flag=1;} if ($flag == 0){push(@new,$line);} } } ## 削除キーによる記事削除 ## else { foreach $line (@lines) { ($number,$date,$name,$email,$subj, $comment,$url,$host,$encode_pwd) = split(/<>/, $line); $flag = 0; if ($in{'usr_no'} eq "$number"){ if ($encode_pwd eq "") { $no_del = 1; last; } $plain_text = "$in{'usr_key'}"; &passwd_decode; if ($check eq "yes") { $flag = 1; } else { $no_del = 2; last; } } if ($flag == 0) { push(@new,$line); } } if ($no_del == 1) { &error("削除キーが設定されていません。"); } elsif ($no_del == 2) { &error("パスワードが違います。"); } } ## ログを更新 ## open(DB,">$logfile") || &error("Can't write $logfile"); print DB @new; close(DB); # ロック解除 if (-e $lockfile) { unlink($lockfile); } # 記事表示部にもどる &html_log; } ## --- ロックファイル(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") || &error("Can't create $lockfile"); close(LOCK); $flag = 1; last; } else { sleep(1); } } if ($flag == 0) { &error("LOCK is BUSY"); } } ## --- メール送信 sub mail_to { $mail_subj = "$title に投稿がありました。"; &jcode'convert(*mail_subj,'jis'); &jcode'convert(*name,'jis'); &jcode'convert(*subj,'jis'); &jcode'convert(*comment,'jis'); $comment =~ s/
/\n/g; $comment =~ s/<//g; # メールアドレスがない場合はダミーメールに置き換え if ($in{'email'} eq "") { $email = "nomail\@xxx.xxx"; } if (open(MAIL,"| $sendmail $mailto")) { print MAIL "To: $mailto\n"; print MAIL "From: $email\n"; print MAIL "Subject: $mail_subj\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 "$mail_subj\n"; print MAIL "--------------------------------------------------------\n"; print MAIL "TIME : $date\n"; print MAIL "NAME : $name\n"; print MAIL "EMAIL: $in{'email'}\n"; if ($url) { print MAIL "URL : http://$url\n"; } if (!$subj) { $subj = "Untitled"; } print MAIL "TITLE: $subj\n\n"; print MAIL "$comment\n\n"; print MAIL "--------------------------------------------------------\n"; close(MAIL); } } ## --- パスワード暗号処理 sub passwd_encode { $now = time; ($p1, $p2) = unpack("C2", $now); $wk = $now / (60*60*24*7) + $p1 + $p2 - 8; @saltset = ('a'..'z','A'..'Z','0'..'9','.','/'); $nsalt = $saltset[$wk % 64] . $saltset[$now % 64]; $encode_pwd = crypt($in{'usr_pwd'}, $nsalt); } ## --- パスワード照合処理 sub passwd_decode { if ($encode_pwd =~ /^\$1\$/) { $crptkey = 3; } # FreeBSDサーバ対応 else { $crptkey = 0; } $check = "no"; if (crypt($plain_text, substr($encode_pwd,$crptkey,2)) eq $encode_pwd) { $check = "yes"; } } ## --- 時間を取得 sub get_time { $ENV{'TZ'} = "JST-9"; ($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime(time); $year += 1900; $mon++; if ($mon < 10) { $mon = "0$mon"; } if ($mday < 10) { $mday = "0$mday"; } if ($hour < 10) { $hour = "0$hour"; } if ($min < 10) { $min = "0$min"; } if ($sec < 10) { $sec = "0$sec"; } $week = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat') [$wday]; # 日時のフォーマット $date = "$year\/$mon\/$mday\($week\) $hour\:$min\:$sec"; } ## --- ホスト名取得 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; } }