#! /usr/local/bin/perl # ↑この上のPerlのパスを書き換えるのはお約束ですね #========================================================================================== # # マルチボード掲示板システム 『MultiBBS』ver 1.3 : 掲示板スクリプト本体 # # Copyright Shinobu Suzuki 1998. All rights reserved. #----------------------------------------------------------------------------------------- # HomePage : http://www.aikis.or.jp/~s-suzuki/cgilabo/ # E-mail : s-suzuki@aikis.or.jp # Version : 1.32 # Update : 1999/02/27 #----------------------------------------------------------------------------------------- # ■通常の掲示板機能に加え、メッセージの削除や編集、ボードのカスタマイズなどができます # ■crypt()を利用したパスワード設定で、投稿者もメッセージの削除や編集ができます # ■特定のメッセージにコメントを追加できます # ■メッセージや名前など、各項目のサイズを制限することができます # ■ログファイルのサイズを制限することができます # ■簡単なドメイン別のアクセス制限(プロキシ制限等)ができます # ■タグを全面禁止にしたり、一部を禁止したり、細かく設定できます # ■「WEB裏技」さんの MiniBBS v5.0をベースに開発していますが、主要部分ではもはや跡形がわ # からないくらいに変更を加えています。データの互換性なども当然ありませんし、使い方も大 # 幅に拡張されています。開発のきっかけとなった MiniBBSに敬意をあらわし、著作権表示を残 # します # **** # ■このスクリプトは config.cgi を参照しています #========================================================================================== # 初期設定 #----------------------------------------------------------------------------------------- # CERN HTTPDなどのサーバーの場合で、ファイル関係のエラーが # 出る場合、設置するディレクトリのフルパスを指定してみて下 # さい。なお、最後は / で終わること。 # 例) $path = "/home/users/s-suzuki/public_html/bbs/"; #---------------------------------------------------------- $path = ""; #---------------------------------------------------------- # 共通設定ファイルの指定 #---------------------------------------------------------- require "$path"."config.cgi"; #---------------------------------------------------------- # 日本語コード変換ライブラリの指定 #---------------------------------------------------------- require "$path"."jcode.pl"; #---------------------------------------------------------- # システム固定のリンクを使用したいときに指定する。これを利 # 用すると、ユーザーの設定に関係なくリンクタグが出ます。 #---------------------------------------------------------- $fixedlink1 = '掲示板一覧'; # システム固定のリンク1 $fixedurl1 = 'list.cgi'; # そのurl1 $fixedlink2 = ''; # システム固定のリンク2 $fixedurl2 = ''; # そのurl2 $fixedlink3 = ''; # システム固定のリンク3 $fixedurl3 = ''; # そのurl3 #---------------------------------------------------------- # 外部からの(イタズラ)書き込みを禁止する場合、以下に、ス # クリプトのURLを記入する。(サーバーやブラウザによっては # うまくいかないこともあります) # 例:$script_url = 'http://www.aikis.or.jp/~s-suzuki/multibbs/multibbs.cgi'; #---------------------------------------------------------- $script_url = ''; #---------------------------------------------------------- # 書き込みの後のリロードに失敗する場合(File Not Foundので # る場合)、CGIスクリプトを設置するディレクトリ名をURLで指 # 定すると成功する場合があるそうです。 # ※この機能については未確認です # ※biglobeでは成功するそうです # ※v1.24より記述方法を変更しています # ※最後は / で終わること。 # 例:$rerload_url = 'http://www.aikis.or.jp/~s-suzuki/multibbs/'; #---------------------------------------------------------- $reload_url = ''; #===================================================================== # これより、処理の開始 #===================================================================== $| = 1; # ファイルバッファリングをしない &form; # フォーム入力された値の分解 &read_master_key; # 管理用マスターキー読み込み &read_domainlist; # 制限するドメインリストの読み込み &init; # 各種データ変数の初期化 &read_cfg; # ボード定義ファイルの読み込み #-------------------------------------------------- # 主催者のパスワードが設定されていなければ設定する #-------------------------------------------------- if( $CFG_DATA{'user_pass'} eq "" ) { &error("主催者のパスワードが設定されていません。"); } #-------------------------------------------------- # スクリプトの動作を決定($FORM{'task'}で判定) #-------------------------------------------------- if ( $FORM{'task'} eq 'regist') { # データ書き込み(通常・コメント) ®ist; } elsif ( $FORM{'task'} eq 'remove' ) { # 削除データのリスト表示 if( -e "remove.cgi" ) { print "Location:$reload_url"."remove.cgi?bordname=$bordname\n\n"; } else { &error("削除スクリプト(remove.cgi)が見つかりません。"); } } elsif ( $FORM{'task'} eq 'edit' ) { # 編集データのリスト表示 if( -e "edit.cgi" ) { print "Location:$reload_url"."edit.cgi?bordname=$bordname\n\n"; } else { &error("編集スクリプト(edit.cgi)が見つかりません。"); } } elsif ( $FORM{'task'} eq 'cust') { # ボードのカスタマイズ if( -e "admin.cgi" ) { print "Location:$reload_url"."admin.cgi?pwd=$FORM{'pwd'}&task=edit_bord&mode=backbbs&bordname=$bordname\n\n"; } else { &error("管理スクリプト(admin.cgi)が見つかりません。"); } } elsif ($FORM{'task'} eq 'pass') { # ユーザーパスワードの変更 if( -e "admin.cgi" ) { print "Location:$reload_url"."admin.cgi?task=change_user_pass&bordname=$bordname\n\n"; } else { &error("管理スクリプト(admin.cgi)が見つかりません。"); } } else { # 通常の画面表示 if( $FORM{'task'} eq "log_all" ) { $CFG_DATA{'page'} = "0"; } &main; exit; } #===================================================================== # 処理はここまで(以下は、サブルーチン) #===================================================================== #---------------------------------------------------------------------- # 通常の画面表示ルーチン #---------------------------------------------------------------------- sub main { #--------------------------- # クッキーの取得(独自方式) #--------------------------- $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"; if ( $announce ne "" ) { print "

