#! /usr/local/bin/perl # #========================================================================================== # # 多機能(?)掲示板システム 『Suzuki's Simple Board』ver 1.27 # # Copyright Shinobu Suzuki 1998. All rights reserved. #----------------------------------------------------------------------------------------- # HomePage : http://www.aikis.or.jp/~s-suzuki/cgilabo/ # E-mail : s-suzuki@aikis.or.jp #========================================================================================== # # 初期設定 # #--------------------------------------------------------------------- $script = 'ssboard'; # 掲示板スクリプト名(ファイル名のみ、拡張子なし) $version = '1.27'; # 本スクリプトのバージョン #--------------------------------------------------------------------- # ボード定義情報:デフォルト値 # ・定義ファイルを使用する場合は、そちらが優先されます。 # ・定義ファイルに無い項目がある場合、ここで定義する値が使用されます。 # ・定義ファイルを使用する場合は、この項目は削除してもかまいません。 #--------------------------------------------------------------------- $max = '50'; # 最大ログ数(0で無制限に保存) $max_comment = '10'; # コメントの最大数(1〜99) $page = '20'; # 1ページあたりのメッセージ数(0でページ処理をしない) $user_name = ''; # ボードの主催者名 $user_email = ''; # 主催者のE-mailアドレス $title = "SSBoard v$version"; # 掲示板のタイトル $title_image = ''; # タイトル画像(URL:省略可) $bg_col = '#f0f0f0'; # 背景色 $bg_image = ''; # 背景画像(URL:省略可) $title_col = '#000090'; # タイトルの色 $text_col = '#000000'; # テキストの色 $link_col = '#0000ff'; # リンクの色 $alink_col = '#ff0000'; # リンク中の色 $vlink_col = '#900090'; # 既リンクの色 $subject_col = '#ff0000'; # 題名の色 $name_col = '#009000'; # 投稿者名の色 $linkname1 = ''; # 外部リンク その1 $link1 = ''; # 外部リンク その1(URL) $linkname2 = ''; # 外部リンク その2 $link2 = ''; # 外部リンク その2(URL) $linkname3 = ''; # 外部リンク その3 $link3 = ''; # 外部リンク その3(URL) $readme = ''; # 掲示板の説明文 $readme2 = ''; # 書き込み画面の説明文 $max_size = '1500'; # 最大書き込みサイズ(0で制限なし) $max_subject = '100'; # 題名のサイズ $max_name = '100'; # 投稿者名のサイズ $max_email = '100'; # 投稿者emailのサイズ $max_url = '200'; # 投稿者homeのサイズ #---------------------------------------------------------- # ボード情報定義ファイル名 # 例) $cfg_name = "ssboard.cfg"; #---------------------------------------------------------- # $cfg_name = ""; #---------------------------------------------------------- # ログファイル名についてはセキュリティ上、変更しておいた方 # がよいと思います。 #---------------------------------------------------------- # $log_name = "ssboard.log"; #---------------------------------------------------------- # デフォルトセキュリティレベルの設定 # セキュリティレベルの設定がされていない場合のデフォルト # 0:制限なし # 1:JPドメインのみ許可 # 2:プロキシの禁止 # 3:JPおよびプロキシ #---------------------------------------------------------- # $security = '0'; #---------------------------------------------------------- # 許可したいプロキシ(と誤判定されるドメイン)を設定する #---------------------------------------------------------- @proxylist = ( "aikis.or.jp", "cypress.ne.jp" ); #---------------------------------------------------------- # 利用制限するドメインリストのファイル名 # 省略すると、ドメイン制限は行われません # $domain_file = "domain.lst"; #---------------------------------------------------------- $domain_file = ""; #---------------------------------------------------------- # クッキー処理のためのクッキー名 # 変更しない場合、複数のボードで同じクッキーが利用されるこ # とになり、支障をきたすこともあります #---------------------------------------------------------- # $cookie_name = "ssb001"; #---------------------------------------------------------- # 管理用パスワード # 当然のことですが、できるだけ類推できにくいものを設定して # ください。できれば8文字より長いものにしましょう #---------------------------------------------------------- # $user_pass = "1234"; #---------------------------------------------------------- # ファイル入出力時にファイルロックを行う設定。これにより、 # 同時アクセス時の問題が多少マシになる(?) # サーバーが flock()関数を使える設定の場合のみ利用できます # 0:ファイルロックを行わない # 1:flock()でファイルロックを行う #---------------------------------------------------------- # $lockmode = 0; #---------------------------------------------------------- # 掲示板メンテナンス中の時に指定するフラグ。 # メンテナンス中は読み込み・書き込みの制限ができます。 # 0:通常の運用 1:書き込みを禁止 2:表示も禁止 #---------------------------------------------------------- # $maintenance = 0; #---------------------------------------------------------- # CERN系のサーバーなどで、ファイル関係でエラーが出る場合、 # 以下に設置するディレクトリのサーバー内でのフルパスを指定 # してみると、正常に動作することがあるかもしれません ^^;; # # 最後は / で終わること。 # 例:$path = '/home/user/foo/public_html/cgi-bin/bbs/'; #---------------------------------------------------------- # $path = ''; #---------------------------------------------------------- # 外部からの(イタズラ)書き込みを禁止する場合、以下に、ス # クリプトのURLを記入する。(サーバーやブラウザによっては # うまく働かないこともあります) # 例:$script_url = 'http://www.foo.com/~foo/ssboard.cgi'; #---------------------------------------------------------- # $script_url = ''; #---------------------------------------------------------- # 書き込みの後のリロードに失敗する場合(File Not Foundので # る場合)、CGIスクリプトを設置するディレクトリ名をURLで指 # 定すると成功する場合があるそうです。 # ※この機能については未確認です # ※biglobeでは成功するそうです # ※v1.27より記述方法を変更しています # ※最後は / で終わること。 # 例:$rerload_url = 'http://www.aikis.or.jp/~s-suzuki/multibbs/'; #---------------------------------------------------------- $reload_url = ''; #---------------------------------------------------------- # 日本語コード変換ライブラリの指定 #---------------------------------------------------------- # require "$path"."jcode.pl"; #========================================================================================= # これより、処理の開始 #========================================================================================= $| = 1; # ファイルバッファリングをしない &form; # フォーム入力された値の分解 &init; # 各種データ変数の初期化 &read_domainlist; # 制限するドメインリストの読み込み &read_cfg; # ボード定義情報の読み込み #---------------------------------------------------------- # 動作モードの判定(管理者・ユーザーの各モード) #---------------------------------------------------------- if( $FORM{'mode'} eq 'admin' ) { if ( $FORM{'editpwd'} ne $user_pass ) { &error("パスワードが違います。"); } else { $mode = 'admin'; } } #---------------------------------------------------------- # スクリプトの動作を決定($FORM{'task'}で判定) #---------------------------------------------------------- if ( $FORM{'task'} eq 'removelist' ) { # 削除データのリスト表示 &removelist; } elsif ( $FORM{'task'} eq 'remove' ) { # データの削除ルーチンへ &remove_data; } elsif ( $FORM{'task'} eq 'editlist' ) { # 編集データのリスト表示 &editlist; } elsif ( $FORM{'task'} eq 'edit') { # 編集モード &edit_data; } elsif ( $FORM{'task'} eq 'regist') { # データの書き込み(通常・コメント) ®ist; } elsif ($FORM{'task'} eq 'regist2') { # 編集モードのデータ書き込み ®ist2; } elsif ($FORM{'task'} eq 'makelog') { # 過去ログ作成CGIの呼び出し if( $FORM{'pwd'} ne $user_pass ) { &error("パスワードが違います。"); } else { if( -e "makelog.cgi" ) { print "Location:$reload_url"."makelog.cgi?\n\n"; } else { &error("過去ログ作成スクリプト(makelog.cgi)が見つかりません。"); } } } elsif ($FORM{'task'} eq 'cust') { # カスタマイズCGIの呼び出し if( $FORM{'pwd'} ne $user_pass ) { &error("パスワードが違います。"); } else { if( -e "cust.cgi" ) { print "Location:$reload_url"."cust.cgi?\n\n"; } else { &error("カスタマイズスクリプト(cust.cgi)が見つかりません。"); } } } elsif ($FORM{'task'} eq 'domain') { # ドメイン管理CGIの呼び出し if( $FORM{'pwd'} ne $user_pass ) { &error("パスワードが違います。"); } else { if( -e "cust.cgi" ) { print "Location:$reload_url"."domain.cgi?\n\n"; } else { &error("ドメイン管理スクリプト(dmain.cgi)が見つかりません。"); } } } else { # 通常の画面表示 if( $FORM{'task'} eq "log_all" ) { $CFG_DATA{'page'} = "0"; } &html; exit; } #========================================================================================= # 処理はここまで(以下は、各サブルーチン) #========================================================================================= #---------------------------------------------------------------------- # 通常の画面表示ルーチン #---------------------------------------------------------------------- sub html { #------------------------------------------------------- # クッキーの取得(独自方式) #------------------------------------------------------- $cookies = $ENV{'HTTP_COOKIE'}; @pairs = split(/;/,$cookies); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $name =~ s/ //g; $DUMMY{$name} = $value; } @pairs = split(/,/,$DUMMY{$cookie_name}); foreach $pair (@pairs) { ($name, $value,$temp) = split(/:/, $pair); if( $name eq "url" ) { if( $value eq "" ) { $COOKIE{$name} = "http:\/\/"; } else { $COOKIE{$name} = "$value\:$temp"; } } else { $COOKIE{$name} = $value; } } if ( $COOKIE{'url'} eq "" ) { $COOKIE{'url'} = "http://"; } #------------------------------------------------------------ # 記録ファイルをオープンして、配列<@lines>に格納 #------------------------------------------------------------ &read_log; #-------------------------------------------------- # ページ処理でスタートするメッセージ番号 #-------------------------------------------------- if ( $CFG_DATA{'page'} ne "0" ) { $start = $FORM{'page'}*$CFG_DATA{'page'}; $end = $FORM{'page'}*$CFG_DATA{'page'}+$CFG_DATA{'page'}; } #-------------------------------------------------- # メッセージ数の取得 #-------------------------------------------------- $data_count = 0; $page_mode = 0; if ( $CFG_DATA{'page'} ne "0" ) { foreach $line (@lines) { if( $data_count < $start ) { # 開始番号までスキップ if ( substr($line, 0, 1) eq "#" ) { $data_count++; } } else { if ( substr($line, 0, 1) eq "@" ) { # コメントは無条件に格納 if( $data_count != $start ) { push( @line_data, $line ); } } elsif ( substr($line, 0, 1) eq "#" ) { # 本文の場合 if( $data_count < $end ) { push( @line_data, $line ); $data_count++; } else { $page_mode = 1; # 続きがあるよ! last; } } } } } else { foreach $line (@lines) { push( @line_data, $line ); } } #-------------------------------------------------- # HTML(画面)の出力 #-------------------------------------------------- print "Content-type: text/html\n\n"; print "\n\n$CFG_DATA{'title'}\n\n\n"; print "\n\n"; print "\n"; print "\n"; print "\n"; print "\n"; } else { print "$CFG_DATA{'title'}\n"; } print "\n"; print "\n
"; if( $CFG_DATA{'title_image'} ne "" ) { print "\"$CFG_DATA{'title'}\""; if( $CFG_DATA{'max'} ne '0' ) { print "全$CFG_DATA{'max'}件"; } else { print " "; } print "
\n
\n
\n"; if ( $CFG_DATA{'readme'} ne "" ) { print "
$CFG_DATA{'readme'}
\n"; } print "
\n"; if ( $CFG_DATA{'readme'} ne "" ) { print "

