#!/usr/local/bin/perl # アンケートからのご意見ご感想に対する返信(掲示板の応用) # id=hensin.cgi # update. 99.6.1 # 日本語コード変換ライブラリ(v2.0)の指定 # &ReadParse命令で、$in{ }の変数にフォーム入力データが格納される require 'cgi-lib.pl'; require 'jcode.pl'; &ReadParse; # 設置するURLを設定 $reload = 'http://www0.kumagaya.or.jp/cgi-bin/users/chichibu/hensin.cgi'; $bkhmpg = "http://www.kumagaya.or.jp/~chichibu/cgi1.html"; $file = "/dialup/chichibu/cgi-bin/hensin.dat"; # データ確認デバッグモード(通常は$test=""、各画面で変数状態を見たいときは"on") $test=""; # 文字数の制限(日本語はこの半分) $mojisu=1000; # 表示色 $iro="blue"; #################################### # # # メインルーチン(処理の分岐) # # # #################################### # 全体の流れを決定する $page=$in{'page'}; if ($in{'action'} eq 'main') { &main; } elsif ($in{'action'} eq 'kinyu') { &kinyu; } elsif ($in{'action'} eq 'check') { ✓ &kakunin; } elsif ($in{'action'} eq 'update') { &update; } 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 'teisei') {&teisei;&main; } elsif ($in{'action'} eq 'hensin') {&hensin; &main; } elsif ($in{'action'} eq 'nexts') { &nexts; } elsif ($in{'action'} eq 'backs') { &backs; } else { &first; } # なくても良いが最終出口を示す exit; ############################################# # # # データを読む           # # # ############################################# sub read { # データを読み各連想配列に加算する # 1 2 3 # 日付時刻、内容、返信 open(DB,"$file"); flock(DB,2); $j=0; # 配列の初期化 @data=(); while () { chop($_); $bundt = $_; &bunkai; $data[$j]=$_ ; $j++; } # end of while flock(DB,8); close(DB); # データ数 $cnt=@data; # 1件目の日付時刻セット $bundt=$data[0]; &bunkai; $eday=$hizuke1; $etime=$hizuke2; # 最終の日付時刻セット $endno=$cnt-1; $bundt=$data[$endno]; &bunkai; $sday=$hizuke1; $stime=$hizuke2; } # end of read ############################################# # # # 登録データを読む(訂正削除用配列)  # # # ############################################# sub read2 { # データを読み各連想配列に加算する open(DB,"$file"); flock(DB,2); @data=; flock(DB,8); close(DB); # データ数 $cnt=@data; # 配列の初期化 %idxdt=(); # 各レコードを日時をキーにした連想配列にセットする foreach (@data) { # キー部をとる(左から14桁) $idx=substr($_,0,14); # キーを変数名に入れて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 bunkai { ($dt1,$dt2,$dt3) = 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分"; # 内容の改行を元に戻す $dt2 =~ s/&k/\n/g; # 表示用に変換する $naiyo2 = $dt2; $naiyo2 =~ s/\n/
/g; # 返信の改行を元に戻す $dt3 =~ s/&k/\n/g; $naiyo3 = $dt3; $naiyo3 =~ s/\n/
/g; } # end of bunkai ############################################# # # # 最初に処理するルーチン         # # # ############################################# sub first { # 初期値セット $in{'page'}=1; # 表示は明細 $in{'hyoji'}=3; $in{'gyosu'}=10 ; $in{'sortkb'}=0; &main; } # end of first ############################################# # # # メイン処理画面を表示する    # # # ############################################# sub main { # 表示用変数 $page = $in{'page'}; $hyoji = $in{'hyoji'} ; $gyosu = $in{'gyosu'} ; $sortkb = $in{'sortkb'} ; &read; # 昇順にする if ($sortkb == 1) { @data=reverse(@data);} # ページ数計算 if ($hyoji == 2) { $page_max = ($cnt /(2*$gyosu)) + 1;} else { $page_max = ($cnt / $gyosu) + 1;} # 整数部をとりだす ($page_max,$dummy)=split(/\./,$page_max); # 表示出力処理 print "Content-type: text/html\n\n"; print < ご意見・ご感想の返信 EOM print ''; print ''; print ''; print "\n"; print ''; print "\n"; print "\n"; print "\n"; print '
'; print ''."\n"; print 'ご意見・ご感想の返信'."\n"; print '   開始日時終了日時登録件数表示頁最終頁
'; print '
' . "\n"; print '' . "\n"; print '' . "\n"; &hidpara; print '
'; print '
'."\n"; print '
' . "\n"; print '' . "\n"; print '' . "\n"; &hidpara; print '
'. "\n"; print '
'."\n"; print '
' . "\n"; print '' . "\n"; print '
' . "\n"; print '
$sday
$stime
$eday
$etime
$cnt$page$page_max
'."\n"; # 前頁表示 # ボタンを並べる # 上段 print ''; 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 '
  '; print '