\n"; print "
$announce
\n"; } print "


\n"; } else { if ( $announce ne "" ) { print "
$announce
\n"; print "


\n"; } } 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"; } if ( $fixedlink1 ne "" ) { print " $fixedlink1\n"; } if ( $fixedlink2 ne "" ) { print " $fixedlink2\n"; } if ( $fixedlink3 ne "" ) { print " $fixedlink3\n"; } print "

\n"; if ($maintenance == 2 ) { print "
ただ今、掲示板のメンテナンス中です。しばらくお待ち下さい。
\n"; #------------------------- # スクリプトの著作権表示 #------------------------- print "
\n
"; print "MultiBBS v$version
\n"; print "Based MiniBBS v5.0
\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)

"; print "
$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 "
\n"; print "

$subject"; print " 名前:$name"; if ($email ne "") { print " Mail"; } if ($url ne "") { print " Home"; } print " ($date)

$value
\n\n"; $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 ""; print "
※続きがあります
"; } } print "
\n"; print "
\n"; print "主催者:"; if ($CFG_DATA{'user_email'} ne "" ) { print ""; } if( $CFG_DATA{'user_name'} eq "" ) { if ($CFG_DATA{'user_email'} ne "" ) { print "$CFG_DATA{'user_email'}"; } else { print "名無しの権兵衛"; } } else { print "$CFG_DATA{'user_name'}"; } if ($CFG_DATA{'user_email'} ne "" ) { print "\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
"; print "MultiBBS v$version
\n"; print "Based MiniBBS v5.0
\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"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print "
名前
mail省略可
Home省略可
 投稿者/メールアドレスをブラウザに記憶させる
題名
内容"; if ( $max_size ne "0" ) { print "
※書き込み量の制限:最大$max_sizeバイトまで"; } if ( $tag_mode == 0 ) { print "
※タグは全面禁止になっています"; } else { print "
※タグは一部のみ許可されています"; } print "
  "; print "  コメント先番号(4桁)
 