\n"; } print "書き込み\n"; if ( $CFG_DATA{'link1'} ne "" ) { print " $CFG_DATA{'linkname1'}\n"; } if ( $CFG_DATA{'link2'} ne "" ) { print " $CFG_DATA{'linkname2'}\n"; } if ( $CFG_DATA{'link3'} ne "" ) { print " $CFG_DATA{'linkname3'}\n"; } print "

\n"; if ($maintenance == 2 ) { print "
ただ今、掲示板のメンテナンス中です。しばらくお待ち下さい。
\n"; print "\n\n"; exit; } #---------------------------------------------------------- # 記事一覧処理 # 配列<@lines>から1件ずつデータを取り出して処理する #---------------------------------------------------------- $nextline = 1; foreach $line (@line_data) { ($count,$date,$editpwd,$name,$email,$url,$value,$subject,$rhost) = split(/\,/,$line); if ( substr($line, 0, 1) eq "@" ) { next; } #--------------------------------------- # nullコード(\0)を半角カンマに変換 #--------------------------------------- $name =~ s/\0/\,/g; $value =~ s/\0/\,/g; $subject =~ s/\0/\,/g; $email =~ s/\0/\,/g; $url =~ s/\0/\,/g; print "
$count $subject"; print " 名前:$name"; if ($email ne "") { print " Mail"; } if ($url ne "") { print " Home"; } print " ($date)

