#!/usr/local/bin/perl # 掲示板2(フレームを利用したパターン)右画面 # id=bbs2.cgi # update. 01.9.16 # 使用上の注意・・・漢字コードの変換が不完全ですので文字化けするおそれがあります。 #          そのつもりでお使い下さい。 # 日本語コード変換ライブラリ(v2.0)の指定 # &ReadParse命令で、$in{ }の変数にフォーム入力データが格納される require 'cgi-lib.pl'; require 'jcode.pl'; &ReadParse; # 設置するURLを設定 $reload = 'http://www0.kumagaya.or.jp/cgi-bin/users/chichibu/bbs2.cgi'; $file = "/dialup/chichibu/cgi-bin/bbs2.dat"; $sendmail = '/usr/lib/sendmail'; # 掲示板へ記入したら管理者へメール通知するならON $send="on"; # メールの送り先 $myaddress = 'chichibu@po.kumagaya.or.jp'; # データ確認デバッグモード(通常は$test=""、各画面で変数状態を見たいときは"on") $test=""; # 最大登録数 $max=200; # メッセージの文字数制限(この値の半分が漢字数) $mojisu = 200; # 表示期間の設定(設定した日数後のファイル更新時に消去します、消去しない場合は0) $syokyo=7; # 1週間後 # 1画面表示件数 $gyosu=10 ; #################################### # # # メインルーチン(処理の分岐) # # # #################################### # 消去日計算 ($byo,$fun,$ji,$dd,$mm,$yy,$yobi) = localtime(time); $mm++; # 2桁化 $mm = sprintf("%.2d",$mm); $dd = sprintf("%.2d",$dd); # 西暦4桁処理 if ($yy < 70) { $yy = $yy + 2000;} else { $yy = $yy + 1900;} # 本日 $ymd=$yy.$mm.$dd; $page=$in{'page'}; $syurui=$in{'syurui'}; # 最初に渡された状態セーブ $syurui_sv=$syurui; # 該当データを調べる if ($syurui ne "all") { &read4 } # 全体の流れを決定する if ($in{'action'} eq 'main') { &main; } elsif ($in{'action'} eq 'kinyu') { &kinyu; } elsif ($in{'action'} eq 'check') { ✓ &main; } elsif ($in{'action'} eq 'meisai') { &meisai; } elsif ($in{'action'} eq 'next') { &next; } elsif ($in{'action'} eq 'back') { &back; } elsif ($in{'action'} eq 'narabi') { &narabi; } # メール送信画面 elsif ($in{'action'} eq 'email') { &email; } # 詳細表示画面 elsif ($in{'action'} eq 'teisei') {&teisei;&main; } else { &first; } # なくても良いが最終出口を示す exit; ############################################# # # # データを読む           # # # ############################################# sub read { # データを読み各連想配列に加算する # 1 2 3 4   5   6 # 日付時刻、宛先、内容、差出人、消去日、訂正用パスワード $j=0; # 配列の初期化 @data=(); open(DB,"$file"); flock(DB,2); while () { ($dt1,$dt2,$dt3,$dt4,$dt5,$dt6) = split(/\t/,$_); # とりあえずキーがないデータを表示しないため if ($dt1 ne "") { # 表示期限チェック if ($dt5 > 0 && $dt5 >= $ymd) { # 9は全部、他は指定分類のみ、指定なしも全件 if ($syurui eq "all") { $data[$j]=$_ ;$j++} elsif ($syurui eq $dt2) { $data[$j]=$_ ;$j++} } # end of if } # とりあえずここまで } # end of while flock(DB,8); close(DB); # データ数 $cnt=@data; } # end of read ############################################# # # # 登録データを読む(訂正削除用配列)  # # # ############################################# sub read2 { # データを読み各連想配列に加算する open(DB,"$file"); flock(DB,2); @data=; flock(DB,8); close(DB); # データ数 $cnt=@data; # 配列の初期化 %idxdt=(); # 各レコードを日時をキーにした連想配列にセットする foreach (@data) { ($idx,$dt2,$dt3,$dt4,$dt5,$dt6) = split(/\t/,$_); # キーを変数名に入れて1レコード全体をセットする $idxdt{$idx} = $_; } # end of foreach } # end of read2 ############################################# # # # データを読む(全件)          # # # ############################################# sub read3 { open(DB,"$file"); flock(DB,2); @data=; flock(DB,8); close(DB); } # end of read3 ############################################# # # アンカータグで渡されたキーデータから該当内容を調べる   # ############################################# sub read4 { open(DB,"$file"); flock(DB,2); while () { ($dt1,$dt2,$dt3,$dt4,$dt5,$dt6) = split(/\t/,$_); # 指定レコードキーがあったらそのレコードの宛先をセットする if ($syurui == $dt1) { $syurui=$dt2 ;last ; } } # end of while flock(DB,8); close(DB); } # end of read4 ######################## #            # # 項目分解ルーチン   # #            # ######################## sub bunkai { ($dt1,$dt2,$dt3,$dt4,$dt5,$dt6) = split(/\t/,$bundt); # 日付時刻分解 $yy=substr($dt1,0,4); $mm=substr($dt1,4,2); $dd=substr($dt1,6,2); $ji=substr($dt1,8,2); $fun=substr($dt1,10,2); $byo=substr($dt1,12,2); $nichiji=$yy.$mm.$dd.$ji.$fun.$byo; $hizuke="$yy年$mm月$dd日$ji時$fun分"; $hizuke1="$yy年$mm月$dd日"; $hizuke2="$ji時$fun分"; # 番号 # 内容の改行を元に戻す $dt3 =~ s/&k/\n/g; # 表示用に変換する $naiyo2 = $dt3; $naiyo2 =~ s/\n/
/g; } # end of bunkai ############################################# # # # 最初に処理するルーチン         # # # ############################################# sub first { print "Content-type: text/html\n\n"; print < 掲示板2 EOM print '