' . "\n"; print ''."\n"; print '' . "\n"; print '' . "\n"; ##&hidpara; print '' . "\n"; print '
   '; $selh1="";$selh2="";$selh3=""; if ($hyoji == 1) {$selh1 = "SELECTED";} elsif ($hyoji == 2) {$selh2 = "SELECTED"; } else {$selh3 = "SELECTED"; } print ''. "\n"; print '   '; $sel5="";$sel10="";$sel30="";$sel40="";$sel50=""; if ($gyosu == 5) {$sel5 = "SELECTED";} elsif ($gyosu == 10) {$sel10 = "SELECTED"; } elsif ($gyosu == 30) {$sel30 = "SELECTED"; } elsif ($gyosu == 40) {$sel40 = "SELECTED"; } elsif ($gyosu == 50) {$sel50 = "SELECTED"; } else {$sel20 = "SELECTED"; } print ''. "\n"; print '   
'."\n"; print ''. "\n"; # 該当データが0件の場合 if ($cnt == 0) { print '

'; print '
該当データは0件です、選択内容を変えてご覧ください
'."\n"; return } # end of if # 最初は詳細形式を表示する if ($hyoji == 1) { &disp1; } elsif ($hyoji == 2) { &disp2; } else { &disp3; } } # end of main ################################# # hiddenパラメータ共通項目  # ################################# sub hidpara { print ''."\n"; 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; print ''; print ''."\n"; print ''; print ''."\n"; # 返信 print ''."\n"; print ''."\n"; # 最終データを表示したら抜ける if ($lno >= $cnt) { last } } # end of for print '
日付ご意見等返信
'.$lno.''."\n"; if ($test eq "on") { print '
'.$bundt.''."\n"; } # テスト表示 print '
'.$hizuke1.'
'.$hizuke2.'
'; $act="meisai"; print ''.$naiyo2.''; print '
'."\n"; print '
'.$naiyo3.'
'; print "\n"; } # end of disp3 ########################## #            # #  1列表示ルーチン  # #            # ########################## sub disp1 { 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; print ''; print ''."\n"; print ''."\n"; print ''."\n"; # 返信 print ''."\n"; print ''; # 最終データを表示したら抜ける if ($lno >= $cnt) { last } } # end of for print '
日付ご意見等返信
'.$lno.''.$hizuke.''; $act="meisai"; print ''.$naiyo2.''; print ''.$naiyo3.'
'; print "\n"; } # end of disp1 ########################## #            # #  2列表示ルーチン  # #            # ########################## sub disp2 { print "\n"; print "\n"; # 行数分だけ繰り返す for($i=1; $i<=$gyosu; $i++) { # 1列目はページカウンタ*2*行数+$i $lno=2 * $gyosu * ($page - 1) + $i; $no=$lno-1; # 項目分解処理 $bundt=$data[$no]; &bunkai; print ''; print ''."\n"; $act="meisai"; print ''."\n"; print ''."\n"; print ''."\n"; # 2列目は1列目+行数 $rno=$lno + $gyosu; if ($rno <= $cnt) { $no=$rno-1; # 項目分解処理 $bundt=$data[$no]; &bunkai; print ''."\n"; $act="meisai"; print ''."\n"; print ''."\n"; print ''."\n"; print ''; } # end of if # 最終データを表示したら抜ける if ($lno >= $cnt) { last } } # end of for print '
日付ご意見等返信日付ご意見等返信
'.$lno.''.$hizuke.''; print ''.$naiyo2.''; print ''.$naiyo3.''.$rno.''.$hizuke.''; print ''.$naiyo2.''; print ''.$naiyo3.'
'; print "\n"; } # end of disp2 ############################### # タグの無効化サブルーチン ############################### sub tagck { $ckdt =~ s//>/ig; $ckdt =~ s///ig; $ckdt =~ s/\,//g; } ########################################## # # # 次ページ表示処理         # # # ########################################## sub next { ##$page++; $in{'page'}++; &main; } # end of sub ########################################## # # # 前ページ表示処理         # # # ########################################## sub back { #if ($page > 1) { $page--; } 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 { $pwd1=$in{'pwd1'}; # 登録済みデータを読み配列にセットする if ($pwd1 ne "subetekesu") { &read3; unshift(@data,$value);} else {push(@data,$value);} # 掲示板は先頭から古い順になっているのでそのまま1番目のデータをシフトする $a=@data; if ($a > $max) { $herasu=$a - $max; for ($i=1; $i<=$herasu; $i++) { pop(@data) } } # end of if # ファイル登録 if (!open(WRITE,">$file")) { &error(0); } flock(WRITE,2); print WRITE @data; 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 '