$value"; for (;;) { #--------------------------------------- # 次行がコメントかどうか #--------------------------------------- if ( substr($line_data[$nextline], 0, 1) ne "@" ) { last; } ($count,$date,$editpwd,$name,$email,$url,$value,$subject,$rhost) = split(/\,/,$line_data[$nextline]); #--------------------------------------- # nullコード(\0)を半角カンマに変換 #--------------------------------------- $name =~ s/\0/\,/g; $value =~ s/\0/\,/g; $subject =~ s/\0/\,/g; $email =~ s/\0/\,/g; $url =~ s/\0/\,/g; print "
$subject"; print " 名前:$name"; if ($email ne "") { print " Mail"; } if ($url ne "") { print " Home"; } print " ($date)

$value
"; $nextline++; } print"
\n\n"; $nextline++; } #---------------------------------------------------------------------- if ( $CFG_DATA{'page'} ne "0" ) { print "
"; if( $page_mode eq "0" ) { print "
これ以上のメッセージはありません。
\n"; } else { $next_page = $FORM{'page'} + 1; print "
"; print ""; print ""; print ""; print ""; print "
※続きがあります
"; } } print "
\n"; print "
\n"; if( $CFG_DATA{'user_email'} eq "" ) { print "主催者:"; if( $CFG_DATA{'user_name'} eq "" ) { print "名無しの権兵衛\n"; } else { print "$CFG_DATA{'user_name'}\n"; } } else { print "主催者:"; if( $CFG_DATA{'user_name'} eq "" ) { print "$CFG_DATA{'user_email'}\n"; } else { print "$CFG_DATA{'user_name'}\n"; } } print "
\n"; #---------------------------------------------------------------------- print "
\n\n"; print "記事の書き込み 最初へ
\n"; if( $CFG_DATA{'readme2'} ne "" ) { print "
$CFG_DATA{'readme2'}
\n"; } if ($maintenance == 1 ) { print "
ただ今、掲示板のメンテナンス中につき書き込みができません。しばらくお待ち下さい。
\n"; print "\n\n"; exit; } print "
\n"; print "\n"; print "\n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; } else { print "\n"; } print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; if ( $crypt_mode eq 'OK' ) { print " \n"; print " \n"; print " \n"; print " \n"; } else { print " \n"; print " \n"; print " \n"; print " \n"; } print "
名前
mail省略可
Home省略可
 投稿者/メールアドレスをブラウザに記憶させる
題名
内容"; if ( $CFG_DATA{'max_size'} ne "0" ) { print "
書き込み量の制限:最大$CFG_DATA{'max_size'}バイトまで
  "; print "  コメント先番号
 
管理用パスワード、4〜8文字(省略可:設定した場合は編集・削除ができます)
 
このサーバーではユーザーパスワードの利用はできません
\n"; print "
\n"; print "
\n"; #---------------------------------------------------------------------- print "
\n"; print "

