#! /usr/local/bin/perl #掲示板を作ってみる。 #※実際の運用時はこのファイルの拡張子を.cgiに変更する。 #----------------------------------------------------------- #ディレクトリ構造 ※[]内は実行権限の設定 #----------------------------------------------------------- #┏0509_bbs.cgi(このファイル)[755] #┃ #┣cgi-lib.pl (ライブラリ)[444]/フォームデータの送受信処理 #┣cookie.pl (ライブラリ)[444]/クッキーの読み書き #┣jcode.pl (ライブラリ)[444]/文字コードの処理 #┃ #┣logfile.txt[666] /書き込まれた内容を保存するファイル #┣home.gif /家の画像(クリックすると登録されたURLへ飛ぶ) #┃ #┗guest_imgs[444] /ディレクトリ #  ┣banana.gif (バナナの画像) #  ┣cherry.gif (さくらんぼの画像) #  ┣fuji.gif (富士の画像) #  ┣grape.gif (ぶどうの画像) #  ┣ichigo.gif (いちごの画像) #  ┣kogyoku.gif (紅玉の画像) #  ┣malon.gif (栗の画像) #  ┗sweet.gif (スウィーティの画像) #  ┗delited.gif (削除済み画像) # #※各種ライブラリファイルは他のサイトで入手できる。 #----------------------------------------------------------- #定数など #----------------------------------------------------------- require './jcode.pl'; #各種ライブラリ呼び出し require './cgi-lib.pl'; require './cookie.pl'; #クッキー $jisin='./bbs.cgi'; #このcgiファイル $title='掲示板プログラム'; $homepage_url='./bbs.cgi'; #ホームページのURL $log_file='./logfile.txt'; #ログファイル $home_icon='./home.gif'; #HPリンク用にアイコン $page_size=5; #1ページ当たりの表示件数 $kanri_mail='aaa@aaa.com'; #管理者用メアド $max_log='2000'; #ログを保管する最大件数 $double_count=3; #二重投稿をチェックする数(範囲) $img_dir='./guest_imgs/'; #投稿者イメージを格納するディレクトリ $guest_imgs[0]='banana.gif'; #バナナ $guest_imgs[1]='cherry.gif'; #さくらんぼ $guest_imgs[2]='fuji.gif'; #富士 $guest_imgs[3]='grape.gif'; #ぶどう $guest_imgs[4]='ichigo.gif'; #いちご $guest_imgs[5]='kogyoku.gif'; #紅玉 $guest_imgs[6]='malon.gif'; #栗 $guest_imgs[7]='sweet.gif'; #スウィーティ $guest_imgs_name[0]='バナナ'; $guest_imgs_name[1]='さくらんぼ'; $guest_imgs_name[2]='富士'; $guest_imgs_name[3]='ぶどう'; $guest_imgs_name[4]='いちご'; $guest_imgs_name[5]='紅玉'; $guest_imgs_name[6]='栗'; $guest_imgs_name[7]='スウィーティ'; $guest_imgs_delited='delited.gif'; #削除済み画像 #クッキーの名前と値 $COOKIE_EXP=30; #クッキーの有効期限 $COOKIE_NAME_A="K_boardID_A"; #クッキーの名前/名前 $COOKIE_NAME_B="K_boardID_B"; #クッキーの名前/メアド $COOKIE_NAME_C="K_boardID_C"; #クッキーの名前/ホムペ $COOKIE_NAME_D="K_boardID_D"; #クッキーの名前/パスワード $COOKIE_NAME_E="K_boardID_E"; #クッキーの名前/投稿者イメージ #文字色 @colors=('#000000','#660000','#cc0000','#669900','#cc9900'); #----------------------------------------------------------- #受信部 #----------------------------------------------------------- $addr=$ENV{'REMOTE_ADDR'}; #環境変数の取得(IPアドレス) $host=$ENV{'REMOTE_HOST'}; #環境変数(どこから来たか) $method=$ENV{'REQUEST_METHOD'}; ReadParse(); #cgi-lib.plの関数/フォームからデータの受信処理 #GETもPOSTも両方対応している。 while(($k,$v)=each(%in)){ &jcode'convert(*v,'euc'); #連想配列%inの値をeucにコンバートする &jcode::h2z_euc(*v); #★さらにここで半角カナを全角に戻す &jcode::tr(*v, '0-9A-Za-z', '0-9A-Za-z'); #半角から全角へ &jcode::tr(*v, ' ()_@−', ' ()_@-'); #全角SPなどを半角に #$v =~ s/
/\n/gi; $v =~ s//>/g; $v =~ s/\r\n|[\n\r]/
/gi; #もしくは(\r\nか\nのとき)$v=~s/\r?\n/
/g; $v =~ s/,/,/g; #$v=~s/&/&/g; $v=~s/"/"/g; #※一部のタグを有効の場合のダブルクオートは無効 #(参考)************************************************************************************* #$v=~s/&lt;(A|FONT|I|B)(\s*)(.*?)&gt;(.*?)&lt;\/\1&gt;/<$1$2$3>$4<\/$1>/gi; #特別なタグだけ使用できるようにする。(A,FONT,I,Bタグ) #< AかFONTかIかB($1) 0個以上のSP($2) 任意の文字列($3) > 任意の文字列($4) #< \/ マッチした(A|FONT|I|B) > ⇒置換え後 <$1$2$3>$4<\/$1> #※ただしこの場合入れ子になったタグやダブルクオートが足りない物は表示できない! #******************************************************************************************* $in{ $k } = $v; #コンバートして再び%inに格納 } $mode=$in{'mode'}; #掲示板モード切替 $name=$in{'name'}; #投稿者 $password=$in{'password'}; #パスワード $email=$in{'email'}; #電子メール $subject=$in{'subject'}; #タイトル $text=$in{'text'}; #本文 $h_addr=$in{'h_addr'}; #HP $page=$in{'page'}; #ページ数 $edit_line=$in{'edit_line'}; #引用する番号 $edit_mode=$in{'edit_mode'}; #引用文章をフォームに表示する $guest_img=$in{'guest_img'}; #投稿者画像 $guest_color=$in{'guest_color'};#本文の色 #----------------------------------------------------------- #制御部 #----------------------------------------------------------- #print "Content-type:text/html;charset=x-euc-jp\n\n"; #httpヘッダ if($mode eq 'write'){ #■書き込みモード if(($name eq '')||($text eq '')){ #未入力項目のチェック print "Content-type:text/html;charset=x-euc-jp\n\n"; &Show_ERR('「投稿者名」と「投稿内容」な入力必須項目です。'); exit; } &Write_LOGS(); #データ書き込み #print "モード$mode 名前$name 本文$text 画像$guest_img"; #★クッキーの保存 setCookie($COOKIE_NAME_A,$name,&getExpiresAfter($COOKIE_EXP)); #引数:クッキー名,値,期限 setCookie($COOKIE_NAME_B,$email,&getExpiresAfter($COOKIE_EXP)); setCookie($COOKIE_NAME_C,$h_addr,&getExpiresAfter($COOKIE_EXP)); setCookie($COOKIE_NAME_D,$password,&getExpiresAfter($COOKIE_EXP)); setCookie($COOKIE_NAME_E,$guest_img,&getExpiresAfter($COOKIE_EXP)); print "Content-type:text/html;charset=x-euc-jp\n\n"; #httpヘッダ $page="1"; #書き込みしたら先頭ページに戻る Print_Head(); Print_Input_Area(); #Print_Rireki(); Print_Rireki_TREE(); Print_Foot(); } #elsif($mode eq 'change'){ # print "Content-type:text/html;charset=x-euc-jp\n\n"; #httpヘッダ # print "OK!ここでログを上書きする動作を行う"; #} elsif($edit_mode eq 'show_delite'){ Read_LOGS(); print "Content-type:text/html;charset=x-euc-jp\n\n"; #httpヘッダ Print_Head(); &Print_DEL_KAKUNIN(); #print "OK!削除確認画面"; #Print_Rireki(); Print_Foot(); } else{ #■通常モード Read_LOGS(); #@Logsに外部ファイルを格納 #★削除を実行した時にクッキーのパスワードを削除する if($edit_mode eq 'delite'){ setCookie($COOKIE_NAME_D,$password,&getExpiresAfter(-1)); } #★クッキーの読み込み $c_name=getCookie($COOKIE_NAME_A) if(!$name); $c_email=getCookie($COOKIE_NAME_B) if(!$email); $c_h_addr=getCookie($COOKIE_NAME_C) if(!$h_addr); $c_password=getCookie($COOKIE_NAME_D) if(!$password); $guest_img=getCookie($COOKIE_NAME_E) if(!$guest_img); print "Content-type:text/html;charset=x-euc-jp\n\n"; #httpヘッダ if($edit_mode eq 'delite'){ #ログの削除を実行($edit_mode eq 'show_delite'より) $Change_Info=qq|■投稿の削除に成功しました。
|; #print "$edit_lineと$page
"; DEL_Log(); } if($mode eq 'change'){ #ログの編集を実行 if(($name eq '')||($text eq '')){ #未入力項目のチェック &Show_ERR('「投稿者名」と「投稿内容」な入力必須項目です。'); exit; } $Change_Info=qq|■投稿の修正に成功しました。
|; #print "$edit_lineと$page
"; Change_LOG(); } #Get_Data(); #print "$now"; Print_Head(); Print_Input_Area(); #Print_Rireki(); Print_Rireki_TREE(); Print_Foot(); } #----------------------------------------------------------- #関数部 #----------------------------------------------------------- sub Show_ERR{ #■エラーメッセを出力 local($e_msg)=@_; print <<"EOM"; $title
エラーメッセージ