管理用パスワード、4〜8文字(省略可:設定した場合は編集・削除ができます)
\n"; print "
\n"; #------------------------------------------------------- print "
\n"; print "
\n"; print ""; print "
"; #------------------------- # スクリプトの著作権表示 #------------------------- print "
\n
"; print "MultiBBS v$version
\n"; print "Based MiniBBS v5.0
\n"; print "\n\n"; } #---------------------------------------------------------------------- # 通常のメッセージ投稿時のデータ書き込み #---------------------------------------------------------------------- sub regist { if ($maintenance ne "0" ) { &error("ただいまメンテナンス中です。しばらくお待ち下さい。"); } #--------------------- # 各種のチェック #--------------------- &security_check; &data_check; #--------------------- # パスワードの暗号化 #--------------------- if ( $FORM{'editpwd'} ne "" ) { $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; &read_log; #---------------------------- # 同一メッセージの排除処理 #---------------------------- for ( $j=0; ; $j++ ) { $temp1 = $lines[$j]; ($count,$dummy,$dummy,$dummy,$dummy,$dummy,$data,$dummy,$dummy) = split(/\,/,$temp); $temp2 = substr( $temp1, 0, 1 ); if ( $temp2 ne "#" && $temp2 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++; } #--------------------------------- # 投稿されたメッセージのデータ化 #--------------------------------- $value = "#$last,$date_now\,$password\,$FORM{'name'}\,$FORM{'email'}\,$FORM{'url'}\,$FORM{'value'}\,$FORM{'subject'}\,$remote_host\,\n"; #------------------------- # データサイズを取得する #------------------------- $data_size = length($value); #--------------- # 記録件数処理 #--------------- $i = 0; foreach $line (@lines) { if( substr($line, 0,1) eq "#" ) { $i++; if ($i == $CFG_DATA{'max'}) { last; } #------------------------------ # 記録ファイルをサイズチェック #------------------------------ if ($file_size ne "0") { if ( $data_size > $file_size ) { last; } } } push(@new,$line); $len = length($line); $data_size += $len; } unshift(@new,$value); } #--------------------------------- # コメントモードの時のデータ登録 #--------------------------------- else { $max_line = 0; $data_size = 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'} ) { $value = "$count,$date\,$editpwd\,$name\,$email\,$url\,$value\,$subject\,$rhost\,\n"; push( @new, $value ); $len = length($value); $data_size += $len; $base_count = substr($count, 1, 4); $res_count = "01"; $max_res = sprintf("%02d", $max_comment+1 ); # コメント数の調整(2桁化) for ( ;; ) { #------------------------ # コメント数のチェック #------------------------ if ( $res_count eq $max_res ) { &error("コメントは$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]); $value = "@"."$base_count$res_count,$date\,$editpwd\,$name\,$email\,$url\,$value\,$subject\,$rhost\,\n"; push( @new,$value ); $len = length($value); $data_size += $len; $line_count++; $res_count++; } else { $value = "@"."$base_count$res_count,$date_now\,$password\,$FORM{'name'}\,$FORM{'email'}\,$FORM{'url'}\,$FORM{'value'}\,$FORM{'subject'}\,$remote_host\,\n"; push( @new, $value ); $len = length($value); $data_size += $len; $line_count++; last; } } #---------------------------------------- # コメントを保存したら一度ループを抜ける #---------------------------------------- last; } else { $value = "$count,$date\,$editpwd\,$name\,$email\,$url\,$value\,$subject\,$rhost\,\n"; push( @new, $value ); $len = length($value); $data_size += $len; $line_count++; } } #-------------------------------------------- # コメントのついた番号以下のメッセージの処理 #-------------------------------------------- for ( ; $line_count<$max_line; ) { ($count,$date,$editpwd,$name,$email,$url,$value,$subject,$rhost) = split(/\,/,$lines[$line_count]); $value = "$count,$date\,$editpwd\,$name\,$email\,$url\,$value\,$subject\,$rhost\,\n"; #------------------------------ # 記録ファイルをサイズチェック #------------------------------ if( substr($count, 0,1) eq "#" ) { if ( $file_size ne "0") { if ( $data_size > $file_size ) { last; } } } push( @new, $value ); $len = length($value); $data_size += $len; $line_count++; } } #------------------ # データを書き出す #------------------ &write_log; #---------------------------- # 記録処理後、リロードする #---------------------------- print "Location:$reload_url$script?bordname=$FORM{'bordname'}\n\n"; exit; } #--------------------------------------------------------------------- # 各種データ変数の初期化 #--------------------------------------------------------------------- sub init { if( $FORM{'bordname'} eq "" ) { &error("ボード名が指定されていません。"); } else { $bordname = "$FORM{'bordname'}"; } if( $path eq "" ) { $log_file = "./log/"."$FORM{'bordname'}".".log"; } else { $log_file = "$path"."log/"."$FORM{'bordname'}".".log"; } $cookie_name = "suz-"."$bordname"; # クッキー名 #------------------------------------ # 記入者のリモートホスト名を取得 # 取得できない場合、アドレスを取得 #------------------------------------ $remote_host = $ENV{'REMOTE_HOST'}; if ( $remote_host eq "" ) { $remote_host = $ENV{'REMOTE_ADDR'}; } #----------------------------- # 制限中のドメインのチェック #----------------------------- if( $domainlist ne "" ) { #--------------------------------------- # IPアドレスのみの場合 nslookupで検索 #--------------------------------------- if( $remote_host=~/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/ ) { $remote_host = &nslook($remote_host); } 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); #------------------------ # 時分秒を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); #---------------- # 曜日の変換処理 #---------------- $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 ne $pass2 ) { &error("crypt()関数が利用できないので、暗号化処理ができません。"); } } #----------------------------------------------------------------- # ドメイン・エラーメッセージの出力 #----------------------------------------------------------------- sub domain_error { &html_header("MultiBBS:エラーのおしらせ"); print "
現在アクセスしているホスト情報(ドメイン)ではご利用になれません。
\n"; print "アクセスしているホスト情報は以下のように判定されています。
"; print "もし判定がおかしい場合、管理者まで連絡してください。

