#!/usr/bin/perl # ------------------------------------------------ # # mimic board model2 # 別窓で返信ができる掲示板スクリプト # # # 30-Apr-2001 # Nobutaka Makino # # ------------------------------------------------ # このソフトウェアは商用目的での使用を除き # 基本的にライセンスフリーとします。 # $Build = '#086'; #================================================ # file path settings #================================================ $mimic_ini = './mimic2.ini'; $skins_ini = './m2skin.ini'; MAIN: { &load_lib($mimic_ini); &load_lib($skins_ini); &parse_extra_forms if(@Extra); &get_cookies; # OP窓表示処理 # -------------------------------------- my $query = &read_buf; if($query =~ /^reply(\d+)$/ ){ &put_reply_window($1); } elsif($query =~ /^delete(\d+)$/ ){ &put_delete_window($1); } # データ操作処理 # -------------------------------------- &decode($query); &check_required_form; &set_default_values; my $action = &get_action; &put_cookies if($action =~ /^add_/); if($action eq 'add_message' ){ &add_message('message'); } elsif($action eq 'add_reply' ){ &add_message('reply'); } elsif($action eq 'delete_message' ){ &delete_message; } elsif($action eq 'set_admin_password' ){ &set_admin_password_step2; } # * # それ以外 # -------------------------------------- else{ &put_board; } } 1; # load_lib.pl #--------------- # ライブラリ/ファイルをロードする #----------------------------------------------------- sub load_lib{ my $file = shift; eval{ require $file; }; if( $@ ){ &error("$ERRMSG_LOADLIB_FAILED ($file: $@)"); } } 1; # cookie.pl #--------------- # 00/08/24 prototpye # クッキーを取得する #---------------------------------------------------------- # %C にクッキー値を指定 # $Cookie_name : mimic.ini クッキー名 # $Extra_forms : skins.ini 特別フォーム数 sub get_cookies{ # 生クッキーを取得 #----------------------------- my $cookies = $ENV{'HTTP_COOKIE'}; $cookies =~ s/; /;/g; # mimic2クッキーを検索 #----------------------------- my $name = $Cookie_name; my $value; for ( split(/;/,$cookies ) ){ if( /^$name=(.+)$/ ){ $value = $1; $value =~ s/%3B/;/g; # [;]のデコード / [:]はそのまま表示する last; } } # 分割 & 代入 #----------------------------- my @values = split(/::/,$value); $C{'name'} = shift @values; $C{'email'} = shift @values; $C{'url'} = shift @values || 'http://'; # extra forms #061 #----------------------------- for(0..$#Extra){ if($Extra[$_]->{'use_cookie'}){ @C{'ext'.$_} = shift @values || $Extra[$_]->{'cookie_default_value'}; } } } # クッキーを発行する #---------------------------------------------------------- sub put_cookies{ if($Use_cookie_checkbox){ return if !$F{'use_cookies'}; } else{ return if !$Use_cookies; } my $name = $Cookie_name; my $limit = &parse_time($Cookie_limit); my @values; # 値の配列を作成 #061 #----------------------------- push @values, $F{'name'}; push @values, $F{'email'}; push @values, $F{'url'}; for $this(@Extra){ push @values, $this->{'value'} if($this->{'use_cookie'}); } # 値が無いときクッキーを削除 #----------------------------- $limit = &parse_time("-30d") if( !@values ); # 時刻の取得 #----------------------------- my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time + $limit); $year = sprintf( "%04d", $year + 1900 ); $sec = sprintf( "%02d", $sec ); $min = sprintf( "%02d", $min ); $hour = sprintf( "%02d", $hour ); $mday = sprintf( "%02d", $mday ); $wday = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat') [$wday]; $mon = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[$mon]; my $date = "$wday, $mday\-$mon\-$year $hour:$min:$sec GMT"; # セパレータ[;][::]をエンコード #----------------------------- for( @values ){ s/;/%3B/g; s/\::/::/g; } # 値の生成 #----------------------------- my $value = join('::',@values); # 出力 #----------------------------- print "Set-Cookie: $name=$value; expires=$date\n"; # クッキー値の更新 #----------------------------- for( @values ){ s/%3B/;/g; } $C{'name'} = shift @values; $C{'email'} = shift @values; $C{'url'} = shift @values || 'http://'; #[079] for(0..$#Extra){ $C{'ext'.$_} = shift @values || $Extra[$_]->{'cookie_default_value'}; } } 1; # error.pl #--------------- sub flush_message{ return if(!$Set_message_called); my $action = &get_action; if( $action eq 'add_message' ){ &put_board; } else{ &put_result_window; } } sub set_message{ $Error_message .= shift; $C{'title'} = $F{'title'}; $C{'message'} = $F{'message'}; $C{'message'} =~ s/
/\n/ig; for(0..$#Extra){ $C{'ext'.$_} = $Extra[$_]->{'value'}; } $Set_message_called = 1; # flush用フラグ } #------- sub error{ print "Content-type: text/html\n\n"; #--------------------------------------------------------------------- print qq( エラーが発生しました
エラーが発生しました
An error has occured

@_

Mimic Board the 2nd $Build
(c) 1999-2000 Nobutaka Makino
); #--------------------------------------------------------------------- exit; } 1; # misc.pl #--------------- # 文字を短くする(2バイト文字対応) #----------------------------------------------------- # update 2001.04.30 [#080] # うまく切れてなかったのを修正 sub to_short_string{ my $string = shift; my $size = shift; my $length = length($string); # 短くしなくて良いなら終わり #----------------------------- return $string if !$size; return $string if $size > $length; &load_lib( $Jcode ); my $count; my $new_string; my $is2byte; while( $count!=$length && $count<$size ){ my $char = substr($string,$count,2); # 2文字取得してみる ($is2byte,undef) = &jcode::getcode(*char); # 漢字かな? if( $is2byte){ $new_string .= $char; $count+=2; } else{ $new_string .= substr($string,$count++,1); } } return $new_string . '...'; } # 書き込み時刻の取得 #----------------------------------------------------- sub get_date{ my $date = $Date_format; my $diff = &parse_time($Time_difference); #--------------------- # 書き込み時間の取得 my $week; my($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime(time + $diff ); my $hour_t = $hour; if($hour_t > 12){ $hour_t -= 12 }; if($hour_t == 0){ $hour_t += 12 }; # [#081] my $tt; if($hour < 12 ){ $tt = $Am_tt; } #086 else { $tt = $Pm_tt; } # for($date){ s/MMM//; s/ddd//; s/tt//; s/yyyy/ sprintf("%02d", $year+1900)/e; s/yy/ sprintf("%02d", $year%100 )/e; s/MM/ sprintf("%02d", $mon+1) /e; s/M/ $mon+1 /e; s/dd/ sprintf("%02d", $mday) /e; s/d/ $mday /e; s/HH/ sprintf("%02d", $hour) /e; s/H/ $hour /e; s/hh/ sprintf("%02d", $hour_t) /e; s/h/ $hour_t /e; s/mm/ sprintf("%02d", $min) /e; s/m/ $min /e; s/ss/ sprintf("%02d", $sec) /e; s/s/ $sec /e; s// $Mons[$mon] /e;# s// $Days[$wday] /e;# s//$tt/; } return $date; } # リモートホスト名の取得 #----------------------------------------------------- sub get_host{ my $host = $ENV{'REMOTE_HOST'}; my $addr = $ENV{'REMOTE_ADDR'}; if( $host eq $addr || $host eq ""){ my $packed_addr = pack('C4', split(/\./,$addr) ); ($host) = gethostbyaddr($packed_addr,2); } return $host || $addr; } 1; # lock.pl #--------------- # ファイルロック #---------------------------------------------------------- # スカラ値でもファイルハンドル扱いされる sub lock{ return if(!$Use_lock); my $handle = shift; eval{ flock($handle,2); }; if($@){ &error("$ERRMSG_FLOCK_FAILED ($handle: $@) "); } } 1; # decode.pl #--------------- # デコード #---------------------------------------------------------- sub decode{ my $tags = $Arrow_tags; my $link = $Auto_link; my $buffer = shift; &load_lib($Jcode); &load_lib($Ntc) if($tags || $link ); my @pairs = split(/&/,$buffer); my($name ); local($value); foreach(@pairs){ ($name, $value) = split(/=/); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ s/\r\r/\n/go; $value =~ s/\r\n/\n/go; $value =~ s/\n/\t/go; # 文字コード変換 #-------------------------- &jcode'h2z_sjis(*value); &jcode'convert(*value,'sjis'); $value =~ s/\,/,/g; # タグの処理 / 後で見直し #-------------------------- if( $tags ){ &ntc'tag(*value,$tags, 0, 0) if( $name ne 'message' ); #リンクしない &ntc'tag(*value,$tags, 0, $link) if( $name eq 'message' ); #リンクする } else{ $value =~ s/\/>/go; &ntc'tag(*value,$tags, 0,$link) if( $name eq 'message' && $link ); } $value =~ s/\t/
/go; # ハッシュ代入 #-------------------------- $Extra[$1]->{'value'} = $value if($name =~ /^ext(\d+)$/); $F{$name} = $value; } # 'addr' if($F{'addr'}){ if($F{'addr'} =~ m|\@| ){ $F{'email'} = $F{'addr'}; } if($F{'addr'} =~ m|^http://|){ $F{'url'} = $F{'addr'}; } } # 簡易フォーマットチェック $F{'url'} = '' if( $F{'url'} !~ m|^http://(.+)\.(.+)$| ); $F{'email'} = '' if( $F{'email'} !~ m|^(.+)@(.+)\.(.+)$| ); # 061 Extra入力値チェック if( &get_action =~ /^add_/ ){ for $this(@Extra){ next if(!$this->{'value'}); # 後でrequiredチェック next if(!$this->{'use_type_check'}); if($this->{'value'} !~ /$this->{'type_check_regexp'}/){ if($this->{'type_check_error_mode'}){ &set_message( $this->{'type_check_error_message'} ); &flush_message; } else{ $this->{'value'} = ''; } } } } } 1; # get_action.pl #--------------- # 00/08/26 うーん。存在意義があるのか。 # 00/08/24 アクション名を抽出する # 基本的にactionは単項で渡される # Extract Action name. #------------------------------------------------ sub get_action{ return $F{'action'} if($F{'action'}); for(@Actions){ return $_ if( exists $F{$_} || exists $F{"$_.x"} || exists $F{"$_.y"} ); } } 1; # put_board.pl #--------------- sub put_board{ local @Data = &load_data($Data_file); # for extract reply data! my $head = shift @Data; &check_header($head); print "Expires: 01/01/70 00:00:00 GMT\n"; print "Content-type: text/html\n\n"; &page_init; &format_init; &replace_print($Format_head); my $count; while($_ = shift @Data){ # adjust display arguments #------------------------------ next if(/^\t/); # $count++; if($count < $Range_start){ $Put_page_ctrl_prev = 1; next; } if($count > $Range_last ){ $Put_page_ctrl_next = 1; last; } # extract data #------------------------------ s/\n$//; # chomp; my $fmt; my($mid,$name,$email,$url,$title,$message,$date,$host,$time,$password,@extra) = split (/,/,$_); if($Link_main_url_on_name && $url ){ $name = qq|$name|; } if($Link_main_email_on_name && $email ){ $name = qq|$name|; } # anchor #------------------------------ if($url){ ( $fmt = $Format_main_url ) =~ s/\$url/$url/g; $url = $fmt; } else{ $url = $Format_main_url_blank } if($email){ ( $fmt = $Format_main_email ) =~ s/\$email/$email/g; $email = $fmt; } else{ $email = $Format_main_email_blank; } for(@Extra_subscripts_which_use_formats){ if($extra[$_]){ ( $fmt = $Extra[$_]->{'replace_format_main'} ) =~ s/\$value/$extra[$_]/g; $extra[$_] = $fmt; } else{ $extra[$_] = $Extra[$_]->{'replace_format_main_blank'}; } } my $reply_data = &extract_reply_data; # replace ! #------------------------------ for($temp=$Format_data){ s/\$Cgi_url/$Cgi_url/sg; s/\$mid/$mid/sg; s/\$name/$name/sg; s/\$email/$email/sg; s/\$url/$url/sg; s/\$title/$title/sg; s/\$message/$message/sg; s/\$date/$date/sg; s/\$host/$host/sg; s/\$time/$time/sg; s/\$ext(\d+)/$extra[$1]/sg; s/\$loop_value/$Loop_values[ $mid % ( $#Loop_values + 1) ]/g if($#Loop_values >= 0 ); s/\$random_value/$Random_values[ int( rand($#Random_values+1) ) ]/eg; s/\$reply_data/$reply_data/sg; print; } } &page_control_init; &replace_print($Format_last) if(!$Put_page_ctrl_next); &replace_print($Format_foot); exit; } #--------------------------------------------------------------- 1; # replace_print.pl #--------------- sub replace_print{ my $line = shift; for($line){ # base s/\$cgi_url/$Cgi_url/sg; s/\$home_url/$Home_url/sg; # page control s/\$prev/$Prev/sg; s/\$next/$Next/sg; # cookeis or default values s/\$cook_name/$C{'name'}/sg; s/\$cook_email/$C{'email'}/sg; s/\$cook_url/$C{'url'}/sg; s/\$cook_addr/$C{'email'}||$C{'url'}/esg; s/\$cook_title/$C{'title'}/sg; s/\$cook_message/$C{'message'}/sg; s/\$cook_ext(\d+)/$C{'ext'.$1}/sg; # others s/\$build/$Build/sg; s/\$error_message/$Error_message/sg; s/\$op_window_height/$Op_window_height/sg; s/\$op_window_width/$Op_window_width/sg; print; } } 1; # put_board_etc.pl #--------------- # ページ設定を行う #---------------------------------------------------------- sub page_init{ my $current = $F{'page'} || 1; $Page_next = $current+1; $Page_prev = $current-1; $Range_last = $current * $Arguments; $Range_start = $Range_last - $Arguments +1; } # #---------------------------------------------------------- sub page_control_init{ if($Put_page_ctrl_prev){ ( $Prev = $Format_page_ctrl_prev ) =~ s/\$url/$Cgi_url?page=$Page_prev/g; } else{ $Prev = $Format_page_ctrl_prev_off; } if($Put_page_ctrl_next){ ( $Next = $Format_page_ctrl_next ) =~ s/\$url/$Cgi_url?page=$Page_next/g; } else{ $Next = $Format_page_ctrl_next_off; } } # ファイルをスカラ値に読み込む #---------------------------------------------------------- sub load_data{ my $file = shift; open(FH, $file) || &error("$ERRMSG_OPEN_FAILED ($file: $!)"); &lock(FH); my @line = ; close(FH); return @line; } 1; # put_board_reply.pl #--------------- # extract reply data sub extract_reply_data{ my @reply; my $buffer; while($Data[0] =~ /^\t/){ my $data = shift @Data; $data =~ s/^\t//; $data =~ s/\n$//; push @reply, $data; } for(@reply){ # split data #------------------------------ ($mid,$name,$email,$url,$title,$message,$date,$host,$time,$password,@extra) = split (/,/,$_); # set anchors #------------------------------ my $fmt; if($Link_reply_url_on_name && $url ){ $name = qq|$name|; } if($Link_reply_email_on_name && $email ){ $name = qq|$name|; } if($url){ ( $fmt = $Format_reply_url ) =~ s/\$url/$url/g; $url = $fmt; } else{ $url = $Format_reply_url_blank } if($email){ ( $fmt = $Format_reply_email ) =~ s/\$email/$email/g; $email = $fmt; } else{ $email = $Format_reply_email_blank; } for(@Extra_subscripts_which_use_formats){ if($extra[$_]){ ( $fmt = $Extra[$_]->{'replace_format_reply'} ) =~ s/\$value/$extra[$_]/g; $extra[$_] = $fmt; } else{ $extra[$_] = $Extra[$_]->{'replace_format_reply_blank'}; } } # replace ! #------------------------------ for($temp=$Format_reply){ s/\$Cgi_url/$Cgi_url/g; s/\$mid/$mid/sg; s/\$name/$name/sg; s/\$email/$email/sg; s/\$url/$url/sg; s/\$title/$title/sg; s/\$message/$message/sg; s/\$date/$date/sg; s/\$host/$host/sg; s/\$time/$time/sg; s/\$ext(\d+)/$extra[$1]/sg; s/\$loop_value/$Loop_values[ $mid % ( $#Loop_values + 1) ]/g if($#Loop_values >= 0 ); s/\$random_value/$Random_values[ int( rand($#Random_values+1) ) ]/eg; $buffer .= $_; } } return $buffer; } 1; # read_buf.pl #--------------- # フォーム値取得 #---------------------------------------------------------- sub read_buf{ my $buffer; read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'} ); $buffer = $ENV{'QUERY_STRING'} if( !$buffer ); return $buffer; } 1; # format_init.pl #--------------- # フォーマットを抽出 #---------------------------------------------------------- sub format_init{ my $format = &load_format($Format_mimic_main); for($format){ if(/(.*)/s){ $Format_head =$1; } if(/(.*)/s){ $Format_data =$1; } if(/(.*)/s){ $Format_last =$1; } if(/(.*)/s){ $Format_foot =$1; } for($Format_data){ if( s/(.+)/\$reply_data/s ){ $Format_reply = $1; } } } } # ファイルをスカラ値に読み込む #---------------------------------------------------------- sub load_format{ my $file = shift; open(FMT, $file) || &error("$ERRMSG_OPEN_FAILED ($file: $!)"); $line = join('',); close(FMT); return $line; } 1; # set_admin_password.pl #--------------- # 管理者パスワード登録 #---------------------------------------------------------- sub set_admin_password_step2{ # encode the password #-------------------------------------------- my $encoded_password = &encode_password($F{'password'}); # open the file #-------------------------------------------- open(FH, "+<$Data_file") || &error("$ERRMSG_OPEN_FAILED ($file: $!)"); &lock(FH); my @data = ; my $head = shift @data; # already password exists #---------------------------------------- if($head =~ /^mimic board2:(.+):(.*)$/){ close FH; &error("$ERRMSG_ADMIN_PASSWORD_NOT_BLANK"); } # extract last_mid from header of mimic board1 #---------------------------------------- if($head =~ /[^,]+,(\d+),\d+,[^,]+$/){ $last_mid = $1; &set_message($MSG_HEADER_CONVERTED); } # add header #---------------------------------------- unshift(@data, "mimic board2:$encoded_password:$last_mid\n"); # write on the file #-------------------------------------------- seek(FH,0,0); truncate(FH,0); print FH @data; close FH; &set_message($MSG_ADMIN_PASSWORD_SET_SUCCEED); &put_board; } # 管理者パスワード登録画面出力 #---------------------------------------------------------- sub set_admin_password_step1{ print "Expires: 01/01/70 00:00:00 GMT\n"; print "Content-type: text/html\n\n"; #--------------------------------------------------------------------- print qq( 管理者パスワードのセットアップ
管理者パスワードの設定
Admin password setup