パスワード\n"; print "\n"; print "
\n"; #-------------------------------------------------- # スクリプトの著作権表示(削除禁止) #-------------------------------------------------- print "
\n
\n"; print "SSBoard v$version
\n"; print "Based MiniBBS v5.0\n"; print "\n
\n
\n"; print "\n\n"; } #---------------------------------------------------------------------- # 通常のメッセージ投稿時のデータ書き込み #---------------------------------------------------------------------- sub regist { #-------------------------------------------------- # 各種のセキュリティチェック #-------------------------------------------------- &security_check; #-------------------------------------------------- # 入力されたデータのチェック #-------------------------------------------------- &data_check; #-------------------------------------------------- # パスワードの処理 #-------------------------------------------------- if ( $FORM{'editpwd'} ne "" ) { if ( $FORM{'editpwd'} eq $user_pass ) { # 管理者パスワードは保存しない $password = ""; $FORM{'editpwd'} = ""; } else { $pwd_len=length("$FORM{'editpwd'}"); if ( $pwd_len > 8 || $pwd_len < 4 ) { &error("パスワードは4〜8文字で設定してください。"); } else { $now = time; ($p1, $p2) = unpack("C2", "admin"); $wk = $now / (60*60*24*7) + $p1 + $p2 - 8; @saltset = ('a'..'z','A'..'Z','0'..'9','.','/'); $nsalt = $saltset[$wk % 64] . $saltset[$now % 64]; $password = crypt( $FORM{'editpwd'}, $nsalt); } } } #-------------------------------------------------- # クッキー処理 #-------------------------------------------------- &set_cookie; #-------------------------------------------------- # 記録ファイルをオープン、配列<@lines>に格納 #-------------------------------------------------- &read_log; #-------------------------------------------------- # 同一メッセージの排除処理 #-------------------------------------------------- for ( $j=0; ; $j++ ) { $temp = $lines[$j]; ($count,$dummy,$dummy,$dummy,$dummy,$dummy,$data,$dummy,$dummy) = split(/\,/,$temp); $mode = substr( $temp, 0, 1 ); if ( $mode ne "#" && $mode ne "@" ) { last; } if( $data eq $FORM{'value'} ) { &error("同じメッセージの投稿はできません。"); } } #------------------------------------------------------ # 通常のメッセージ投稿時のデータ書き込み #------------------------------------------------------ if ( $FORM{'res'} eq '#' ) { #-------------------------------------------------- # 最終のメッセージ番号取得 #-------------------------------------------------- if ( $lines[0] eq "" ) { # 空ログの時 $last = "0001"; } else { $last = substr( $lines[0], 1, 4 ); if ( $last eq "9999" ) { $last = "0000"; } $last++; } #-------------------------------------------------- # 記録件数処理 #-------------------------------------------------- $i = 0; foreach $line (@lines) { if( substr($line, 0,1) eq "#" ) { $i++; if ($i == $CFG_DATA{'max'}) { last; } } push(@new,$line); } $value = "#$last,$date_now\,$password\,$FORM{'name'}\,$FORM{'email'}\,$FORM{'url'}\,$FORM{'value'}\,$FORM{'subject'}\,$remote_host\,\n"; unshift(@new,$value); } #------------------------------------------------------ # コメントモードの時のデータ登録 #------------------------------------------------------ else { $max_line = 0; foreach $line (@lines) { $max_line++; } for ( $line_count=0; $line_count<$max_line; ) { ($count,$date,$editpwd,$name,$email,$url,$value,$subject,$rhost) = split(/\,/,$lines[$line_count]); #---------------------------------------- # コメント先の文書の時 #---------------------------------------- if ( $count eq $FORM{'res'} ) { push( @new, "$count,$date\,$editpwd\,$name\,$email\,$url\,$value\,$subject\,$rhost\,\n" ); $base_count = substr($count, 1, 4); $res_count = "01"; #------------------------------------ # コメントのデフォルトは10個 #------------------------------------ if( $CFG_DATA{'max_comment'} < 1 || $CFG_DATA{'max_comment'} > 99 ) { $CFG_DATA{'max_comment'} = 10; } $max_res = sprintf("%02d", $CFG_DATA{'max_comment'}+1 ); # コメント数の調整 for ( ;; ) { #---------------------------------------- # コメント数のチェック #---------------------------------------- if ( $res_count eq $max_res ) { &error("コメントは$CFG_DATA{'max_comment'}個までです。"); } #---------------------------------------- # コメント文の時 #---------------------------------------- if ( substr($lines[$line_count+1], 0, 1) eq "@" ) { ($count,$date,$editpwd,$name,$email,$url,$value,$subject,$rhost) = split(/\,/,$lines[$line_count+1]); push( @new,"@"."$base_count$res_count,$date\,$editpwd\,$name\,$email\,$url\,$value\,$subject\,$rhost\,\n"); $line_count++; $res_count++; } else { push( @new,"@"."$base_count$res_count,$date_now\,$password\,$FORM{'name'}\,$FORM{'email'}\,$FORM{'url'}\,$FORM{'value'}\,$FORM{'subject'}\,$remote_host\,\n"); $line_count++; last; } } } else { push( @new, "$count,$date\,$editpwd\,$name\,$email\,$url\,$value\,$subject\,$rhost\,\n" ); $line_count++; } } } #-------------------------------------------------- # 記録ファイルをオープンしてデータを書き出す #-------------------------------------------------- &write_log; #-------------------------------------------------- # 記録処理後、再読み込み(リロード)する #-------------------------------------------------- print "Location:$reload_url$cgi_name?\n\n"; exit; } #----------------------------------------------------------------- # 編集モードの時のデータ登録 #----------------------------------------------------------------- sub regist2 { #-------------------------------------------------- # 各種のセキュリティチェック #-------------------------------------------------- &security_check; #-------------------------------------------------- # 管理者パスワードのチェック #-------------------------------------------------- if ( $FORM{'mode'} eq "admin" ) { if ( $FORM{'editpwd'} ne $user_pass ) { &error("パスワードが違います。"); } } #-------------------------------------------------- # 入力されたデータのチェック #-------------------------------------------------- &data_check; #-------------------------------------------------- # 記録ファイルをオープン、配列<@lines>に格納 #-------------------------------------------------- &read_log; #-------------------------------------------------- # メッセージの入れ替え処理 #-------------------------------------------------- foreach $line (@lines) { ($count,$date,$editpwd,$name,$email,$url,$value,$subject,$rhost) = split(/\,/,$line); if ( $count eq $FORM{'count'} ) { if ( $FORM{'mode'} eq "user" ) { $temp = crypt( $FORM{'editpwd'}, substr($editpwd,0,2) ); if ( $temp ne $editpwd ) { &error("パスワードが違います。"); } } push( @new,"$count,$date\,$editpwd\,$FORM{'name'}\,$FORM{'email'}\,$FORM{'url'}\,$FORM{'value'}\,$FORM{'subject'}\,$rhost\,\n"); } else { push( @new, "$count,$date\,$editpwd\,$name\,$email\,$url\,$value\,$subject\,$rhost\,\n" ); } } #-------------------------------------------------- # 記録ファイルをオープンしてデータを書き出す #-------------------------------------------------- &write_log; #-------------------------------------------------- # 記録処理後、再読み込み(リロード)する #-------------------------------------------------- print "Location:$reload_url$cgi_name?\n\n"; exit; } #----------------------------------------------------------------- # フォーム投稿されたデータを解析し、配列にリストする #----------------------------------------------------------------- sub form { #-------------------------------------------------- # フォームから入力されたデータを$bufferに格納 #-------------------------------------------------- if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } #-------------------------------------------------- # 動作モードの判定(管理者・ユーザーの各モード) #-------------------------------------------------- $mode = "user"; @pairs = split(/&/,$buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); if ( $name eq "editpwd" ) { if( $value eq $user_pass ) { $mode = "admin"; } last; } } #-------------------------------------------------- # $bufferに格納されたFORM形式のデータを取り出す #-------------------------------------------------- foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; #-------------------------------------------------- # 処理の都合上、改行コード等を文字列から排除する # 改行コードを
に変換する(97.01.29) #-------------------------------------------------- $value =~ s/\r\n/
/g; $value =~ s/\n/
/g; #-------------------------------------------------- # 半角カンマをnull(\0)に変換する #-------------------------------------------------- $value =~ s/\,/\0/g; #-------------------------------------------------- # 書き込まれたくないタグが含まれる内容を消去する #-------------------------------------------------- if ( $mode ne "admin" ) { $value =~ s/に格納 #-------------------------------------------------- &read_log; #-------------------------------------------------- # 記事の一覧処理 #-------------------------------------------------- print "Content-type: text/html\n\n"; print "\n\n削除モード\n\n"; print "\n\n"; print "\n"; print "削除モード\n"; print "
\n"; print "\n"; print "
"; foreach $line (@lines) { ($count,$date,$editpwd,$name,$email,$url,$value,$subject,$rhost) = split(/\,/,$line); if ( $mode2 eq "user" ) { if ( $editpwd ne "" ) { $temp = crypt( $FORM{'pwd'}, substr($editpwd,0,2) ); if ( $temp eq $editpwd ) { print ""; print "削除 "; print "$count $subject "; print "投稿者:$name"; print " ($date)