'; print '
左側から表示させる内容を選択してください
'."\n"; print '

'."\n"; $page=1; print '
' . "\n"; print '' . "\n"; print '' . "\n"; &hidpara; print '
'; print ''. "\n"; } # end of first ############################################# # # # メイン処理画面を表示する    # # # ############################################# sub main { # 表示用変数 $page = $in{'page'}; $sortkb = $in{'sortkb'} ; &read; # 昇順にする if ($sortkb == 1) { @data=reverse(@data);} # ページ数計算 $page_max = (($cnt-1) / $gyosu) + 1; # 整数部をとりだす ($page_max,$dummy)=split(/\./,$page_max); # 表示出力処理 print "Content-type: text/html\n\n"; print < 掲示板2 EOM print ''; print ''; print ''; print "\n"; print ''; if ($syurui eq "all") { $sitei="全件" } else { $sitei=$syurui } print "\n"; print "\n"; print "\n"; print '
'; print ''."\n"; print '掲示板2'."\n"; print '指定データ該当件数表示頁最終頁
'; print '
' . "\n"; print '' . "\n"; print '' . "\n"; &hidpara; print '
'; print '
$sitei$cnt$page$page_max
'."\n"; # 前頁表示 # ボタンを並べる # 上段 print ''; print ''; # 表示順序 print ''; print ''; # 前頁表示 print ''; print ''; # 次頁表示 print ''; print ''; print '
'; print '
' . "\n"; print '' . "\n"; &hidpara; if ($sortkb == 0) { $sortkbn = "日付の古いものを先に"; } else { $sortkbn = "日付の新しいものを先に"; } print '' . "\n"; print '
'. "\n"; print '
   '; if ($page == 1) { print ' '; } else { print '
' . "\n"; print '' . "\n"; &hidpara; print '' . "\n"; print '
'; } # end of if print '
  '; if ($page == $page_max) { print ' '; } else { print '
' . "\n"; print '' . "\n"; &hidpara; print '' . "\n"; print '
'. "\n"; } # end of if print '
  
'."\n"; print ''. "\n"; # 該当データが0件の場合 if ($cnt == 0) { print '