'; if ($test eq "on") { if ($error eq "92") { print "登録パスワード=$dt8,入力パスワード=$pwd1,\n";print '

'; } } # end of if # リロードでもどると入力データが消えてしまうので 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 { # 対象データ $syurui=$in{'syurui'}; &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 "
a@$mno / $cnt
\n"; if ($test eq "on") {print "keyno=$keyno,bundt=$bundt\n" } print '
' . "\n"; # print ''; print '
'; print 'ご意見'; print '
'; print '' . "\n"; print '
'; print '

'; print '
'; print '返信メッセージ'; print '
'; print '' . "\n"; print '' . "\n"; print '
'; print '

'; print '' . "\n"; print ''."\n"; &hidpara; print '' . "\n"; print '
'. "\n"; # 訂正か削除か選択する print ''; print '
'; print '訂正削除なし' . "\n"; print '   '; print '訂正します' . "\n"; print '   '; print '削除します' . "\n"; print '   '; print ''."\n"; print ''."\n"; &hidpara; print '' . "\n"; print '' . "\n"; print '
'."\n"; print ''. "\n"; ############################ # ボタンを並べる #print '
'; print ''; print ''; # 戻る print ''; print ''; # 前データ print ''; print ''; # 次データ print '
'; print '
' . "\n"; print '' . "\n"; &hidpara; print '' . "\n"; print '
'. "\n"; print '
   '; if ($tbno == 0) { print '  '; } else { print '
' . "\n"; print '' . "\n"; print '' . "\n"; &hidpara; print '' . "\n"; print '
'; } # end of if print '
   '; if (($tbno+1) == $cnt) { print '  '; } else { print '
' . "\n"; print '' . "\n"; print '' . "\n"; &hidpara; print '' . "\n"; print '
'. "\n"; } # end of if print '
'."\n"; print ''. "\n"; } # end of meisai ########################################## # # # 次データ表示処理(詳細)     # # # ########################################## sub nexts { $tbno=$in{'tbno'}; $tbno++; &meisai2; } # end of nexts ########################################## # # # 前データ表示処理(詳細)     # # # ########################################## sub backs { $tbno=$in{'tbno'}; if ($tbno > 0) { $tbno--; } &meisai2; } # end of backs ##################### # データ訂正 ##################### sub teisei { # 訂正削除なしの場合 if (($in{'action'} eq 'teisei') && ($in{'syori'} == 0)) { return } # 入力項目チェックへ ✓ # フォーム入力データ &form_data; &read2; # キー $keyno=$in{'keyno'}; # 管理者用強制パスワード if ($pwd1 ne "nopassword") { # 訂正パスワードチェック $bundt=$idxdt{$keyno}; ($dt1,$dt2,$dt3) = split(/\t/,$bundt); } # end of if ######################## # 削除の場合 if (($in{'action'} eq 'teisei') && ($in{'syori'} == 2)) { &sakujo; return } # ここからは訂正選択時処理 # データ訂正 $value = "$keyno\t$namae\t$naiyo\t$dt9\n"; $idxdt{$keyno}=$value; &file_write; } # end of teisei ##################### # データ削除 ##################### sub sakujo { # データ削除 delete $idxdt{$keyno}; &file_write; } # end of sakujo ##################### # 返信処理 ##################### sub hensin { # フォーム入力データ $hensin2=$in{'hensin'}; $hensin2 =~ s/\015\012/\n/g; $hensin2 =~ s/\015/\n/g; $hensin2 =~ s/\n/&k/g; # 文字数チェック if (length($hensin2) > $mojisu) { $hensin2 = substr($hensin2,0,$mojisu); } &read2; # キー $keyno=$in{'keyno'}; $bundt=$idxdt{$keyno}; &bunkai; # 意見の改行変換 $dt2 =~ s/\n/&k/g; # 返信データのみ更新する $value = "$dt1\t$dt2\t$hensin2"; #$value =~ s/\n//g; $value = "$value\n"; $idxdt{$keyno}=$value; &file_write; } # end of hensin ########################## # ファイル登録共通処理 # ########################## 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 ###################