\n"; print "$value\n


\n"; } } } else { print ""; print "削除 "; print "$count $subject "; print "投稿者:$name"; print " ($date)

\n"; print "$value\n


\n"; } } print "\n"; print "

\n"; print "先頭へ
"; print "\n"; print "\n"; print "

\n"; print "\n"; exit; } #----------------------------------------------------------------- # リストアップされたメッセージのデータ削除 #----------------------------------------------------------------- sub remove_data { #-------------------------------------------------- # 記録ファイルをオープン、配列<@lines>に格納 #-------------------------------------------------- &read_log; foreach $line (@lines) { ($count,$date,$editpwd,$name,$email,$url,$value,$subject,$rhost) = split(/\,/,$line); $del = 0; foreach $target (@RM) { if ($target eq "") { last; } if ($target eq $count) { $del = 1; } } if ($del == 0) { push(@new,$line); } } #-------------------------------------------------- # 記録ファイルをオープンしてデータを書き出す #-------------------------------------------------- &write_log; #-------------------------------------------------- # 記録処理後、再読み込み(リロード)する #-------------------------------------------------- print "Location:$reload_url$cgi_name?\n\n"; exit; } #----------------------------------------------------------------- # 編集したいメッセージのリスト表示と選択画面 #----------------------------------------------------------------- sub editlist { if ( $FORM{'pwd'} eq "" ) { &error("パスワードが入力されていません。"); } elsif ( $FORM{'pwd'} eq $user_pass ) { $mode2 = "admin"; } else { $mode2 = "user"; } #-------------------------------------------------- # 記録ファイルをオープン、配列<@lines>に格納 #-------------------------------------------------- &read_log; print "Content-type: text/html\n\n"; print "\n\n編集モード\n\n"; print "\n\n"; print "\n"; print "編集モード\n"; print "

\n"; print "\n"; print "\n"; print "\n"; print "
"; foreach $line (@lines) { ($count,$date,$editpwd,$name,$email,$url,$value,$subject,$rhost) = split(/\,/,$line); if ( $mode2 eq "user" ) { if ( $editpwd ne "" ) { $temp = crypt( $FORM{'pwd'}, substr($editpwd,0,2) ); if ( $temp eq $editpwd ) { print ""; print "編集 "; print "$count $subject "; print "投稿者:$name"; print " ($date)

\n"; print "$value\n


\n"; } } } else { print ""; print "編集 "; print "$count $subject "; print "投稿者:$name"; print " ($date)

\n"; print "$value\n


\n"; } } print "\n"; print "

\n"; print "先頭へ
"; print "\n"; print "\n"; print "