'; print '
該当データは0件です、選択内容を変えてご覧ください
'."\n"; return } # end of if # 最初は詳細形式を表示する &disp3; } # end of main ################################# # hiddenパラメータ共通項目  # ################################# sub hidpara { print ''."\n"; print '' . "\n"; print '' . "\n"; } # end of hidpara ########################## #            # #  詳細表示ルーチン  # #            # ########################## sub disp3 { print "\n"; print "\n"; # 行数分だけ繰り返す for($i=1; $i<=$gyosu; $i++) { #print ''; # 1列目はページカウンタ*行数+$i $lno=$gyosu * ($page - 1) + $i; $no=$lno-1; # 項目分解処理 $bundt=$data[$no]; &bunkai; # 分類別色 $iro=$buncol[$bunrui]; print ''; print ''."\n"; print ''; print ''; print ''."\n"; print ''."\n"; print ''."\n"; #print ''."\n"; #print ''."\n"; #print ''."\n"; print ''."\n"; # 最終データを表示したら抜ける if ($lno >= $cnt) { last } } # end of for print '
宛先日付内 容差出人
'.$lno.''."\n"; if ($test eq "on") { print '
'.$bundt.''."\n"; } # テスト表示 print '
'.$dt2.''.$hizuke1.'
'.$hizuke2.'
'; $act="meisai"; print ''.$naiyo2.''; print '
'."\n"; print '
'.$dt4.''.$dt5.''.$dt6.'
'; print "\n"; } # end of disp3 ############################################# # # # 掲示板新規記入処理          # # # ############################################# sub kinyu { # 消去日が設定してある場合 if ($syokyo > 0) { # 消去日計算 $syokyobyo = $syokyo * 60 * 60 * 24; ($byo,$fun,$ji,$dd,$mm,$yy,$yobi) = localtime(time + $syokyobyo); $mm++; # 2桁化 $mm = sprintf("%.2d",$mm); $dd = sprintf("%.2d",$dd); $ji = sprintf("%.2d",$ji); $fun = sprintf("%.2d",$fun); $byo = sprintf("%.2d",$byo); # 西暦4桁処理 if ($yy < 70) { $yy = $yy + 2000;} else { $yy = $yy + 1900;} # 消去日 $symd=$yy.$mm.$dd; } # end of if else { $symd=0 } # end of else print "Content-type: text/html\n\n"; print < 掲示板への記入

掲示板への記入

EOM # 外側の飾り線(画面の設定によってはわくとして表示しないことがある) print ''; print ''; print '' . "\n"; print '' . "\n"; # 左画面から指定された宛先があれば表示させる if ($syurui eq "all") { $atesaki = "" } else { $atesaki = $syurui } print '宛先 
'."\n"; print '
'; print 'メッセージをどうぞ(漢字の場合100文字以内)'; print '
'; print '' . "\n"; print '

'; print '差出人 ' . "\n"; print '

'; print ''; print '登録後にあなたが訂正削除する場合に必要。未設定時は訂正削除不可'; print ''; print '
'; print '訂正削除パスワード ' . "\n"; print '