new password:

Mimic Board the 2nd $Build
(c) 1999-2000 Nobutaka Makino
); #--------------------------------------------------------------------- } 1; # password.pl #--------------- # salt取得 & 暗号化 #---------------------------------------------------------- sub encode_password{ my $raw_password = shift; return '' if(!$raw_password); my $salts = q|./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz|; srand(time/$$); # umm..- # my $salt = substr($salts, int(rand(63)),1); $salt .= substr($salts, int(rand(63)),1); return crypt($raw_password,$salt); } # パスワード照合 #---------------------------------------------------------- sub password_verify{ my $given_password = shift; my $encoded_password = shift; return 0 if(!$given_password || !$encoded_password); return ( $encoded_password eq crypt($given_password,$encoded_password) ); } 1; # prase_time.pl #--------------- sub parse_time{ my $string = shift; my $parsed = $string; for($parsed){ s/s//g; s/m/*60/g; s/h/*60*60/g; s/d/*60*60*24/g; s/M/*60*60*24*30/g; s/y/*60*60*24*365/g; } my $evaled = eval $parsed; if(!$@ && ($evaled =~ /^\d*$/ )){ return $evaled; } else{ &error("$ERRMSG_PARSE_TIME_FAILED ( $string -> $parsed )"); } } 1; # add_message.pl #--------------- sub add_message{ # check action #---------------------------------- my $add_message; my $add_reply; if( shift eq 'message'){ $add_message = 1; } else { $add_reply = 1; } # adding reply, disabled ? #----------------------------------- if($add_reply && $Disable_adding_reply ){ &set_message( $MSG_ADDING_REPLY_DISABLED ); &put_result_window; } # file open #------------------------------------------------------ open(FH, "+<$Data_file") || &error("$ERRMSG_OPEN_FAILED ($file: $!)"); &lock(FH); my @data = ; my $head = shift @data; my($encoded_admin_password,$last_mid) = &check_header($head); $last_mid++; # require admin password when you add message. #-------------------------------------------------- my $set_message; if( ( $add_message && $Admin_password_required_when_add_message && !&password_verify($F{'password'},$encoded_admin_password)) || ( $add_reply && $Admin_password_required_when_add_reply && !&password_verify($F{'password'},$encoded_admin_password)) ){ &set_message( $MSG_WRONG_ADMIN_PASSWORD ); } # check double post #-------------------------------------------------- # seek the latest data my $target_mid = $F{'target_mid'}; my $target_data; if($add_message){ $target_data = $data[0]; } # 重複チェックアルゴリズム変更 (084) # target_mid : 返信対象のメッセージID # 返信対象が含まれるツリーの一番最後のメッセージを取り出して照合 else{ my $found = 0; my $prev; for(@data){ if($found && !/^\t/ ){ last; } # 親記事が来たら、その1個前を取り出したい if($found ){ $prev = $_; } # 一個前をセット if(/(^|\t)$target_mid/){ $found=1; $prev = $_; } # ターゲットが見つかった! } $target_data = $prev; if(!$target_data){ &set_message("$MSG_DATA_NOT_FOUND ( message id: $target_mid )"); } } # split the latest data (undef,undef,undef,undef,undef,$last_message,undef,$last_host) = split(/,/,$target_data); if( $Check_double_post && ($last_message eq $F{'message'}) && ($last_host eq &get_host)){ &set_message( $MSG_DOUBLE_POST ); } # if any warning, print it. #-------------------------------------------------- if( $Set_message_called ){ close FH; &flush_message; } # extract extraform values #-------------------------------------------------- my @extra; for $this(@Extra){ push @extra, $this->{'value'}; } # create the new message #-------------------------------------------------- my $new_data = join(',', $last_mid, $F{'name'}, $F{'email'}, $F{'url'}, $F{'title'}, $F{'message'}, &get_date, &get_host, time, &encode_password($F{'password'}), @extra ); my $new_head = "mimic board2:$encoded_admin_password:$last_mid"; # adjust number of message, and add the message. #-------------------------------------------------- if($add_message){ my $count; for(@data){ $count++ if(!/^\t/); $_ = '' if($count >= $Arguments_max); } unshift(@data, $new_data."\n" ); } # or add the reply to the place #-------------------------------------------------- else{ my $reply_limit = $Limit_number_of_reply_messages; my $move_above = $Move_the_tree_above_when_replied; my $target_found; my $number_of_tree; my $parent_index; for(0..$#data+1){ # 最後のデータも消せるように if( $data[$_] !~ /^\t/){ # if found ... #-------------------------------------- if($target_found){ # check the number of replies. #---------------------------------- if($reply_limit && $number_of_tree > $reply_limit){ &set_message("$MSG_TOO_MANY_REPLIES ( message id: $target_mid )"); close FH; &put_result_window; # :exit: } # add type1 move above. #---------------------------------- if($Move_the_tree_above_when_replied ){ @trees = splice(@data,$parent_index,$number_of_tree); unshift(@data,"\t$new_data\n"); unshift(@data, @trees ); } # add type2 stay there #---------------------------------- else{ splice(@data,$_,0,"\t$new_data\n"); } last; } # initialize the tree info. #-------------------------------------- $number_of_tree = 0; $parent_index = $_; } # set a found flag #------------------------------------------ if( $data[$_] =~ /(^|\t)$target_mid,/){ $target_found = 1; } $number_of_tree++; } if($target_found){ &set_message("$MSG_ADD_REPLY_SUCCEEDED ( message id: $last_mid )"); } else { &set_message("$MSG_ADD_REPLY_FAILED ( message id: $last_mid )"); } } unshift(@data, $new_head."\n" ); seek(FH,0,0); truncate(FH,0); print FH @data; close FH; if( $add_message ){ &put_board; } else { &put_result_window; } } 1; # check_header.pl #--------------- sub check_header{ my $head = shift; if($head !~ /^mimic board2:(.+)$/){ &set_admin_password_step1; exit; } else{ return split(/:/,$1); } } 1; # parse_extra_forms.pl #--------------- sub parse_extra_forms{ # エラー検出など? for(0..$#Extra){ # 表示ループの処理時間短縮対策 if($Extra[$_]->{'use_replace_format'} ){ push @Extra_subscripts_which_use_formats, $_; } # require setting check if($Extra[$_]->{'required'} && !$Extra[$_]->{'required_message'} ){ error($ERRMSG_REQUIRED_MESSAGE_REQUIRED); } if($Extra[$_]->{'use_type_check'} && !$Extra[$_]->{'type_check_error_message'} ){ error($ERRMSG_TYPE_CHECK_MESSAGE_REQUIRED); } } } 1; # check_required_form.pl #--------------- sub check_required_form{ my $action = &get_action; # write a message #------------------------------------------------------ if($action =~ /^add_(message|reply)/){ if($1 eq 'message'){ $add_message = 1; } else { $add_reply = 1; } # require admin password when you add message. #-------------------------------------------------- if( $add_message && $Admin_password_required_when_add_message && !$F{'password'} ){ &set_message( $MSG_ADMIN_PASSWORD_REQUIRED ); } # require admin password when you add message. #-------------------------------------------------- if( $add_reply && $Admin_password_required_when_add_reply && !$F{'password'} ){ &set_message( $MSG_ADMIN_PASSWORD_REQUIRED ); } # check required forms #-------------------------------------------------- if( $Require_name && !$F{'name'} ){ &set_message( $MSG_NAME_REQUIRED ); } if( $Require_email && !$F{'email'} ){ &set_message( $MSG_EMAIL_REQUIRED ); } if( $Require_url && !$F{'url'} ){ &set_message( $MSG_URL_REQUIRED ); } if( $Require_title && !$F{'title'} ){ &set_message( $MSG_TITLE_REQUIRED ); } if( $Require_message && !$F{'message'} ){ &set_message( $MSG_MESSAGE_REQUIRED ); } if( $Require_password && !$F{'password'} ){ &set_message( $MSG_PASSWORD_REQUIRED ); } if( $add_reply && !$F{'target_mid'} ){ &set_message( $MSG_TARGET_MID_REQUIRED_REPLY ); } # make extra data. #-------------------------------------------------- for $this(@Extra){ if( $this->{'required'} && !($this->{'value'}) ){ &set_message($this->{'required_message'}); } } # if any warning, push it. #-------------------------------------------------- &flush_message; } # delete a message #------------------------------------------------------ elsif($action eq 'delete_message'){ # check required forms #-------------------------------------------------- if(!$F{'target_mid'}){ &set_message($MSG_TARGET_MID_REQUIRED_DELETE);} if(!$F{'password'} ){ &set_message($MSG_PASSWORD_REQUIRED); } # error and exit; #-------------------------------------------------- &flush_message; } # set admin password #------------------------------------------------------ elsif($action eq 'set_admin_password'){ # check required forms #-------------------------------------------------- if(!$F{'password'}){ &error($ERRMSG_ADMIN_PASSWORD_REQUIRED); } } } 1; # put_op_result_window.pl #--------------- # $error_messageを置換するだけの関数? sub put_result_window{ my $format = &load_format($Format_op_result); print "Expires: 01/01/70 00:00:00 GMT\n"; print "Content-type: text/html\n\n"; &replace_print($format); exit; } 1; # put_op_delete_window.pl #--------------- # ターゲットMIDの記事の情報をロードする sub put_delete_window{ my $target_mid = shift; my @data = &load_data($Data_file); my $format = &load_format($Format_op_delete); for(@data){ if(/(^|\t)$target_mid,/){ ($target_data=$_) =~ s/^\t//; last; } } if(!$target_data){ &set_message("$MSG_DATA_NOT_FOUND (message id: $target_mid)"); &put_result_window; } my ($mid,$name,$email,$url,$title,$message,$date,$host,$time,$password,@extra) = split (/,/,$target_data); print "Expires: 01/01/70 00:00:00 GMT\n"; print "Content-type: text/html\n\n"; for($format){ # base s/\$cgi_url/$Cgi_url/sg; s/\$home_url/$Home_url/sg; # others s/\$build/$Build/sg; s/\$mid/$mid/sg; # 削除記事確認用? # from: put_board s/\$name/$name/sg; s/\$email/$email/sg; s/\$url/$url/sg; s/\$title/$title/sg; s/\$message/$message/sg; s/\$date/$date/sg; s/\$host/$host/sg; s/\$time/$time/sg; s/\$ext(\d+)/$extra[$1]/sg; print; } exit; } 1; # put_op_reply_window.pl #--------------- # ターゲットMIDの記事の情報をロードする sub put_reply_window{ my $target_mid = shift; my @data = &load_data($Data_file); my $format = &load_format($Format_op_reply); for(@data){ if(/(^|\t)$target_mid,/){ ($target_data = $_) =~ s/^\t//; last; } } if(!$target_data){ &set_message($MSG_DATA_NOT_FOUND); &put_result_window; } my ($mid,$name,$email,$url,$title,$message,$date,$host,$time,$password,@extra) = split (/,/,$target_data); my $reply_messae; my $reply_title = $Reply_title_head . &to_short_string($title,$Reply_title_lengh_limit); ($reply_message = $message) =~ s/(^|
)/\n$Reply_message_head/g; print "Expires: 01/01/70 00:00:00 GMT\n"; print "Content-type: text/html\n\n"; for($format){ # base s/\$cgi_url/$Cgi_url/sg; s/\$home_url/$Home_url/sg; # others s/\$build/$Build/sg; s/\$mid/$mid/sg; # from: replace_print s/\$cook_name/$C{'name'}/sg; s/\$cook_email/$C{'email'}/sg; s/\$cook_url/$C{'url'}/sg; s/\$cook_addr/$C{'email'}||$C{'url'}/esg; s/\$cook_title/$C{'title'}/sg; s/\$cook_message/$C{'message'}/sg; s/\$cook_ext(\d+)/$C{'ext'.$1}/sg; # from: put_board s/\$mid/$mid/sg; s/\$name/$name/sg; s/\$email/$email/sg; s/\$url/$url/sg; s/\$title/$title/sg; s/\$message/$message/sg; s/\$date/$date/sg; s/\$host/$host/sg; s/\$time/$time/sg; s/\$ext(\d+)/$extra[$1]/sg; # original s/\$reply_title/$reply_title/sg; s/\$reply_message/$reply_message/sg; print; } exit; } 1; # delete_message.pl #--------------- sub delete_message{ # 管理者のみ削除可能 # 削除禁止 # 投稿者パスワード!? my $target_mid = $F{'target_mid'}; my $last_mid; local $encoded_admin_password; local $given_password = $F{'password'}; open(FH, "+<$Data_file") || &error("$ERRMSG_OPEN_FAILED ($file: $!)"); &lock(FH); my @data = ; # admin password check #------------------------------ my $head = shift @data; ($encoded_admin_password,$last_mid) = &check_header($head); # delete message #------------------------------ my $delete_tree = $Delete_the_tree_when_parent_deleted; my $parent_index; my $number_of_tree; my $target_found; if($delete_tree){ for(0..$#data+1){ if($data[$_] !~ /^\t/){ if($target_found){ splice(@data,$parent_index,$number_of_tree); last; } $parent_index = $_; $number_of_tree=0; } if($data[$_] =~ /(^|\t)$target_mid,/){ &verify_delete_password($data[$_]); $target_found = 1; if($1 eq "\t"){ splice(@data,$_,1); last; } } $number_of_tree++; } } else{ # not deltree for(0..$#data){ if($data[$_] =~ /(^|\t)$target_mid,/){ &verify_delete_password($data[$_]); $data[$_+1] =~ s/^\t// if($1 ne "\t"); splice(@data,$_,1); $target_found = 1; last; } } } if($target_found){ &set_message("$MSG_DELETE_MESSAGE_SUCCEEDED ( message id: $target_mid )"); } else { &set_message("$MSG_DELETE_MESSAGE_FAILED ( message id: $target_mid )"); } unshift(@data, $head ); seek(FH,0,0); truncate(FH,0); print FH @data; close FH; &put_result_window; } sub verify_delete_password{ my $admin_only = $Delete_with_admin_password_only; my $target_data = shift; $target_data =~ s/\n$//; my $encoded_user_password = (split(/,/,$target_data) )[9]; my $admin_result = &password_verify($given_password, $encoded_admin_password ); my $user_result = &password_verify($given_password, $encoded_user_password ); my $result; if($admin_only){ $result = $admin_result; } else{ $result = $admin_result || $user_result; } if(!$result){ close FH; &set_message($MSG_WRONG_PASSWORD); &put_result_window; } return; } 1; # set_default_values.pl #--------------- sub set_default_values{ # set_default value #-------------------------------------------------- $F{'name'} ||= $Default_name; $F{'title'} ||= $Default_title; $F{'message'} ||= $Default_message; for $this(@Extra){ next if($this->{'value'}); if($this->{'use_default_random_value'}){ my $uniq_subscripts = int( rand( $#{ $this->{'default_random_values'} } + 1 )); $this->{'value'} = $this->{'default_random_values'}[ $uniq_subscripts ]; } $this->{'value'} ||= $this->{'default_value'}; } } 1;