\n"; print "\n"; exit; } #----------------------------------------------------------------- # 編集モード #----------------------------------------------------------------- sub edit_data { if( $FORM{'mode'} eq "admin" ) { if ( $FORM{'editpwd'} ne $user_pass ) { &error("パスワードが違います。"); } } if ( $FORM{'target'} eq "" ) { &error("編集するメッセージが選択されていません。"); } #----------------------------------------------- # 記録ファイルをオープン、配列<@lines>に格納 #----------------------------------------------- &read_log; foreach $line (@lines) { ($count,$date,$editpwd,$name,$email,$url,$value,$subject,$rhost) = split(/\,/,$line); if ( $count eq $FORM{'target'} ) { if( $FORM{'mode'} eq "user" ) { $temp = crypt( $FORM{'editpwd'}, substr($editpwd,0,2) ); if ( $temp ne $editpwd ) { &error("パスワードが違います。"); } } #--------------------------------------- # 表示用にタグを変換 #--------------------------------------- $value =~ s/
/\n/ig; $value =~ s//>/g; #--------------------------------------- # nullコード(\0)を半角カンマに変換 #--------------------------------------- $name =~ s/\0/\,/g; $value =~ s/\0/\,/g; $subject =~ s/\0/\,/g; $email =~ s/\0/\,/g; $url =~ s/\0/\,/g; last; } } print "Content-type: text/html\n\n"; print "\n\n編集モード\n\n\n"; print "\n\n"; print "編集モード

\n


\n\n"; print "
\n"; print "\n"; print "\n"; print "\n"; print "\n\n"; print "\n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print "
名前
mail省略可
Home省略可
題名\n"; print "
内容
 
\n
\n
\n\n\n"; exit; } #--------------------------------------------------------------------- # 各種データ変数の初期化 #--------------------------------------------------------------------- sub init { $cgi_name = "$script".".cgi"; # CGIファイル名 $log_file = "$path"."$log_name"; # ログファイル名 #------------------------------------------------------------- # 記入者のリモートホスト名を取得 # ホスト名が取得できない場合、アドレスを取得する #------------------------------------------------------------- $remote_host = $ENV{'REMOTE_HOST'}; if ( $remote_host eq "" ) { $remote_host = $ENV{'REMOTE_ADDR'}; } #------------------------------------------------------------- # IPアドレスのみの場合 nslookで検索 #------------------------------------------------------------- if( $remote_host=~/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/ ) { $remote_host = &nslook($remote_host); } #------------------------------------------------------------- # 制限中のドメインのチェック #------------------------------------------------------------- if( $domain_file ne "" ) { foreach $domain (@domainlist2) { &domain_error if($remote_host=~/$domain/i); } } #------------------------------------------------------------- # 海外サーバ等で時差が生じる場合は修正 # 海外時間に+9時間する場合 = localtime(time + 9*60*60); # 海外時間に−9時間する場合 = localtime(time - 9*60*60); #------------------------------------------------------------- ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); #------------------------------------------------------------- # クッキーの消化設定 # 最終書き込みから 30日後 30*24*60*60 # 1日後 24*60*60 # 10時間後 10*60*60 #------------------------------------------------------------- $ENV{'TZ'} = "GMT"; # 時刻取得を国際標準時とする ($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg,$ydayg,$isdstg) = localtime(time + 30*24*60*60); #------------------------------------------------------------- # 時分秒を2桁に統一する処理 #------------------------------------------------------------- if ($sec < 10) { $sec = "0$sec"; } if ($min < 10) { $min = "0$min"; } if ($hour < 10) { $hour = "0$hour"; } #------------------------------------------------------------- # 上記の$monには0から11までの数字が入るので修正処理 #------------------------------------------------------------- $month = ($mon + 1); #------------------------------------------------------------- # 曜日変換処理 # $wdayには0から6までの数字が入り曜日に対応している #------------------------------------------------------------- $y0="日"; $y1="月"; $y2="火"; $y3="水"; $y4="木"; $y5="金"; $y6="土"; $youbi = ($y0,$y1,$y2,$y3,$y4,$y5,$y6) [$wday]; #------------------------------------------------------------- # 時刻フォーマット #------------------------------------------------------------- $date_now = "$month月$mday日($youbi)$hour時$min分$sec秒"; #------------------------------------------------------------- # crypt()が使用できるかの判定 #------------------------------------------------------------- $now = time; ($p1, $p2) = unpack("C2", "admin"); $wk = $now / (60*60*24*7) + $p1 + $p2 - 8; @saltset = ('a'..'z','A'..'Z','0'..'9','.','/'); $nsalt = $saltset[$wk % 64] . $saltset[$now % 64]; $pass1 = crypt( $user_pass, $nsalt); $pass2 = crypt( $user_pass, substr($pass1, 0, 2) ); if ( $pass1 eq $pass2 ) { $crypt_mode = 'OK'; } else { $crypt_mode = 'NG'; } } #----------------------------------------------------------------- # ボード定義情報の初期化と、ファイルからの読み込み #----------------------------------------------------------------- sub read_cfg { $CFG_DATA{'max'} = $max; $CFG_DATA{'max_comment'} = $max_comment; $CFG_DATA{'page'} = $page; $CFG_DATA{'user_name'} = $user_name; $CFG_DATA{'user_email'} = $user_email; $CFG_DATA{'security'} = $security; $CFG_DATA{'title'} = $title; $CFG_DATA{'title_image'} = $title_image; $CFG_DATA{'bg_col'} = $bg_col; $CFG_DATA{'bg_image'} = $bg_image; $CFG_DATA{'title_col'} = $title_col; $CFG_DATA{'text_col'} = $text_col; $CFG_DATA{'link_col'} = $link_col; $CFG_DATA{'alink_col'} = $alink_col; $CFG_DATA{'vlink_col'} = $vlink_col; $CFG_DATA{'subject_col'} = $subject_col; $CFG_DATA{'name_col'} = $name_col; $CFG_DATA{'linkname1'} = $linkname1; $CFG_DATA{'link1'} = $link1; $CFG_DATA{'linkname2'} = $linkname2; $CFG_DATA{'link2'} = $link2; $CFG_DATA{'linkname3'} = $linkname3; $CFG_DATA{'link3'} = $link3; $CFG_DATA{'readme'} = $readme; $CFG_DATA{'readme2'} = $readme2; $CFG_DATA{'max_size'} = $max_size; $CFG_DATA{'max_subject'} = $max_subject; $CFG_DATA{'max_name'} = $max_name; $CFG_DATA{'max_email'} = $max_email; $CFG_DATA{'max_url'} = $max_url; #--------------------------------------- # ファイルからの読み込み #--------------------------------------- $cfg_file = "$path"."$cfg_name"; if ( open(DB,"$cfg_file")) { if( $lockmode == 1 ) { eval { flock( DB, 1 );}; # ファイルをロック if ( $@ ne "" ) { &error("flock()がサポートされていません。"); } @cfg = ; flock( DB, 8 ); # ロック解除 } else { @cfg = ; } close(DB); } foreach $line (@cfg) { ($name,$value) = split(/\,/,$line); $CFG_DATA{$name} = $value; } } #----------------------------------------------------------------- # ログファイルの読み込み(@linesに格納) #----------------------------------------------------------------- sub read_log { if (!open(DB,"$log_file")) { &error("ファイルの入出力にエラーが発生しました。"); } if( $lockmode == 1 ) { eval { flock( DB, 1 );}; # ファイルをロック if ( $@ ne "" ) { &error("flock()がサポートされていません。"); } @lines = ; flock( DB, 8 ); # ロック解除 } else { @lines = ; } close(DB); } #----------------------------------------------------------------- # ログファイルの書き出し #----------------------------------------------------------------- sub write_log { if (!open(DB,">$log_file")) { &error("ファイルの入出力にエラーが発生しました。"); } if( $lockmode == 1 ) { eval { flock( DB, 2 );}; # ファイルをロック if ( $@ ne "" ) { &error("flock()がサポートされていません。"); } print DB @new; flock( DB, 8 ); # ロック解除 } else { print DB @new; } close(DB); } #----------------------------------------------------------------- # ドメインリストの読み込み #----------------------------------------------------------------- sub read_domainlist { if( $domain_file eq "" ) { return; } $filename = "$path"."$domain_file"; if (!open(DB,"$filename")) { &error("ドメインファイルが見つかりません。"); } if( $lockmode == 1 ) { eval { flock( DB, 1 );}; # ファイルをロック if ( $@ ne "" ) { &error("flock()がサポートされていません。"); } } @data = ; if( $lockmode == 1 ) { flock( DB, 8 ); # ロック解除 } close(DB); foreach $temp (@data) { ($domain,$level) = split(/\,/,$temp); if ( $level eq "0" ) { push( @domainlist1, "$domain" ); } else { push( @domainlist2, "$domain" ); } } } #----------------------------------------------------------------- # エラーメッセージの出力 #----------------------------------------------------------------- sub error { $error_msg = $_[0]; print "Content-type: text/html\n\n"; print "SSBoard v$version\n"; print "\n"; print "