'; print ''; print "表示期限は本日より $syokyo日間です、要変更の場合は訂正して下さい\n"; print '
'; print '
'; print '表示期限 ' . "\n"; print '
'; print '
'; print ''; # 表示順序 print ''; print ''; print ''; print ''; print '
'; print '' . "\n"; print '  '; print '' . "\n"; # 登録日時セット ($byo,$fun,$ji,$dd,$mm,$yy,$yobi) = localtime; $mm++; # 2桁化 $mm = sprintf("%.2d",$mm); $dd = sprintf("%.2d",$dd); $ji = sprintf("%.2d",$ji); $fun = sprintf("%.2d",$fun); $byo = sprintf("%.2d",$byo); # 西暦4桁処理 if ($yy < 70) { $yy = $yy + 2000;} else { $yy = $yy + 1900;} # 登録日時 $nichiji=$yy.$mm.$dd.$ji.$fun.$byo; # ここで同時刻に登録しようとした場合を考えてキーをユニーク(唯一)にするため # 日時の後に4桁のランダム数字を足す(これでも同一になった場合は訂正時1つのデータ消滅する) srand; $a=rand; $no4=substr($a,index($a,".")+1,4); if ($no4 == 0) { $no4 = "0000"; } $nichiji.=$no4; print '' . "\n"; # 共通データ渡し $syurui_sv=$nichiji; &hidpara; print ''. "\n"; print '  '; # 戻る print '
' . "\n"; print '' . "\n"; print '' . "\n"; # 最初の画面から来たときは何も指定データがないから if ($syurui eq "") { $syurui="all" } $syurui_sv=$syurui; &hidpara; print '
'."\n"; print ''. "\n"; # 外側の飾り線 print ''; print ''. "\n"; } # end of kinyu ########################################## # # # 入力されたデータのチェックルーチン # # # ########################################## sub check { &form_data; # 宛名がない場合 if ($namae eq "" ) { &error(2); } # 差出人がない場合 if ($sasidasi eq "" ) { &error(3); } # チェック通過、更新へ &update; $syurui=$namae; # 管理者へメール送信 if ($send eq "on") { &mymail } } # end of check ############################################# # # # 管理者へのメール送信ルーチン     # # # ############################################# sub mymail { # 改行コードを戻す $naiyo =~ s/&k/\n/g; $message = < 1) { $msg=$msg.$_."\n"; } # end of if } # end of foreach $naiyo=$msg; $naiyo=~ s/\015\012/\n/g; $naiyo=~ s/\015/\n/g; $naiyo =~ s/\n/&k/g; # 文字数チェック if (length($naiyo) > $mojisu) { $naiyo = substr($naiyo,0,$mojisu); } $sasidasi=$in{'sasidasi'}; $pwd1=$in{'pwd1'}; $symd=$in{'symd'}; # タグの無効化 $ckdt=$namae ; &tagck ; $namae=$ckdt; # 宛先をセットする $syurui=$namae; $ckdt=$naiyo ; &tagck ; $naiyo=$ckdt; $ckdt=$sasidasi ; &tagck ; $sasidasi=$ckdt; $ckdt=$pwd1 ; &tagck ; $pwd1=$ckdt; $ckdt=$symd ; &tagck ; $symd=$ckdt; } # end of form_data ############################### # タグの無効化サブルーチン ############################### sub tagck { $ckdt =~ s//>/ig; $ckdt =~ s///ig; $ckdt =~ s/\,//g; } ########################################## # # # 次ページ表示処理         # # # ########################################## sub next { $in{'page'}++; &main; } # end of sub ########################################## # # # 前ページ表示処理         # # # ########################################## sub back { if ($page > 1) { $in{'page'}--; } &main; } # end of sub ########################################## # # # 表示順序の変更指示        # # # ########################################## sub narabi { if ($in{'sortkb'} == 0) { $in{'sortkb'} = 1; } else { $in{'sortkb'} = 0; } &main; } # end of sub ##################### # ファイル登録 ##################### sub update { # 1 2 3 4   5   6 # 日付時刻、宛先、内容、差出人、消去日、訂正用パスワード $value = "$nichiji\t$namae\t$naiyo\t$sasidasi\t$symd\t$pwd1\n"; $pwd1=$in{'pwd1'}; # 登録済みデータを読み配列にセットする if ($pwd1 ne "subetekesu") { &read3; unshift(@data,$value);} else {push(@data,$value);} # 表示期限を過ぎたデータを消す %new=(); foreach(@data) { ($dt1,$dt2,$dt3,$dt4,$dt5,$dt6) = split(/\t/,$_); # 消去日が本日を過ぎていたら除外する if ($dt5 == 0 || $dt5 >= $ymd) { push(@new,$_);} } # end of foreach # 掲示板は先頭から古い順になっているのでそのまま1番目のデータをシフトする $a=@new; if ($a > $max) { $herasu=$a - $max; for ($i=1; $i<=$herasu; $i++) { pop(@new) } } # end of if # ファイル登録 if (!open(WRITE,">$file")) { &error(0); } flock(WRITE,2); print WRITE @new; flock(WRITE,8); close (WRITE); } # end of update ############################################# # # # チェックエラー表示画面ルーチン    # # # ############################################# sub error { # &error(xx); で呼び出されたルーチンは、()内の数字が $error に代入される。 $error = $_[0]; if ($error eq "0") { $error_msg = 'ファイルがない、またはOPENできない。'; } elsif ($error eq "2") { $error_msg = '宛名がありません'; } elsif ($error eq "3") { $error_msg = '差出人は必ず入力してください'; } elsif ($error eq "91") { $error_msg = '訂正パスワードが最初の登録時入力してありませんので、訂正/削除はできません。'; } elsif ($error eq "92") { $error_msg = '訂正パスワードが最初の登録時のものと不一致のため、訂正/削除はできません。'; } print "Content-type: text/html\n\n"; print '掲示板' . "\n"; print '' . "\n"; print '

掲示板の入力で下記のエラーが発生しました

' . "\n"; print '

