#!/usr/local/bin/perl #サーバによっては上の一文を変更する必要があります。サーバ管理者にお尋ねください。 $ver = 3.50; #バージョン情報 #-----これ以下の著作者表示を変更しないでください----- #[Web Qnaire 2] #(C)narishin,2000-2004 #http://www.narishin.com #このスクリプトはフリーウェアです。 #このスクリプトの設定・設置・運用はスクリプト使用者の責任において行ってください。 #改造・再配布etcは著作者表示を改変しない限り自由です。 #-----ここまで----- #---------------------- #初期設定 #---------------------- require './jcode.pl'; #日本語処理系(このファイルと同じディレクトリにおいてください) $kanji='sjis'; #漢字変換方式(sjis(推奨)かjisかeuc) $script='./qnaire2.cgi'; #スクリプト名(このファイルの名前) $logfile='./data.txt'; #データファイル名(このファイルと同じディレクトリにおいてください) $graphgif='http://'; #グラフ用画像データ(絶対パスで指定) $method='POST'; #メソッド形式(POST(推奨)かGET) $mkazu = 0; #フリーメッセージ表示数(0:非表示) $home='http://'; #ホームページ(帰り先、絶対パスで指定) $mail=''; #管理者メール $pass='0123'; #管理者用パスワード $title='アンケート'; #タイトル $bgcolor='#fffff0'; #背景色 $bgimage='http://'; #背景画像(絶対パスで指定) #説明文(タグも使用可能です) $subtitle=''; $lockkey = 0; #ロック機構 (0:不使用 1:使用) $lockfile = './lock'; #ロックファイル名 #---------------------------------- #メイン処理系 #---------------------------------- &decode; if ($mode eq 'tohyo' || $mode eq 'kekka'){ &tohyo; }elsif($mode eq 'kanri'){ &kanri; }else { &tohyo; } #---------------------------------- #投票内容を今までのものに追加し結果を表示します #---------------------------------- sub tohyo{ &lock if ($lockkey); # ロック開始 open (IN,$logfile) || &error("ログファイルを開けません"); #データファイル読み込み @qset=; #データを一行ごと配列qsetに入れる close (IN); chop(@qset); #qsetの最後の改行を取り除く $lahost=$qset[$qset[0]+3]; $host = $ENV{'REMOTE_HOST'}; $addr = $ENV{'REMOTE_ADDR'}; if ($host eq $addr) { $host = gethostbyaddr(pack('C4',split(/\./,$host)),2) || $addr; } if ($lahost eq $host && $mode eq 'tohyo') {&error("連続投票はできません。

(接続ホストを変えて投票を試してみてください)");} &head; #ヘッダ出力 &jikan(0); #現時間読み込み print "
$title

\n"; if ($home ne 'http://'){ print "ホームへ\n"; } print "
\n"; print "

$subtitle\n"; print "


\n"; if ($mode eq 'tohyo'){ print "投票ありがとうございました。
\n"; print "なお、同一ホストからの連続投票はできませんのでご注意ください。

\n"; } print "[$jikanl]現在の投票状況です。\n"; print "この前の投票は[$qset[$qset[0]+2]]に行われました。\n"; print "
\n"; $qkazu=$qset[0]; $qset[0]="$qset[0]\n"; for ($i=1;$i<=$qkazu;$i++){ #質問ごとの処理 @qtemp=split(/,/,$qset[$i]); #行内データを「,」で分けて配列qtempに格納 $add = $in{"add$i"}; #追加する選択肢内容 $tothyo = 0; #質問別の総票数 $maxhyo = 1; #質問別の最高得票数 for ($j=1;$j<=$qtemp[1];$j++){ #既存の選択肢への処理 ($anstmp[$j],$hyotmp[$j])=split(/=/,$qtemp[$j+3]); $done=0; foreach $x (@ans){ if ("$i/$j" eq $x){ $hyotmp[$j]++,$done=1; #票数の追加 } } if ($add eq $anstmp[$j] ){ $add=''; #追加する選択肢が既存 if ($done == 0 ){ $hyotmp[$j]++; } } if ($hyotmp[$j] > $maxhyo){ #最高得票数の更新 $maxhyo = $hyotmp[$j]; } $qtemp[$j+3]="$anstmp[$j]=$hyotmp[$j]"; #更新データを格納 $tothyo += $hyotmp[$j]; #質問ごと総票数更新 } if ($in{$i} eq 'add' && $add ne ''){ #選択肢追加 $qtemp[$j+3]="$add=1",$tothyo++; $anstmp[$j]=$add,$hyotmp[$j]=1,$qtemp[1]++,$j++; } #票数によるソート表示 if ($qtemp[3] =~ m/sort/){ $hyotmp[0] = 0; #ダミー @sizensu = (); for ($j=0;$j<$qtemp[1];$j++){ $sizensu[$j] = $j + 1 ; } $j = 1; foreach (sort({$hyotmp[$b] <=> $hyotmp[$a]} @sizensu)){ $h_anstmp[$j] = $anstmp[$_]; $h_hyotmp[$j] = $hyotmp[$_]; $h_ansnum[$j] = $_; $j++; } }else{ for ($j=1;$j<=$qtemp[1];$j++){ $h_anstmp[$j] = $anstmp[$j]; $h_hyotmp[$j] = $hyotmp[$j]; $h_ansnum[$j] = $j; } } print "\n