おしらせ

\n"; print "$error_msg\n"; print "

\n"; exit; } #----------------------------------------------------------------- # ドメイン・エラーメッセージの出力 #----------------------------------------------------------------- sub domain_error { print "Content-type: text/html\n\n"; print "SSBoard v$version\n"; print "\n"; print "

エラーのおしらせ

\n"; print "現在アクセスしているホスト情報(ドメイン)では、掲示板をご利用になれません。
\n"; print "アクセスしているホスト情報は以下のように判定されています。
\n"; print "もし判定がおかしい場合、管理者まで連絡してください。

\n"; print "ホスト情報:$remote_host
\n"; print "\n"; exit; } #----------------------------------------------------------------- # プロキシ・エラーメッセージの出力 #----------------------------------------------------------------- sub proxy_error { print "Content-type: text/html\n\n"; print "MultiBBS v$version\n"; print "\n"; print "

エラーのおしらせ

\n"; print "プロキシ経由での書き込みはできません。
\n"; print "プロキシの判定がおかしい場合、以下のホスト情報を添えて"; print "管理者まで連絡してください。

\n"; print "
REMOTE_HOST = $remote_host
\n"; print "HTTP_PROXY_CONNECTION = $ENV{'HTTP_PROXY_CONNECTION'}
\n"; print "HTTP_CACHE_INFO = $ENV{'HTTP_CACHE_INFO'}
\n"; print "HTTP_VIA = $ENV{'HTTP_VIA'}
\n"; print "HTTP_CLIENT_IP = $ENV{'HTTP_CLIENT_IP'}
\n"; print "HTTP_X_FORWARDED_FOR = $ENV{'HTTP_X_FORWARDED_FOR'}
\n"; print "HTTP_FORWARDED = $ENV{'HTTP_FORWARDED'}
\n"; print "HTTP_USER_AGENT = $ENV{'HTTP_USER_AGENT'}
\n"; print "\n"; exit; } #----------------------------------------------------------------- # IPアドレスからホスト名を取得する #----------------------------------------------------------------- sub nslook { local($x)=@_; local($ip,$addr); if ($x =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ ){ $ip="$1.$2.$3.$4"; $addr = (gethostbyaddr(pack('C4',$1,$2,$3,$4),2))[0]; if ($addr ne "") { return $addr; } else { return $ip; } } return ""; } #----------------------------------------------------------------- # 各種のセキュリティ対策 #----------------------------------------------------------------- sub security_check { #-------------------------------------------------- # 制限中のドメインのチェック #-------------------------------------------------- foreach $domain (@domainlist1) { &domain_error if($remote_host=~/$domain/i); } foreach $domain (@domainlist2) { &domain_error if($remote_host=~/$domain/i); } #-------------------------------------------------- # 外部からの書き込みチェック(POSTのみ許可) #-------------------------------------------------- if ($ENV{'REQUEST_METHOD'} ne "POST") { &error("method=getでの投稿は受け付けられません。"); } #-------------------------------------------------- # 外部フォームからの書き込みの禁止チェック #-------------------------------------------------- if ($script_url ne "") { $ref = $ENV{'HTTP_REFERER'}; $ref_url = $script_url; $ref_url =~ s/\~/.*/g; if (!($ref =~ /$ref_url/i)) { &error("「$script_url」以外からの投稿は受け付けられません。"); } } #------------------------------------------------------------ # 各種のセキュリティ処理 #------------------------------------------------------------ if ( $CFG_DATA{'security'} eq "1" || $CFG_DATA{'security'} eq "3" ) { $temp = reverse $remote_host; #------------------------------------------------------------ # JPドメインの判定 #------------------------------------------------------------ if ( "pj." ne substr( $temp, 0, 3 ) ) { &domain_error; } } if ( $CFG_DATA{'security'} eq "2" || $CFG_DATA{'security'} eq "3" ) { #------------------------------------------------------------ # プロキシの排除 #------------------------------------------------------------ $proxycheck = 0; $proxycheck = 1 if($ENV{'HTTP_PROXY_CONNECTION'}); $proxycheck = 1 if($ENV{'HTTP_CACHE_INFO'}); $proxycheck = 1 if($ENV{'HTTP_VIA'}); $proxycheck = 1 if($ENV{'HTTP_CLIENT_IP'}); $proxycheck = 1 if($ENV{'HTTP_X_FORWARDED_FOR'}); $proxycheck = 1 if($ENV{'HTTP_FORWARDED'}); $proxycheck = 1 if($ENV{'HTTP_USER_AGENT'}=~/via/i); if( $proxycheck == 1 ) { $proxycheck2 = 1; foreach $temp2 (@proxylist) { $proxycheck2 = 0 if($remote_host=~/$temp2/i); } if( $proxycheck2 == 1 ) { &proxy_error; } } } } #----------------------------------------------------------------- # クッキー処理ルーチン #----------------------------------------------------------------- sub set_cookie { if ($FORM{'cookie'} eq "on") { if ($yearg < 10) { $yearg = "0$yearg"; } if ($secg < 10) { $secg = "0$secg"; } if ($ming < 10) { $ming = "0$ming"; } if ($hourg < 10) { $hourg = "0$hourg"; } if ($mdayg < 10) { $mdayg = "0$mdayg"; } $y0="Sunday"; $y1="Monday"; $y2="Tuesday"; $y3="Wednesday"; $y4="Thursday"; $y5="Friday"; $y6="Saturday"; $youbi = ($y0,$y1,$y2,$y3,$y4,$y5,$y6) [$wdayg]; $m0="Jan"; $m1="Feb"; $m2="Mar"; $m3="Apr"; $m4="May"; $m5="Jun"; $m6="Jul"; $m7="Aug"; $m8="Sep"; $m9="Oct"; $m10="Nov"; $m11="Dec"; $month = ($m0,$m1,$m2,$m3,$m4,$m5,$m6,$m7,$m8,$m9,$m10,$m11) [$mong]; $date_gmt = "$youbi, $mdayg\-$month\-$yearg $hourg:$ming:$secg GMT"; #------------------------------------------------------------ # 独自方式のクッキーフォーマット # # name:,email:,url: という形式にまとめて、 # これを一つのクッキーとしてcookieという名前でブラウザに送 # 信しています。 # # 独自フォーマット cookie=name:,email:,url:,pass: #------------------------------------------------------------ $cook="name\:$FORM{'name'}\,email\:$FORM{'email'}\,url\:$FORM{'url'}\,pass\:$FORM{'editpwd'}"; print "Set-Cookie: $cookie_name=$cook; expires=$date_gmt\n"; } else { #------------------------------------------------------------ # 保存しない場合は、空のデータを保存、前のデータを消去 #------------------------------------------------------------ print "Set-Cookie: $cookie_name=; expires=$date_gmt\n"; } } #-------------------------------------------------- # 入力されたデータ内容のチェック #-------------------------------------------------- sub data_check { if ($FORM{'name'} eq "") { &error("投稿者名が記入されていません。"); } if ($FORM{'value'} eq "") { &error("内容が書かれていません。または記録禁止のタグが書かれています。"); } if ($FORM{'email'} ne "") { if (!($FORM{'email'} =~ /(.*)\@(.*)\.(.*)/)) { &error("メールアドレスが正しく入力されていません。"); } } if ($FORM{'url'} eq "http://") { $FORM{'url'}=""; } if ($FORM{'subject'} eq "") { &error("題名が書かれていません。"); } #-------------------------------------------------- # 書き込み内容サイズの制限 #-------------------------------------------------- &size_check; } #------------------------------------------------------------ # 書き込み内容サイズの制限 #------------------------------------------------------------ sub size_check { if ( $CFG_DATA{'max_size'} ne '0' ) { $FORM{'value'} = substr( $FORM{'value'}, 0, $max_size ); } if ( $CFG_DATA{'max_subject'} ne '0' ) { $FORM{'subject'} = substr( $FORM{'subject'}, 0, $max_subject ); } if ( $CFG_DATA{'max_name'} ne '0' ) { $FORM{'name'} = substr( $FORM{'name'}, 0, $max_name ); } if ( $CFG_DATA{'max_email'} ne '0' ) { $FORM{'email'} = substr( $FORM{'email'}, 0, $max_email ); } if ( $CFG_DATA{'max_url'} ne '0' ) { $FORM{'url'} = substr( $FORM{'url'}, 0, $max_url ); } }