'; print "$error_msg\n"; # リロードでもどると入力データが消えてしまうので print 'ブラウザ画面の戻るをクリックする'."\n";; print '' . "\n"; # サブルーチンからプログラムを抜けるので exit; } ############################################# # # # 明細データの訂正・削除ルーチン    # # # ############################################# sub meisai { &read2; # キー $keyno=$in{'keyno'}; # 配列番号(次前データ移動用) $tbno=$in{'tbno'}; # 実配列番号は−1 $tbno--; # 項目分解処理 $bundt=$idxdt{$keyno}; &bunkai; &meisai_display; } # end of meisai ############################################# # # # 明細データの訂正・削除ルーチン    # # (次前データ処理用) # ############################################# sub meisai2 { &read; # 項目分解処理 $bundt=$data[$tbno]; &bunkai; # キー $keyno=$dt1; &meisai_display; } # end of meisai2 ############################################# # # # 明細データの共通表示ルーチン     # # # ############################################# sub meisai_display { # 明細表示データbヘ配列a{1 $mno=$tbno+1; print "Content-type: text/html\n\n"; print < 掲示板の詳細

掲示板の詳細

EOM print '
' . "\n"; # 外側の飾り線 print ''; print ''; print '宛先 
' . "\n"; print '
'; print 'メッセージをどうぞ'; print '
'; print '' . "\n"; print '

'; print '差出人 
' . "\n"; print '
'; print '表示期限 
' . "\n"; print '
'; # パスワードが設定してあれば変更可能 # 最終項目なので改行コードがあるのでカットして比較する $dt6=~s/\n//g; if ($dt6 ne "") { print '訂正削除パスワード ' . "\n"; print '
'; print ''; print '*訂正又は削除する場合に必要です。未設定時は訂正削除不可'; print ''; print '
'; # 訂正か削除か選択する print '
'; print '
'; print '訂正削除なし' . "\n"; print '   '; print '訂正します' . "\n"; print '   '; print '削除します' . "\n"; print '   '; print ''."\n"; print ''."\n"; $syurui_sv=$dt1; &hidpara; print '' . "\n"; print '
'."\n"; print '
'. "\n"; print '
'; # キーの確認表示 if ($test eq "on") { print "($keyno)\n"; } } # end of if ############################ # 戻る print '
' . "\n"; print '' . "\n"; $syurui_sv=$dt1; &hidpara; print '' . "\n"; print '
'. "\n"; print '
'; # 外側の飾り線 print ''; print ''. "\n"; } # end of meisai ##################### # データ訂正 ##################### sub teisei { # 訂正削除なしの場合 if (($in{'action'} eq 'teisei') && ($in{'syori'} == 0)) { return } # 入力項目チェック # フォーム入力データ &form_data; # 宛名がない場合 if ($namae eq "" ) { &error(2); } # 差出人がない場合 if ($sasidasi eq "" ) { &error(3); } # チェック通過、更新へ $syurui=$namae; # 管理者へメール送信 if ($send eq "on") { &mymail } &read2; # キー $keyno=$in{'keyno'}; # 管理者用強制パスワード if ($pwd1 ne "nopassword") { # 訂正パスワードチェック $bundt=$idxdt{$keyno}; ($dt1,$dt2,$dt3,$dt4,$dt5,$dt6) = split(/\t/,$bundt); #登録パスワードの改行コードをカットしたものと比較する (98.7.11) $pck=$dt6; $pck=~s/\n//g; if ($pck eq "") { &error(91) } if ($pck ne $pwd1) { &error(92) } } # end of if ######################## # 削除の場合 if (($in{'action'} eq 'teisei') && ($in{'syori'} == 2)) { &sakujo; return } # ここからは訂正選択時処理 # データ訂正 # 1 2 3 4   5   6 # 日付時刻、宛先、内容、差出人、消去日、訂正用パスワード $value = "$keyno\t$namae\t$naiyo\t$sasidasi\t$symd\t$pwd1\n"; $idxdt{$keyno}=$value; &file_write; } # end of teisei ##################### # データ削除 ##################### sub sakujo { # データ削除 delete $idxdt{$keyno}; &file_write; } # end of sakujo ########################## # ファイル登録共通処理 # ########################## sub file_write { # 登録用配列にデータセット %new=(); # 配列データを降順にソートする(keysでは登録順に値が返されるとは限らないため) @data=sort by_date keys(%idxdt); foreach (@data){ # 通常では発生しないが開発途中での空のデータを除く(10は適当) if (length($idxdt{$_}) > 10) { push(@new,$idxdt{$_});} } # end of foreach # ファイル登録 if (!open(WRITE,">$file")) { &error(0); } flock(WRITE,2); print WRITE @new; flock(WRITE,8); close (WRITE); } # end of write #################################### # # # キー(日付)を降順ソートする  # # # #################################### sub by_date { $b cmp $a } ################ end of script ###################