$qtemp[0]"; #質問文の表示 if ($qtemp[3] =~ m/sosu/){ print "\n 投票総数 $tothyo 票"; #投票総数表示 } print "\n"; #結果表示 if ($qtemp[3] =~ m/select/){ $tmptyp = 'radio'; }else{ $tmptyp = $qtemp[3]; $tmptyp =~ s/=sort// , $tmptyp =~ s/=sosu//; } for ($j=1;$j<=$qtemp[1];$j++){ $wari[$j]=0; #票の割合 $width = 0; #グラフ画像表示幅 print "\n"; print ""; if ($qtemp[3] =~ m/radio/ || $qtemp[3] =~ m/select/){ if ($tothyo>0) { $wari[$j]=sprintf("%.1f",$h_hyotmp[$j]*100/$tothyo); } $width = int ( 3 * $wari[$j] ); print ""; }else{ if ($maxhyo > 0){ $width = int(300 * $h_hyotmp[$j]/$maxhyo); } } print "\n"; } print "
"; print ""; print "$h_anstmp[$j]$h_hyotmp[$j] 票$wari[$j] %"; print "
\n\n"; if ($qtemp[2] eq 'yes'){ #選択肢の追加を尋ねる if ($qtemp[3] =~ m/select/){ $tmpadd = 'radio'; }else{ $tmpadd = $qtemp[3]; $tmpadd =~ s/=sort// , $tmpadd =~ s/=sosu//; } print "\n"; print "その他\n"; } push(@qtemp,"\n"); #行末に改行をつける $qset[$i]=join(",",@qtemp); #行データを更新する } #質問ごとの処理の終了 #メッセージの処理 $host = $ENV{'REMOTE_HOST'}; $addr = $ENV{'REMOTE_ADDR'}; if ($host eq $addr) { $host = gethostbyaddr(pack('C4',split(/\./,$host)),2) || $addr; } @tnaiyo = split(/
/,$qset[$qkazu+1],$mkazu+1); if($in{'toko'} ne ''){ #メッセージ更新 unshift (@tnaiyo,"$in{'tname'}/$in{'toko'} [$jikanl][$host]"); } splice (@tnaiyo,$mkazu); $qset[$qkazu+1] = join('
',@tnaiyo); $qset[$qkazu+1] = "$qset[$qkazu+1]\n"; if ($mkazu > 0){ print <<"EOM";

ご意見・ご感想をどうぞ(必須ではありません)
ハンドルネーム
内容 EOM print "

ご意見・ご感想をどうぞ
\n"; print "$qset[$qkazu+1]\n"; #メッセージ表示 } if ($mode eq 'tohyo'){ $qset[$qkazu+2]="$jikanl \n"; #最終投票時間更新 }else{ $qset[$qkazu+2]="$qset[$qkazu+2]\n"; } if ($mode eq 'tohyo'){ $qset[$qkazu+3]="$host\n"; #最終投票ホスト更新 }else{ $qset[$qkazu+3]="$qset[$qkazu+3]\n"; } $qset[$qkazu+4]="$qset[$qkazu+4]\n"; #末データ処理 $qset[$qkazu+5]="$qset[$qkazu+5]\n"; #末データ処理 $qset[$qkazu+6]="$qset[$qkazu+6]\n"; #末データ処理 $qset[$qkazu+7]="$qset[$qkazu+7]\n"; #末データ処理 $qset[$qkazu+8]="$qset[$qkazu+8]\n"; #末データ処理 #データファイル更新 open (OUT,">$logfile") || &error("ログファイルを開けません"); print OUT @qset; close(OUT); &unlock if ($lockkey); # ロック解除 print <<"EOM";



ご協力ありがとうございました。

EOM &foot; #フッタ表示 } #---------------------------------- #管理者用 #---------------------------------- sub kanri{ if ($in{'pass'} ne "$pass") {&error('パスワードが違います');} &jikan(0); &head; print <<"EOM";
管理ページ

アンケート画面へ戻ります

EOM &lock if ($lockkey); # ロック開始 open (IN,$logfile) || &error("ログファイルを開けません"); #データファイル読み込み @qset=; #データを一行ごと配列qsetに入れる close (IN); chop(@qset); #qsetの最後の改行を取り除く print "不測の事態に備えて設定変更の前にデータファイルをバックアップすることをお勧めします。
\n"; print "それぞれの実行ボタンは1回だけクリックしてください。ダブルクリックするとデータが失われる恐れがあります。
\n"; print "こまめに投票ページに戻って設定変更を確認しながら作業を進めてください。\n"; $qkazu=$qset[0]; $qset[0]="$qset[0]\n"; $tocans=0; #表示済み選択肢数 #質問の消去 foreach $x (@delque){ splice(@qset,$x,1); $qkazu--; $qset[0]="$qkazu\n"; } #質問の追加 if ($in{'addque'} ne ''){ $qkazu++; $qset[0]="$qkazu\n"; #質問数の更新 splice(@qset,1+$in{'ajun'},0,"$in{'addque'},0,$in{'aadd'},$in{'rc'},"); } for ($i=1;$i<=$qkazu;$i++){ #質問ごとの処理 @qtemp=split(/,/,$qset[$i]); #行内データを「,」で分けて配列qtempに格納 $add=$in{"add$i"},$tothyo=0; if ($in{'qubunc'} eq $i){ #質問文の更新 $qtemp[0] = $in{'qubun'}; } if ($in{'qtyc'} eq $i){ #回答方法の更新 $qtemp[2] = $in{'aadd'}; $qtemp[3] = $in{'rc'}; if ($in{'sort'} && $qtemp[3] !~ m/sort/){ $qtemp[3] .= '=sort'; #ソート有無の変更 }elsif (!$in{'sort'}){ $qtemp[3] =~ s/=sort//; } if ($in{'sosu'} && $qtemp[3] !~ m/sosu/){ $qtemp[3] .= '=sosu'; #投票総数表示有無の変更 }elsif (!$in{'sort'}){ $qtemp[3] =~ s/=sosu//; } } print "\n


"; print "\n

$qtemp[0]\n"; #質問文の表示 print "

\n"; print "\n"; print "\n"; print "\n"; if ($qtemp[1] == 0){ #この質問に選択肢がない場合 print "\n"; }else{ #この質問の選択肢が残っている場合 print "\n"; print "この質問のすべての選択肢を削除してから行ってください。\n"; } print "
\n\n"; print "
\n"; print "\n"; print "\n"; print "\n"; print "質問文を変更する\n"; print "\n"; print "\n"; print "
\n"; print " ↑この項目はタグ用の\"<\"と\"=\"が使用可\能\です。\n"; print "
\n\n"; print "
\n"; print "\n"; print "\n"; print "\n"; print "回答方法/\表\示方法の変更
\n"; if ($qtemp[3] =~ m/radio/ || $qtemp[3] =~ m/select/){ print "択一(現在の設定)\n"; print "複数回答可
\n"; }else{ print "択一\n"; print "複数回答可(現在の設定)
\n"; } if ($qtemp[2] eq 'yes'){ print "見た人に選択肢の追加を許可する(現在の設定)\n"; print "見た人に選択肢の追加を許可しない
\n"; }else{ print "見た人に選択肢の追加を許可する\n"; print "見た人に選択肢の追加を許可しない(現在の設定)
\n"; } if($qtemp[3] =~ m/sort/){ print "票数の多い順に並び替えて\表\示(現在の設定)\n"; print "管理者による選択肢の追加順に\表\示
\n"; }else{ print "票数の多い順に並び替えて\表\示\n"; print "管理者による選択肢の追加順に\表\示(現在の設定)
\n"; } if ($qtemp[3] =~ m/sosu/){ print "投票総数を\表\示する(現在の設定)\n"; print "投票総数を\表\示しない
\n"; }else{ print "投票総数を\表\示する\n"; print "投票総数を\表\示しない(現在の設定)
\n"; } print "\n"; print "
\n\n"; print "
\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "この質問のすべての票が0に戻ります\n"; print "
\n"; for ($j=1;$j<=$qtemp[1];$j++){ #既存の選択肢への処理 ($anstmp[$j],$hyotmp[$j])=split(/=/,$qtemp[$j+3]); $done=0; if ($in{'qrset'} eq $i){ $hyotmp[$j] = 0; #票数をリセット } if ($add eq $anstmp[$j] ){ $add=''; #追加する選択肢が既存 } $qtemp[$j+3]="$anstmp[$j]=$hyotmp[$j]"; #更新データを格納 $tothyo += $hyotmp[$j]; #質問ごと総票数更新 foreach $x (@del){ if ("$i/$j" eq $x && $chfl == 0){ splice(@qtemp,$j+3,1); #選択肢の除去 $tothyo -= $hyotmp[$j]; $hyotmp[$j]=0; $qtemp[1]--; $j--,$chfl=1; } } } if ($in{$i} eq 'add' && $add ne ''){ #選択肢追加 $qtemp[$j+3]="$add=0"; $anstmp[$j]=$add,$hyotmp[$j]=0,$qtemp[1]++,$j++; } print "\n 投票総数 $tothyo 票"; #投票総数表示 print "\n"; #結果表示 for ($j=1;$j<=$qtemp[1];$j++){ $tocans++; $wari[$j]=0; if ($tothyo>0) { $wari[$j]=sprintf("%.1f",$hyotmp[$j]*100/$tothyo); } $width = int ( 3 * $wari[$j] ); print "\n"; print ""; if ($qtemp[3] =~ m/radio/ || $qtemp[3] =~ m/select/){ print ""; } print "\n"; print "\n"; } print "
$anstmp[$j]$hyotmp[$j] 票$wari[$j] %\n"; print "
\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
\n\n"; print "
\n"; print "\n"; print "\n"; print "新しい選択肢を追加する(既存の選択肢の最後に追加されます)\n"; print "\n"; print "\n"; print "
\n"; print " ↑この項目は管理者ページでの追加のみタグ用の\"<\"が使用可\能\です。ただし\"=\"は使用できません。\n"; print "

\n"; push(@qtemp,"\n"); #行末に改行をつける $qset[$i]=join(",",@qtemp); #行データを更新する } #質問ごとの処理の終了 print "
\n"; print "

[質問を追加する]
"; print "

\n"; print "\n"; print "\n"; print "\n"; print "現在の質問群の\n"; print "に追加する
\n"; print "質問文\n"; print "
\n"; print "択一"; print "複数回答可
\n"; print "見た人に選択肢の追加を許可する\n"; print "見た人に選択肢の追加を許可しない
\n"; print "票数の多い順に並び替えて\表\示\n"; print "管理者による選択肢の追加順に\表\示
\n"; print "投票総数を\表\示する\n"; print "投票総数を\表\示しない
\n"; print "選択肢は管理ページを繰り返して追加してください。
\n"; print "\n"; print "
\n\n"; #メッセージの処理 $host = $ENV{'REMOTE_HOST'}; $addr = $ENV{'REMOTE_ADDR'}; if ($host eq $addr) { $host = gethostbyaddr(pack('C4',split(/\./,$host)),2) || $addr; } @tnaiyo = split(/
/,$qset[$qkazu+1],$mkazu+1); if($in{'toko'} ne ''){ #メッセージ更新 unshift (@tnaiyo,"$in{'tname'}/$in{'toko'} [$jikanl][$host]"); } splice (@tnaiyo,$mkazu); if ($in{'todel'} ne ''){ $tnaiyocp = $tnaiyo[$in{'todel'}-1]; $tnaiyocp =~ tr/<> //d; if ($tnaiyocp eq $in{'todelnai'}){ splice (@tnaiyo,$in{'todel'}-1,1); #投稿内容の削除 }else{ print "新規投稿がありました。確認してください。データ保護のため投稿を削除しません。\n"; } } $tnkazu = @tnaiyo; if ($mkazu > 0){ print "

ご意見・ご感想をどうぞ
\n"; if ($tnkazu == 0){ print "(現在 発言はありません)\n"; } } for ($i=1;$i<=$tnkazu;$i++){ print "

\n"; print "\n"; print "\n"; print "$tnaiyo[$i-1]\n"; #メッセージ表示 print "\n"; print "\n"; $tnaiyocp = $tnaiyo[$i-1]; $tnaiyocp =~ tr/<> //d; print "\n"; print "
\n\n"; } $qset[$qkazu+1] = join('
',@tnaiyo); $qset[$qkazu+1] = "$qset[$qkazu+1]\n"; $qset[$qkazu+2]="$qset[$qkazu+2]\n"; $qset[$qkazu+3]="$qset[$qkazu+3]\n"; #末データ処理 $qset[$qkazu+4]="$qset[$qkazu+4]\n"; #末データ処理 $qset[$qkazu+5]="$qset[$qkazu+5]\n"; #末データ処理 $qset[$qkazu+6]="$qset[$qkazu+6]\n"; #末データ処理 $qset[$qkazu+7]="$qset[$qkazu+7]\n"; #末データ処理 #データファイル更新 open (OUT,">$logfile") || &error("ログファイルを開けません"); print OUT @qset; close(OUT); &unlock if ($lockkey); # ロック解除 &foot; } #---------------------------------- #入力情報の解析 #---------------------------------- sub decode{ if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } open (IN,"$logfile") || &error("ログファイルを開けません"); @qset=; close (IN); chop($qset[0]); for($i=1;$i<=$qset[0];$i++){ #解答チェックのための配列 $input[$i] = 0; $addc[$i] = 0; } @pairs = split(/&/, $buffer); #入力データごとに分ける foreach $pair (@pairs) { ($name,$value) = split(/=/, $pair); #nameとvalueに分ける $value =~ tr/+/ /d; #空白変換 $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ tr/\n/ /d; #改行拒否 $value =~ s/,/‚/g; #「,」拒否 if ($in{'k_mode'} ne 'bunhen'){$value =~ s/=/=/g;}#「=」拒否 if ($in{'mode'} ne 'kanri'){$value =~ s/ $qset[0]){ #回答しようとした質問がすでに削除済み &error('回答しようとした質問が削除されています。確認してください。'); } if ($name eq 'del'){ push (@del,$value); #選択肢の削除 } if ($name eq 'delque'){ if ($value eq 'muko'){ &error('消去したい質問の選択肢をすべて削除してから実行してください。

(既にすべての選択肢が削除されている場合、1回 票数リセットを行ってみてください。)'); }else{ push (@delque,$value); #質問の消去 } } } if ($in{'mode'} eq 'tohyo'){ #回答情報の不備をチェック for ($i=1;$i<=$qset[0];$i++){ if ($input[$i] != 1){ &error("$i 番目の質問が未解答です"); } if ($addc[$i] == 1 && $in{"add$i"} eq ''){ &error("$i 番目の質問の選択肢に追加したい内容が書かれていません"); } } if ($in{'tname'} eq '' && $in{'toko'} ne ''){ &error('メッセージにお名前がありません'); } } if ($in{'mode'} eq 'kanri'){ #回答情報の不備をチェック for ($i=1;$i<=$qset[0];$i++){ if ($addc[$i] == 1 && $in{"add$i"} eq ''){ &error("$i 番目の質問の選択肢に追加したい内容が書かれていません"); } } if ($in{'k_mode'} eq 'bunadd' && $in{'addque'} eq ''){ &error("追加する質問文に内容がありません"); } } $mode = $in{'mode'}; } #---------------------------------- #時間読み込み #---------------------------------- sub jikan{ #更新履歴用 ($sec,$min,$hour,$mday,$mon,$year,) = localtime; $mon++; $mon = sprintf("%.2d",$mon); $mday = sprintf("%.2d",$mday); $hour = sprintf("%.2d",$hour); $min = sprintf("%.2d",$min); $sec = sprintf("%.2d",$sec); $year += 1900; $jikanl = "$year/$mon/$mday $hour:$min:$sec"; } #---------------------------------- #ヘッダ表示 #---------------------------------- sub head{ print "Content-type: text/html\n"; print "\n"; print <<"EOM"; $title EOM } #---------------------------------- #フッタ表示 #---------------------------------- sub foot{ print "
\n"; if ($mail ne ''){ print "

動作に不具合がありましたらお手数ですが\n"; print "こちらまでお知らせください。\n"; } print <<"EOM";

Web Qnaire 2
EOM exit; } #---------------------------------- # ロック処理 #---------------------------------- sub lock { local($retry, $mtime); # 1分以上古いロックは削除する if (-e $lockfile) { ($mtime) = (stat($lockfile))[9]; if ($mtime < time - 60) { &unlock; } } # ロック処理 $retry=5; while (!mkdir($lockfile, 0755)) { if (--$retry <= 0) { &error('LOCK is BUSY'); } sleep(1); } $lockflag=1; } #---------------------------------- # ロック解除 #---------------------------------- sub unlock { rmdir($lockfile); $lockflag=0; } #---------------------------------- #エラー処理 #---------------------------------- sub error{ &unlock if ($lockflag); # ロック解除 &jikan(0); print "Content-type: text/html\n"; print "\n"; print <<"EOM"; $title
エラーが発生しました。

$_[0]

戻ります

アンケート画面へ戻ります

EOM &foot; }