#!/usr/local/bin/perl
#---------------------------#
# 100の質問回答&表示CGI Ver.0.12
# Script by みさお(http://www.nmt.ne.jp/~misao/)
# 2002/4/7作成 2004/3/6最終更新
#---------------------------#
#------------初期設定-----------------
# 日本語コードjcode.plを呼び出す
require 'jcode.pl';
#データファイル名
$questionfile = "100ques.dat"; #質問ファイル
$answerfile = "100ans.dat"; #回答ファイル
#管理用パスワード
$password = "master";
#管理人名
$kanri = "管理人";
#管理人連絡先
$email = "xxx\@xxx.ne.jp";
#ページタイトル
$title = "ネットサーファーへの50の質問";
#HOME
$home = "index.html";
#BODYタグ
$body = '
';
$qnum = 50; #質問数
$def=10; #一覧ページに表示する回答者数
$color1 = "#f0f0ff"; #質問の背景色
$color2 = "#ffffff"; #答えの背景色
$howtotaghtml = "howtotag.html"; #タグの使い方説明ページ
#CGIスクリプト名
$cgi = "100qa.cgi";
#ロックディレクトリ
$lockdir = "100qadir";
#--------初期設定は以上。htmlのわかる人はファイル中程をご覧下さい。
#回答送信後表示されるページおよび回答一覧表示ページに書き加えることができます。
#ファイルの下の方にはスタイルシートを記述する部分があります。
#------------
&decode;
&lock_check;
&file_lock;
&check_input;
&questionwrite;
&rewrite_datafile;
&delete_datafile;
&write_datafile;
&form_view;
&henkou_ok;
&thanks_view;
&list_view;
&answer_view;
&ans_view;
&ichiran;
&rewriteform_view;
&question_admin;
&unlock;
exit;
#-------------
sub decode{
if ($ENV{'REQUEST_METHOD'} eq "POST") {
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}
else {
$buffer = $ENV{'QUERY_STRING'};
}
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($vn, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/&/&/g;
$value =~ s/</g;
$value =~ s/>/>/g;
$value =~ s/\t//g;
$value =~ s/\cM//g;
$value =~ s/\r\n/\n/g;
$value =~ s/\r/\n/g;
$value =~ s/\n/
/g;
&jcode'convert(*value, sjis);
$value;
$FORM{$vn} = $value;
}
$flag=0;$adminflag=0;
}
sub lock_check{
if(-C "$lockdir">0.0004){ &unlock; }
}
sub file_lock{
$lockflag=0;
if (mkdir($lockdir, 0755)) {return;}
for ($i = 0; $i <= 5; $i++) {
if (mkdir($lockdir, 0755)) {
$lockflag=1;
last;
} else {
sleep(1);
}
}
if ($lockflag==0) {
if(-e "$lockdir"){
&error(0,"他の方が使用中です。もう少し待ってからお願いします。
いつまでもこのメッセージが表\示されるようなら、
何らかのアクシデントで、ロックがかかったままの状態になっていると思われます。
$kanriに連絡してください。
");
}
else {&error(1,"ロックディレクトリを作成できません。
CGIの入っているディレクトリがディレクトリの作成を許可するパーミッションでは
ないのが原因だと思います。ディレクトリのパーミッションを変更してください。");
}
}
$SIG{'TERM'} = $SIG{'PIPE'} = $SIG{'HUP'} = "sigexit";
sub sigexit { rmdir($lockdir); exit(1); }
}
sub check_input{
($FORM{'mode'} eq "touroku") || return;
($FORM{'name'}) || &error(0,"お名前の入力をお願いします。");
($FORM{'pass'}) || &error(0,"パスワードの入力をお願いします。訂正・削除の際に必要です。");
&getdata_a;
&get_username;
@answers = split(/\t/,$datas[$#datas]);
(($answers[0] eq $FORM{'name'}) && ($username eq $answers[1]) && &solve_pass($FORM{'pass'},$answers[3])) && &error(0,"同じ内容が既に送信されています。");
$pass = &crypt_pass($FORM{'pass'});
$line = "$FORM{'name'}\t$username\t$^T\t$pass";
for($i=0;$i<$qnum;$i++){
$FORM{"q_$i"} = &tagok($FORM{"q_$i"});
$line .="\t$FORM{\"q_$i\"}";
}
$line .= "\n";
push(@datas,$line);
$flag=1;
}
sub questionwrite{
($FORM{'mode'} eq "questionwrite") || return;
($FORM{'pass'} eq $password) || &error(0,"管理用パスワードが違います。");
for($i=0;$i<$qnum;$i++){
$FORM{"$i"} = &tagok($FORM{"$i"});
push(@req,"$FORM{\"$i\"}\n");
}
@questions=@req;
open (LINES,">$questionfile") || &error(1, "質問ファイルが開けないので、記録できません。");
eval 'flock(LINES,2);';
seek (LINES,0,0);
print LINES (@questions);
eval 'flock(LINES,8);';
close (LINES);
$adminflag=1;
}
sub rewrite_datafile{
(($FORM{'mode'} eq "henkou")||($FORM{'mode'} eq "delete")) || return;
($FORM{'who'} eq "") && &error(1,"誰の回答を訂正/削除しますか?指定がありません。");
&getdata_a;
for ($k=0;$k$answerfile") || &error(1, "記録ファイルが開けないので、記録できません。");
eval 'flock(LINES,2);';
seek (LINES,0,0);
print LINES (@datas);
eval 'flock(LINES,8);';
close (LINES);
}
sub form_view{
($FORM{'mode'} eq "form") || return;
&getdata_q;
&html_header;
print <<"_HTML_";
$title
お疲れさまでした〜。
_HTML_
&html_footer;
}
sub henkou_ok{
(($FORM{'mode'} eq "henkou") || ($FORM{'mode'} eq "delete") || ($FORM{'mode'} eq "del") || ($FORM{'mode'} eq "questionwrite")) || return;
&html_header;
print "";
(($FORM{'mode'} eq "henkou") && ($flag==1))&& print "変更完了。";
(($FORM{'mode'} eq "delete") && ($flag==1))&& print "削除完了。";
(($FORM{'mode'} eq "del") && ($flag==1))&& print "削除完了。";
(($FORM{'mode'} eq "questionwrite") && ($adminflag==1)) && print "質問編集完了。";
print "
\n";
&html_footer;
}
sub thanks_view{
($FORM{'mode'} eq "touroku") || return;
&getdata_q;
&html_header;
#_HTML_と_HTML_の間の行に、HTML言語で記述した内容が、回答送信後に表示されます。
print <<"_HTML_";
回答ありがとう!
お疲れさまでした〜。大変だったでしょ(^^;)
皆様の回答一覧は↓からどうぞ♪
_HTML_
&list;
&html_footer;
}
sub list_view{
(!$FORM{'mode'} || $FORM{'mode'} eq "list") || return;
&getdata_a;
&getdata_q;
&html_header;
#_HTML_と_HTML_の間の行に、HTML言語で記述した内容が表示されます。
print <<"_HTML_";
$title
*回答はパス可です。回答は後から訂正や削除ができます。
質問に答えるとき→回答フォーム
10人ごとの回答一覧→回答一覧
(ちょっと重いです。)
この画面に戻るときは、一番下↓の「個別回答リスト」から。
_HTML_
&list;
&html_footer;
}
sub list{
$num = scalar(@datas);
print "皆様の回答リスト
*それぞれクリックしてください。
\n";
print "*ご自分の回答を訂正/削除したい場合は、回答者ごとの回答リストから、ご自分の回答を選んでください。
\n";
print "*現在回答者は$num人です。\n";
($FORM{'pass'} eq $password) && print "*管理者パスワードを使えば、それぞれの回答ページからも訂正/削除ができます。
\n";
print "
\n";
}
sub answer_view{
($FORM{'mode'} eq "answer_view") || return;
($FORM{'who'} eq "") && &error(1,"誰の回答を見たいのか、指定してください。");
&getdata_a;
&getdata_q;
&html_header;
@answerdatas = split("\t",$datas[$FORM{'who'}]);
print "$answerdatas[0]さんの回答
\n";
$date = &gettime($answerdatas[2]);
print "*→をクリックしたら、その質問の回答一覧が表\示されます。
\n";
print "回答日時:$date
";
print "
\n";
for($i=0;$i$j. $questions[$i]";
print " → | \n";
chomp $answerdatas[$k];
($answerdatas[$k] eq "") && ($answerdatas[$k]="パス");
print " |
\n";
}
print <<"_HTML_";
_HTML_
&html_footer;
}
sub ans_view{
($FORM{'mode'} eq "ans") || return;
($FORM{'q'} eq "" || $FORM{'q'} >= $qnum || $FORM{'q'}<0 || $FORM{'q'} =~ /[^0-9]/) && &error(0,"どの質問についてなのか、指定されていません。
あるいは指定された質問番号が不正です。");
&getdata_a;
&getdata_q;
$question = $questions[$FORM{'q'}];
&html_header;
print "$title\n";
print $FORM{'q'}+1;
print ". $question
\n";
print "現在、回答者は";print scalar(@datas);print "人です。\n";
print "
\n";
$i=0;
foreach (@datas){
@answers = split(/\t/,$_);
$j = $FORM{'q'}+4;
print "- $answers[0]さんの回答\n";
($answers[$j] eq "") && ($answers[$j]="パス");
print "
- $answers[$j]
\n";
$i++;
}
print " |
\n";
&html_footer;
}
sub ichiran{
($FORM{'mode'} eq "ichiran") || return;
&getdata_a;
&getdata_q;
$start=$FORM{'start'};
($FORM{'start'} eq "") && ($start = 1);
$end = $start+$def-1;
($end>scalar(@datas)) && ($end = scalar(@datas));
&html_header;
print "$title回答一覧
\n";
print "($start〜$end人目まで。";print scalar(@datas);print "人中)\n";
print "
\n";
print "No. | ↓質問/回答者→ | \n";
for ($i=$start-1;$i<$end;$i++){
@answers = split(/\t/,$datas[$i]);
print "$answers[0]さん | \n";
}
print "
\n";
for ($i=0;$i<$qnum;$i++){
$j=$i+1;$l=$i+4;
print "$j | $questions[$i] | \n";
for ($k=$start-1;$k<$end;$k++){
@answers = split(/\t/,$datas[$k]);
chomp $answers[$l];
($answers[$l] eq "") && ($answers[$l]="パス");
print "$answers[$l] | \n";
}
print "
\n";
}
print "
\n";
print "
\n";
&html_footer;
}
sub rewriteform_view{
($FORM{'mode'} eq "rewrite") || return;
($FORM{'who'} eq "") && &error(1,"誰の回答の訂正をしますか?指定がありません。");
&getdata_a;
@answers = split(/\t/,$datas[$FORM{'who'}]);
($FORM{'name'} eq $answers[0]) || &error(1,"名前が違います!");
((&solve_pass($FORM{'pass'},$answers[3])) || ($FORM{'pass'} eq $password)) || &error(0,"パスワードが違います。");
&getdata_q;
$date = &gettime($answers[2]);
(($FORM{'pass'} eq $password)) && ($userdata = $answers[1]);
&html_header;
print <<"_HTML_";
$answers[0]さんの回答
$userdata
訂正は▽
*タグはFONTタグ、強調タグ(B)、打ち消しタグ(S)のみOKです。改行は反映されます。
タグの使い方はコチラ。
回答日時:$date
\n";
&html_footer;
}
sub question_admin{
($FORM{'mode'} eq "questionadmin") || return;
($FORM{'pass'} eq $password) || &error(0,"管理用パスワードが違います。");
&getdata_q;
&html_header;
print <<"_HTML_";
質問編集
*タグはFONTタグ、強調タグ(B)、打ち消しタグ(S)のみOKです。改行は反映されます。
タグの使い方はコチラ。
\n";
&html_footer;
}
sub unlock{
return rmdir($lockdir);
}
sub html_header{
print "Content-type: text/html\n\n";
print <<"_HTML_";
$title
$body
[HOME]
_HTML_
}
sub html_footer{
print <<"_HTML_";
もどる | 回答フォーム | 個別回答リスト |
回答一覧
100の質問回答&表\示CGI Ver.0.11
_HTML_
}
sub getdata_a{
open (IN,"$answerfile") || &error(1, "回答記録ファイルが開けません。");
@datas = ;
close (IN);
}
sub getdata_q{
open (IN,"$questionfile") || &error(1, "質問ファイルが開けません。");
@questions = ;
close (IN);
}
sub get_username{
$username = $ENV{'REMOTE_USER'};
$host = $ENV{'REMOTE_HOST'};
$add = $ENV{'REMOTE_ADDR'};
($host eq "" ) && ($host = $add);
($host eq $add) && ($host = ((gethostbyaddr(pack('C4',split(/\./,$add)),2))[0])) || ($host=$add);
$username = "$host";
}
sub tagok{ #タグを戻す。
local($comment) =@_;
$comment =~ s/<b>(.*)<\/b>/$1<\/b>/gi;
$comment =~ s/<s>(.*)<\/s>/$1<\/s>/gi;
$comment =~ s/<font(.*)>(.*)<\/font>/$2<\/font>/gi;
return $comment;
}
#Password
sub crypt_pass{
local($pass) = @_;
srand();
$xx = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
. "abcdefghijklmnopqrstuvwxyz"
. "0123456789./";
$salt = substr($xx, int(rand(64)), 1);
$salt .= substr($xx, int(rand(64)), 1);
$pass = crypt($pass,$salt);
return $pass;
}
sub solve_pass{
local($pass,$pwd) = @_; #&solve_pass($入力されたパス,$保存されたパス)
$salt = substr($pwd,0,2);
($pwd eq crypt($pass,$salt)) && return 1 || return 0;
}
#秒数を年月日に変換
sub gettime{
local($time) = @_;
($sec,$min,$hour,$dy,$mon,$year,$wday,$yday,$isdst) = gmtime($time+60*60*9);
@week = ('日','月','火','水','木','金','土');
$time = sprintf("%04d年%01d月%01d日\($week[$wday]\)%02d:%02d",$year+1900,$mon+1,$dy,$hour,$min);
return $time;
}
sub error{
local ($id,$msg) = @_;
$title = "お知らせ";
$fmsg[0] = "Backを押して戻ってください";
$fmsg[1] = "$kanriに連絡してください";
&html_header;
print "$msg
\n";
print "$fmsg[$id]\n";
&html_footer;
&unlock;
exit;
}