$e_msg

掲示板プログラムに戻る
EOM } sub Read_LOGS{ #■ログファイル$logfileを読み込む open(FILE,"$log_file"); flock(FILE,2); @Logs=; flock(FILE,8); close(FILE); } sub Write_LOGS{ #■ログファイルに書き込む open(FILE,"+<$log_file"); flock(FILE,2); @Logs=; $num=$Logs[0]+1; #ログ番号のカウントアップ #※文字列の演算は文字列の左数字部分を演算 &Get_Data(); #$nowに現時刻を代入 #$c_password=$password; #パスワード $c_password=&passwd_encode($password); if($edit_line eq ''){ #リプライ用の番号(別途設定) $reply_no=0 }else{ $reply_no=$edit_line } #$guest_img='sample.gif';#投稿者のイメージ(別途設定) #$guest_color='black'; #投稿の文字色(別途設定) if($guest_color eq ''){ $guest_color='#000000'; } $Log_data=$num."\t".$now."\t".$name."\t".$email."\t".$subject."\t".$text."\t".$h_addr."\t".$c_password."\t".$addr."\t".$host."\t".$reply_no."\t".$guest_img."\t".$guest_color."\n"; #新規データ作成 #print "$Log_data
"; #ちゃんと書き込みできてるかテスト #print "$num
"; #print "$Logs[0]"; #二重投稿のチェック $bouble_match=0; if($#Logs<$bouble_count){ #チェックする@Logsの配列番号を決める $until_count=$#Logs; }else{ $until_count=$bouble_count-1; } foreach $_($Logs[0..$until_count]){ #名前と本文が同一の場合 ($w_num,$w_today,$w_name,$w_email,$w_subject,$w_text)=split(/\t/,$_); $bouble_match=1 if(($name eq $w_name)&&($text eq $w_text)); } if($bouble_match eq 0){ #二重投稿がなければそのまま書き込みする unshift(@Logs,$Log_data); #受け取ったデータ並列の先頭に追加 Pop_logs(); #古い投稿の削除 seek(FILE,0,0); print FILE @Logs; #データを上書き truncate(FILE,tell(FILE)); #データの切り詰め flock(FILE,8); close(FILE); } } sub Get_Data{ #■時刻データの取得と整形/関数DATA_WRITE()で使用 #$add=1090; #鯖の時刻補正 @jweek=("日","月","火","水","木","金","土"); ($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime(time+$add); $youbi=$jweek[$wday]; $now = sprintf("%02d/%02d/%02d($youbi) %02d:%02d:%02d",$year-100,$mon+1,$mday,$hour,$min,$sec); #日付時刻の変数 #$now = sprintf("%d.%02d.%02d",$year+1900,$mon+1,$mday); #日付時刻の変数 return $now; } sub Print_Head{ #■HTMLヘッダ部からBODY部の見出し部分まで #見出し設定 $midashi1='掲示板'; $midashi2='書き込みをお願いします。'; $JScript=JS_show_board(); #ヘッダにJSを記述 $CSS=Print_CSS(); print <<"EOM"; $title $JScript $CSS $midashi1
$midashi2
EOM } sub Print_Input_Area{ #■入力フォームエリアの表示 #ボタン設定**************************************************** if($edit_mode eq 'show_relpy'){ $button1=qq||; $button2=qq||; }elsif($edit_mode eq 'show_change'){ $button1=qq||; $button2=qq||; #}elsif($edit_mode eq 'show_delite'){ # $button1=qq||; # $button2=qq||; }else{ $button1=qq||; $button2=qq||; } if($edit_mode eq 'show_relpy'){ #[RE]をクリックしたときにフォームに引用する edit_RE_text(); } #修正モードの時はテキストエリアに修正内容表示($subject,$text)*************** if($edit_mode eq 'show_change'){ chomp($line=$Logs[$Logs[0]-$edit_line]); ($num,$today,$name,$email,$subject,$text,$h_addr,$password,$addr,$host,$reply_no,$guest_img,$guest_color)=(split(/\t/,$line)); $RE_subject=$subject; $RE_text=$text; $RE_text=~s/
/\n/gi; $Change_Info=qq|■以下のフォームの内容を修正をして「修正」ボタンを押してください。|; } #削除モードは削除する対象を表示($subject,$text)****************************** #if($edit_mode eq 'show_delite'){ # chomp($line=$Logs[$Logs[0]-$edit_line]); # ($num,$today,$name,$email,$subject,$text,$h_addr,$password,$addr,$host,$reply_no,$guest_img,$guest_color)=(split(/\t/,$line)); # $RE_subject=$subject; # $RE_text=$text; #} #下のフォームのhiddenフィールドの$modeの値を制御 if($edit_mode eq 'show_change'){ $mode_hidden='change'; }elsif($edit_mode eq 'show_delite'){ $mode_hidden='delite'; }else{ $mode_hidden='write'; } #($mode eq 'show_write')||(↓※いらなそうだから削除) if(($mode eq 'write')||($mode eq '')||($edit_mode eq 'show_change')||($mode eq 'change')){ print <<"EOM"; $Change_Info
投稿者 パスワード(投稿の変更・削除用)
メールアドレス
タイトル 投稿者イメージ $button1 $button2
内容
ホームページ EOM if($guest_img eq ''){ #ゲストイメージ画像を配置 print qq||; }else{ print qq||; } print <<"EOM";
文字色 EOM #テキストの色のラジオボタン foreach $_(@colors){ print ""; print "■  \n"; } print <<"EOM";
EOM } } sub Print_DEL_KAKUNIN{ #■削除確認画面を表示($edit_mode eq 'show_delite') #ボタンの表示 $button1=qq||; $button2=qq||; #削除モードは削除する対象を表示($subject,$text)****************************** if($edit_mode eq 'show_delite'){ chomp($line=$Logs[$Logs[0]-$edit_line]); ($num,$today,$name,$email,$subject,$text,$h_addr,$password,$addr,$host,$reply_no,$guest_img,$guest_color)=(split(/\t/,$line)); $RE_subject=$subject; $RE_text=$text; } $edit_mode='delite'; #モード切替 print <<"EOM";
以下の投稿を削除しますか?

投稿者: $name
メールアドレス: $email
タイトル: $RE_subject  $button1 $button2
ホームページ: $h_addr
投稿内容: $RE_text
EOM } sub Print_Rireki{ #■履歴部分表示 #Read_LOGS(); #@Logsに外部ファイルを格納(※制御部先頭に移動) #ページ制御 $page=1 if($mode eq 'wtite'); #書き込み時は最新履歴表示 $page=1 if($page eq ''); #$pageが空なら最新履歴 / 初回 if(($#Logs+1)%$page_size == 0){ #総ページ数 / 総履歴数は$#Logs+1 $page_total=int(($#Logs+1)/$page_size); #切り上げCielを使えない応急処置 }else{ $page_total=int(($#Logs+1)/$page_size)+1; } $page_start_line=($page-1)*$page_size; #表示を開始する履歴番号 $page_end_line=$page_start_line+$page_size-1; #表示を終了する履歴番号 if($page_end_line>$#Logs){ #表示を終る位置の制御 $page_end_line=$#Logs; } $page_rest=$#Logs-$page_end_line; #残りの履歴数 #次のページへ*************************************************** if($page<$page_total){ #この部分は履歴エリアの一番下で使用 $next_page=$page+1; $next=qq|[次のページへ]|; $rest=" "."あと$page_rest件の書き込みがあります。"; }else{ $next=qq|[次のページへ]|; } #前のページへ if($page>1){ $back_page=$page-1; $back=qq|[前のページへ]|; }else{ $back=qq|[前のページへ]|; } #*************************************************************** foreach $_(@Logs[$page_start_line..$page_end_line]){ #ここで指定した番号の履歴を表示 chomp($_); ($num,$today,$name,$email,$subject,$text,$h_addr,$password,$addr,$host,$reply_no,$guest_img,$guest_color)=split(/\t/,$_); #履歴エリアの整形 $maked_url=&make_url_icon($h_addr,$home_icon); $name=&make_email_link($email,$name); $make_RE=&make_reply(); #記事の修正削除のリンク(暗号化されたPWとクッキーのPWを比較) $change_link=&make_change_link($password,$c_password); $delite_link=&make_delite_link($password,$c_password); #ここから投稿履歴出力******************************* if($num ne ''){ print <<"EOM";
[$num]$subject  $make_RE  投稿者:$name  $today   $maked_url   $change_link   $delite_link
$text

EOM } } print <<"EOM"; #ページ制御部
$page/$page_totalページ   $back $next $rest EOM } sub Print_Foot{ #■HTMLフッタ部分表示 print <<"EOM";
【ホームページに戻る】 【管理人】
EOM } sub make_url_icon{ #■URLに画像リンクを配置 my($h_addr,$home_icon)=@_; if($h_addr ne ''){ return qq| ホームページ|; }else{ return ''; } } sub make_email_link{ #■投稿者名にメールリンクを貼る my($email,$name)=@_; if($email ne ''){ return qq|$name|; }else{ return $name; } } sub make_reply{ #■[RE]を表示 return qq|[RE]|; } sub edit_RE_text{ #■フォームに引用できるように文章を整形 Read_LOGS(); chomp($line=$Logs[$Logs[0]-$edit_line]); #引用する行を取得 ($r_num,$r_today,$r_name,$r_email,$r_subject,$r_text,$r_h_addr,$r_password,$r_addr,$r_host,$r_reply_no,$r_guest_img,$r_guest_color)=split(/\t/,$line); $RE_subject='[RE]'.$r_subject; #タイトルの編集 $RE_text=$r_text; $RE_text=~s/
/\n/gi; #
を\nに変換 $RE_text='>'.$RE_text; #引用符>を先頭に着ける $RE_text=~s/(\n)/$1.'>'/ge; #行の先頭に引用符> $RE_text='['.$edit_line.']番の'.$r_name.'さんの書き込みを引用します'."\n".$RE_text; } sub JS_show_board{ #■HTMLにJavaScriptを記述 for($i=0;$i<($#guest_imgs+1);$i++){ $JS_roop.="Images[$i]=new Image();\n"; $JS_roop.="Images[$i].src=\"$img_dir$guest_imgs[$i]\"\n"; } return qq||; } sub passwd_encode{ #■パスワードを暗号化する local ( $input_pwd ) = @_; local ( @saltset ) = ('a'..'z','A'..'Z','0'..'9','.','/'); #64文字から選ぶ #乱数で$saltを作る(毎回でたらめな2文字の組み合わせ) local ( $salt ) = $saltset[ int( rand @saltset ) ] . $saltset[ int( rand @saltset )]; return crypt( $input_pwd, $salt ); } #sub passwd_verify{ #■パスワードが合っているかチェックする # local ( $input_pwd, $encoded_pwd ) = @_; # #引数(検査する文字列,登録した暗号化されたパスワード) # # if ( $encoded_pwd eq crypt( $input_pwd, $encoded_pwd )) { # return 1; # } else { # return 0; # } #} sub make_change_link{ #■記事修正のアンカーを貼る my($password_f,$password_c)=@_; if(($password_f ne crypt($password_c,$password_f))||($password_c eq '')){ #return ''; return qq|[修正]|; }else{ return qq|[修正]|; } } sub make_delite_link{ #■記事削除のアンカー my($password_f,$password_c)=@_; if(($password_f ne crypt($password_c,$password_f))||($password_c eq '')){ #return ''; return qq|[削除]|; }else{ return qq|[削除]|; } } sub DEL_Log{ #■投稿の削除を行う $num=$edit_line; #フォームから受け取った編集する番号 $delite_log=$Logs[$Logs[0]-$num]; ($del_num,$del_today,$del_name,$del_email,$del_subject,$del_text,$del_h_addr,$del_password,$del_addr,$del_host,$del_reply_no)=(split(/\t/,$delite_log)); $new_del_data=Get_Data(); #削除した時刻 $del_text_color="#999999"; #削除の$textの文字色 $del_password=""; #削除した投稿を[修正]モードで修正されるのを阻止 $delite_log=$num."\t".$del_today."\t".$del_name."\t"."\t".$del_subject."\t"."※削除されました
".$new_del_data."\t"."\t".$del_password."\t".$del_addr."\t".$del_host."\t".$del_reply_no."\t".$guest_imgs_delited."\t".$del_text_color."\n"; $Logs[$Logs[0]-$num]=$delite_log; open(FILE,"+<$log_file"); flock(FILE,2); seek(FILE,0,0); print FILE @Logs; truncate(FILE,tell(FILE)); flock(FILE,8); close(FILE); } sub Change_LOG{ #■投稿の変更を行う $num=$edit_line; $change_log=$Logs[$Logs[0]-$num]; ($change_num,$change_today,$change_name,$change_email,$change_subject,$change_text,$change_h_addr,$change_password,$change_addr,$change_host,$change_reply_no,$change_guest_img,$change_guest_color)=(split(/\t/,$change_log)); $today=Get_Data(); #編集した時刻 $change_password=&passwd_encode($password);#パスワード(フォームより) $reply_no=$change_reply_no; #$guest_img='sample.gif'; #投稿者イメージ(別途設定) #$guest_color='black'; #投稿色の設定(別途設定) if($guest_color eq ""){ $guest_color="#000000"; } $text=~s/\r?\n/
/g; #本文(フォームより)を整形 $change_log=$num."\t".$today."\t".$name."\t".$email."\t".$subject."\t".$text."\t".$h_addr."\t".$change_password."\t".$addr."\t".$host."\t".$reply_no."\t".$guest_img."\t".$guest_color."\n"; $Logs[$Logs[0]-$num]=$change_log; open(FILE,"+<$log_file"); flock(FILE,2); seek(FILE,0,0); print FILE @Logs; truncate(FILE,tell(FILE)); flock(FILE,8); close(FILE); } sub Pop_logs{ #■ログを一定の行数にする foreach($max_log..$#Logs){ #popで配列の最後の要素を削る pop @Logs; } } sub Print_CSS{ #■スタイルシートを出力する return qq||; } #ここからツリー表示部分の関数---------------------------------------------------- sub Print_Rireki_TREE{ #■履歴ツリー部分表示 #Read_LOGS(); #@Logsに外部ファイルを格納(※制御部先頭に移動) #★ツリー構造の取得***************************************** foreach ( @Logs ){ chomp( $_ ); ( $pre, $parent ) = ( split( /\t/, $_ ) )[ 0, 10 ]; if( $parent != '0' ) { if( $child{ $parent } != 0 ) { $brother{ $pre } = $child{ $parent }; } $child{ $parent } = $pre; }else { push( @root, $pre ); } } #ページ制御*********************************************** $page=1 if($mode eq 'wtite'); #書き込み時は最新履歴表示 $page=1 if($page eq ''); #$pageが空なら最新履歴 / 初回 if(($#root+1)%$page_size == 0){ #総ページ数 / 総履歴数は$#root+1 $page_total=int(($#root+1)/$page_size); #切り上げCielを使えない応急処置 }else{ $page_total=int(($#root+1)/$page_size)+1; } $page_start_line=($page-1)*$page_size; #表示を開始する履歴番号 $page_end_line=$page_start_line+$page_size-1; #表示を終了する履歴番号 if($page_end_line>$#root){ #表示を終る位置の制御 $page_end_line=$#root; } $page_rest=$#root-$page_end_line; #残りの履歴数 #次のページへ********************************************* if($page<$page_total){ #この部分は履歴エリアの一番下で使用 $next_page=$page+1; $next=qq|[次のページへ]|; $rest=" "."あと$page_rest件の書き込みがあります。"; }else{ $next=qq|[次のページへ]|; } #前のページへ if($page>1){ $back_page=$page-1; $back=qq|[前のページへ]|; }else{ $back=qq|[前のページへ]|; } #*************************************************************** foreach $_(@root[$page_start_line..$page_end_line]){ #ここで指定した番号の履歴を表示 #chomp($_); #($num,$today,$name,$email,$subject,$text,$h_addr,$password,$addr,$host,$reply_no,$guest_img,$guest_color)=split(/\t/,$_); #履歴エリアの整形 #$maked_url=&make_url_icon($h_addr,$home_icon); #$name=&make_email_link($email,$name); #$make_RE=&make_reply(); #記事の修正削除のリンク(暗号化されたPWとクッキーのPWを比較) #$change_link=&make_change_link($password,$c_password); #$delite_link=&make_delite_link($password,$c_password); #★ここから投稿履歴出力******************************* print_tree_rec($_); recor_child($_); $kaisou--; } print <<"EOM"; #ページ制御部
$page/$page_totalページ   $back $next $rest EOM } sub print_tree_rec{ #■ツリー構造の表示 my($rec_num)=@_; $kaisou++; chomp($line=$Logs[$Logs[0]-$rec_num]); ($num,$today,$name,$email,$subject,$text,$h_addr,$password,$addr,$host,$reply_no,$guest_img,$guest_color)=split(/\t/,$line); #履歴エリアの整形 $maked_url=&make_url_icon($h_addr,$home_icon); $name=&make_email_link($email,$name); $make_RE=&make_reply(); #記事の修正削除のリンク(暗号化されたPWとクッキーのPWを比較) $change_link=&make_change_link($password,$c_password); $delite_link=&make_delite_link($password,$c_password); $indent=($kaisou-1)*40; if(($num ne '')&&($kaisou eq 1)){ print <<"EOM";
[$num]$subject  $make_RE  投稿者:$name  $today   $maked_url   $change_link   $delite_link
$text

EOM } if(($num ne '')&&($kaisou ne 1)){ print <<"EOM"; $indent2
[$num]$subject  $make_RE  投稿者:$name  $today   $maked_url   $change_link   $delite_link
$text

EOM } } sub recor_child() { #■子供を探す #***** 引数(ログ番号)の設定 ***** local( $a ) = @_; if( $child{ $a } != 0 ) { &print_tree_rec( $child{ $a } ); &recor_child( $child{ $a } ); $kaisou--; &recor_brother( $child{ $a } ); } else { return; } } sub recor_brother() {# ■兄弟を探す #***** 引数(ログ番号)の設定 ***** local( $a ) = @_; if( $brother{ $a } != 0 ) { print_tree_rec( $brother{ $a } ); &recor_child( $brother{ $a } ); $kaisou--; &recor_brother( $brother{ $a } ); } return; }