\n"; print "ホスト情報:$remote_host
\n"; print "\n"; exit; } #----------------------------------------------------------------- # プロキシ・エラーメッセージの出力 #----------------------------------------------------------------- sub proxy_error { &html_header("MultiBBS:エラーのおしらせ"); 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 { #--------------------------------------- # IPアドレスのみの場合 nslookupで検索 #--------------------------------------- if( $remote_host=~/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/ ) { $remote_host = &nslook($remote_host); } #----------------------------- # 制限中のドメインのチェック #----------------------------- 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" ) { #------------------- # JPドメインの判定 #------------------- $temp = reverse $remote_host; 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; } } } } #----------------------------------------------------------------- # クッキー処理ルーチン(Web裏技さんのルーチンを改変) #----------------------------------------------------------------- sub set_cookie { if ($FORM{'cookie'} eq "on") { #------------------------------------------- # クッキーの消化設定 # 最終書き込みから 30日後 30*24*60*60 # 1日後 24*60*60 # 10時間後 10*60*60 #------------------------------------------- ($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg,$ydayg,$isdstg) = gmtime(time + 30*24*60*60); $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"; $date_gmt = sprintf("%s\, %02d\-%s\-%04d %02d:%02d:%02d GMT",$youbi,$mdayg,$month,$yearg +1900,$hourg,$ming,$secg); #------------------------------------------------------------ # 独自方式のクッキーフォーマット # # 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 { #------------------------------------------ # パスワードのチェックとモードの判定 #------------------------------------------ $temp1 = crypt( $FORM{'editpwd'}, substr($CFG_DATA{'user_pass'},0,2) ); $temp2 = crypt( $FORM{'editpwd'}, substr($master_pass,0,2) ); if ( $temp1 eq $CFG_DATA{'user_pass'} ) { $mode = "owner"; } elsif ( $temp2 eq $master_pass ) { $mode = "admin"; } else { $mode = "user"; } if ( $mode ne "admin" ) { #--------------------------------- # 禁止タグをチェック #--------------------------------- foreach $temp1 (keys %FORM) { foreach $temp2 (@taglist2) { &error("使用を禁止しているタグが含まれています。") if ($FORM{$temp1} =~ /$temp2/ig); } } #--------------------------------- # その他のタグについてのチェック #--------------------------------- foreach $temp1 (keys %FORM) { #--------------------------- # タグを全面禁止する場合 #--------------------------- if( $tag_mode == 0 ) { $FORM{$temp1} =~ s/
/%%%%BR%%%%/ig; $FORM{$temp1} =~ s//>/g; $FORM{$temp1} =~ s/%%%%BR%%%%/
/ig; } #--------------------------- # 許可タグ以外を無効にする #--------------------------- else { #----------------------- # 開始タグの置き換え #----------------------- $FORM{$temp1} =~ s/\に変換する #-------------------------------- $value =~ s/\r\n/
/g; $value =~ s/\n/
/g; #-------------------------------- # 半角カンマをnull(\0)に変換する #-------------------------------- $value =~ s/\,/\0/g; #-------------------------------- # 半角カナを全角カナに変換する # jcode.plのv2.0以降を使うこと #-------------------------------- &jcode'h2z_sjis(*value); #-------------------------------- # 記録するデータはsjisに統一する #-------------------------------- &jcode'convert(*value,'sjis'); $FORM{$name} = $value; } if( $FORM{'page'} eq "" ) { $FORM{'page'} = 0; } } #----------------------------------------------------------------- # ボード定義ファイルの読み込み #----------------------------------------------------------------- sub read_cfg { if( $path eq "" ) { $cfg_file = "./log/"."$FORM{'bordname'}".".cfg"; } else { $cfg_file = "$path"."log/"."$FORM{'bordname'}".".cfg"; } if (!open(DB,"$cfg_file")) { &error("ボード定義ファイルをオープンできません。"); } eval { flock( DB, 1 );}; # ファイルをロック @lines = ; close(DB); eval { flock( DB, 8 );}; # ロック解除 foreach $line (@lines) { ($name,$value) = split(/\,/,$line); $CFG_DATA{$name} = $value; } if ( $CFG_DATA{'max'} > $log_max ) { $CFG_DATA{'max'} = $log_max; } if ( $CFG_DATA{'page'} eq "" ) { $CFG_DATA{'page'} = 0; } else { if( $CFG_DATA{'page'} > $page_max ) { $CFG_DATA{'page'} = $page_max; } } if ( $CFG_DATA{'security'} eq "" ) { $CFG_DATA{'security'} = $security; } } #----------------------------------------------------------------- # 管理用マスターキーの読み込み #----------------------------------------------------------------- sub read_master_key { $pwd_file = "$path$passwd_file"; if ( open( DB, $pwd_file)) { eval { flock( DB, 1 );}; # ファイルをロック $master_pass = ; close(DB); eval { flock( DB, 8 );}; # ロック解除 if ( $master_pass eq "" ) { print "Location:$reload_url"."admin.cgi\n\n"; } chop($master_pass) if $master_pass =~ /\n$/; } else { print "Location:$reload_url"."admin.cgi\n\n"; } } #----------------------------------------------------------------- # ドメインリストの読み込み #----------------------------------------------------------------- sub read_domainlist { if( $domainlist eq "" ) { return; } $filename = "$path"."$domainlist"; if (!open(DB,"$filename")) { &error("ドメインファイルが見つかりません。"); } eval { flock( DB, 1 );}; # ファイルをロック @data = ; close(DB); eval { flock( DB, 8 );}; # ロック解除 foreach $temp (@data) { ($domain,$level) = split(/\,/,$temp); if ( $level eq "0" ) { push( @domainlist1, "$domain" ); } else { push( @domainlist2, "$domain" ); } } } #----------------------------------------------------------------- # ログファイルの読み込み(@linesに格納) #----------------------------------------------------------------- sub read_log { if (!open(DB,"$log_file")) { &error("ファイルの入出力にエラーが発生しました。"); } eval { flock( DB, 1 );}; # ファイルをロック @lines = ; close(DB); eval { flock( DB, 8 );}; # ロック解除 } #----------------------------------------------------------------- # ログファイルの書き出し #----------------------------------------------------------------- sub write_log { if (!open(DB,">$log_file")) { &error("ファイルの入出力にエラーが発生しました。"); } eval { flock( DB, 2 );}; # ファイルをロック print DB @new; close(DB); eval { flock( DB, 8 );}; # ロック解除 }