#!/usr/bin/perl
#
#ゆいぼーと2.1(yuivote2.cgi)
#1997.10.10製作
#すくりぷと ばい ゆいちゃっと
# Since 1996
#
# アンケート fvote.cgi v2.23 (2002/04/17)
# このスクリプトは、ゆいちゃっとさんのゆいぼーと2(yuivote2.cgi)を
# 改造したスクリプトです。(since 1998/08/15)
$ver = '2.24';#(2004/01/11)
# arranged by Falcon Taka
# http://www7.big.or.jp/~falcon/
#
# arranged by Fukura Sato, Feb. 24 '2006
# http://fukura.ne.jp/shop/
#
#設置ディレクトリにfvote.cgi(755),jcode.pl(644),fvote.dat(666),fcount.dat(666)
#を置きます。
#下の初期設定の中を適切に書き換えます。
##############初期設定など###################
require './jcode.pl'; # jcode.plが同一ディレクトリにある場合
$method ='POST'; #通常はこのまま
$homepage ='https://fukura.ne.jp/shop/'; #戻るページのURLを記入
#ブラウザの上部に表示するタイトル(タグは使えません。)
$title = 'アンケート';
#タイトルの中に「'」を使う場合は、直前に\をつける。(ex. B'z → B\'z)
# 画面上部に表示するタイトル
# タイトルに画像を使用する時は、
などに
# タグの使用は可能です。
$title2 ='
MS プロダクトキーのサイト内人気投票
';
#タイトルの中に「'」を使う場合は、直前に\をつける。(ex. B'z → B\'z)
# 画面設定
$backgif = ""; # 壁紙を指定(http://から記述すると確実)
$bgcolor = "#DDFFEE"; # 背景色を指定
$text = "#000080"; # 文字色を指定
$link = "#AA0000"; # リンク色を指定(未リンク)
$vlink = "#AA0000"; # リンク色を指定(リンク済)
$alink = "#FFAAAA"; # リンク色を指定(リンク中)
#表示する質問内容などをここに書きます。HTML文法に従って記述します。
$quest ='
閲覧した中で、あなたの気に入った項目を選択して投票してください。
質問:あなたの好きな項目・ページ・ソフトは何?
';
#↑この行を消したりしないで下さい。
#理由(コメント)を記入していただく内容についての注意書きを記入します。
$message ='
選択した項目やページが好きになった理由やどんなところが気に入ったかなどを簡単にお書き下さい。(max 200字)
タグは使えません。
';
#↑この行を消したりしないで下さい。
#↓あらかじめ決めておいた選択項目を表示する場合は、''の中に記入しておく。投票数にはカウントされません。追加する場合は、('〜','〜','〜','〜','〜');と増やしていってください。
#不要な場合は、何も記入しないで下さい。@sentaku = ();
@sentaku = ('Win 7 Enterprise','Win 7 Ultimate','Win 7 Professional','Win 7 Home Premium','Win 7 Home Basic','Win Vista Ultimate','Win XP SP3','Office 2010 Professional Plus','Office 2010 Professional','Office 2010 Standard','Office 2007 Professional');
$add = 1; #選択項目以外の投票を許可する場合は 1。追加しないときは 0。
$kotei = 0; #上記 $add = 0; の場合、選択項目の順番を固定する 1に、投票数の多い順 0。
$pagelog =20; #コメント表示画面で1ページに表示する件数
$datecolor = '#888888'; #コメント表示画面での日付の表示色
$host_sw = '1'; #コメント表示画面でリモートホスト名を表示(no=0 yes=1)
$max=1000; #保存する投票数。これを超えると古い投票から削除されます。
$mojisuu = 40; #選択項目の文字数の制限 (40→全角20文字)
$comment_max = 400; #コメント欄に書き込める最大文字制限数
$jouge = 1; #初期画面で投票結果が下 1。投票結果が上 0。
$cookies = 2; #何度でも投票を受け付ける場合は、2
#何度でも投票を受け付けるが、同じ項目には一回だけ受け付ける場合は 1
#一人一回の場合は 0
#設置してからの変更はしない方がいいです。
#時間による投票の制限
$timeset = 0; #投票の時間制限(no=0 yes=1)
$timedelay = 24; #時間制限する場合の時間(この時間を経過しないと投票受け付けない)
$nam = 1; #名前が未記入だった場合に投票拒否は1。認める場合は0。
$mail= 0; #メールアドレスが未記入だった場合に投票拒否は1。認める場合は0。
$com = 1; #コメントが未記入だった場合に投票拒否は1。認める場合は0。
$mrkgif = 'mrk.gif'; #グラフ用の画像ファイル名
#↑fvote.cgiと同じフォルダの場合はこのまま
#同じフォルダに入れても画像が表示されない場合は、HTMLスペースに設置して
#http://から記述する。
#通常は、そのまま↓ 同じフォルダに複数設置する場合のみ変更
$cginame = './fvote.cgi'; #このCGIのファイル名
$lockfile = './fovote.lock'; #ロックファイル名
$vote_file = './fvote.dat'; #投票データ記録ファイル
$editname = './fvotedit.cgi'; #管理用CGIのファイル名
$cookiename = 'FVOTE'; #クッキーネーム(複数設置する以外はこのまま)
$lockkey = 2; # ファイルロック形式(0=no 1=symlink関数 2=open関数)
#カウンタ関係設定項目
$count = '1'; #カウンタを表示しない 0,文字で表示 1,画像で表示 2
$lockcount = './fcount.lock'; # カウンタ用ロックファイル名
$countfile = './fcount.dat'; # カウンタファイル
$mini_fig = 4; # カウンタの桁数
$cnt_color = '#FF0000'; # カウンタ数字の色
$gif_path = '.'; #カウンタに画像を使用する場合の画像のあるフォルダ
#↑相対パスもしくは、http://から (0.gif〜9.gifを用意すること)
$cntgif_wid = '10'; #数字画像の横幅サイズ(ピクセル)
$cntgif_hei = '20'; #数字画像の縦サイズ(ピクセル)
#ログ表示部のに追加したいタグなどを記入します。JavaScript スタイルシートなど
$head =<<"_HTML_";
_HTML_
#↑この行を消したりしないで下さい。
#広告バナーなどを入れる場合に入れるタグを記入。$banner1 画面の上 $banner2 画面の下
#MIDIを鳴らしたい場合などは、$banner1に。ページカウンタなどは$banner2に入れてもいいでしょう。
#
$banner1 = '';
$banner2 = '';
#####イタズラ投稿防止設定
# リモートホスト(またはIPアドレス)での投稿拒否
#ppp123.abc.or.jp などの場合は、数字の部分がアクセスのたびに異なるので
#数字の部分を .* (ピリオド+アスタリスク)に置き換えます。
#@deny = ('ppp.*.abc.or.jp','web.net'); #などと設定します。
@deny = ();
# 投稿記事内容にふさわしくない語句の禁止
# @word = ('エッチ','test', '馬鹿');#などと設定。
@word = ('http','援助','不倫','浮気','セックス','credit','comment2','viagura','sex','ciaris','porn','homo','.txt');
################↑初期設定ここまで############
$host = $ENV{'REMOTE_HOST'};
$addr = $ENV{'REMOTE_ADDR'};
if ($host eq $addr || $host eq "") { $host = gethostbyaddr(pack('C4',split(/\./,$addr)),2) || $addr; }
# bodyタグ
if ($backgif) {
$body = "\n";
} else {
$body = "\n";
}
&decode;
&readlog;
$date = &jikan();
&votehtml unless($buffer); #初期画面へ
&detailhtml if($buffer=~/detail=/i); #コメント集画面へ
&writelog if($mode);
&votehtml; #投稿後の集計画面へ
exit;
sub getcookie{ #クッキーの取り出し。
$cooks = $ENV{'HTTP_COOKIE'};
@pairs = split(/;/,$cooks);
foreach $pair(@pairs){
local($name,$value) = split(/=/, $pair);
$name =~ s/ //g;
$dummy{$name} = $value;
}
@pairs = split(/\,/,$dummy{$cookiename});
foreach $pair(@pairs){
local($name,$value) = split(/<>/, $pair);
$COOK{$name} = $value if($value ne '');
}
$id = $COOK{'id'};
$c_name = $COOK{'name'};
$c_email = $COOK{'email'};
$c_time = $COOK{'times'};
if (!$id) { $id = "$times$ENV{'REMOTE_ADDR'}"; }
######
$c_name = $FORM{'name'} if($FORM{'name'});
$c_email = $FORM{'email'} if ($FORM{'email'});
}#getcookie END
sub setcookie{ #クッキーをブラウザに保存。
($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg)
= gmtime(time + 365*24*60*60); #クッキー約1年間有効
$yearg += 1900;
if ($secg < 10) { $secg = "0$secg"; }
if ($ming < 10) { $ming = "0$ming"; }
if ($hourg < 10) { $hourg = "0$hourg"; }
if ($mdayg < 10) { $mdayg = "0$mdayg"; }
$month = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[$mong];
$youbi = ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday')[$wdayg];
$date_gmt = "$youbi, $mdayg\-$month\-$yearg $hourg:$ming:$secg GMT";
if (!$id) { $id = "$times$ENV{'REMOTE_ADDR'}"; }
$data ="id<>$id\,name<>$FORM{'name'}\,email<>$FORM{'email'}\,times<>$times\,dmy<>$dmy";
print "Set-Cookie: $cookiename=$data; expires=$date_gmt\n";
}
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) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/\r/\n/g; $value =~ s/\n\n/\n/g;
$value =~ s/</g; $value =~ s/:#//g; $value =~ s/&/&/g;
$value =~ s/>/>/g; $value =~ s/"/"/g; $value =~ s/\n/
/g;
&jcode'convert(*value,'sjis');
$FORM{$name} = $value if($value);
}
$mode = $FORM{'mode'};
$vote = $FORM{'vote'};
$vote = substr($vote,0,$mojisuu); #選択項目の文字数の制限
$comment = $FORM{'comment'};
$name1 = $FORM{'name'};
$email = $FORM{'email'};
$page = $FORM{'page'};
}#decode END
sub jikan{#$dateに時刻を代入。18時間時差があるなら、$times = $ttt = time+18*60*60とする。
$ENV{'TZ'} = 'JST-9';$times = $ttt = time;
$ttt = $_[0] if($_[0] ne '');
($sec,$min,$hour,$mday,$month,$year,$wday) = localtime($ttt);
$min = "0$min" if ($min < 10);
$month++;
$year += 1900;
$youbi = ('日','月','火','水','木','金','土') [$wday];
local($date) = "$month/$mday($youbi)$hour:$min";
#local($date) = "$year/$month/$mday($youbi)$hour:$min"; #西暦年を表示する場合は、先頭の#を取る。
return $date;
}#jikan END
sub readlog{ #配列@linesにログを読み込む
open(DB,"$vote_file") || &error("Can't open $vote_file");
seek(DB,0,0);
@lines = ;
close(DB);
$total = 0;
foreach $line (@lines) {
next unless($line=~/:#/);
($id, $koumoku, $name, $detail,$dmy) = split(/:#/, $line);
$votes{$koumoku}++;$total++;
}
}#readlog END
sub writelog{ #チェックしつつ書き込み
if (@deny){ &deny; }
if (@word){ &wordcheck($comment); &wordcheck($name1);}
&getcookie;
$timedelay2 = $timedelay * 3600;
if (($timeset) && ($timedelay2 > $times - $c_time)){
$date = &jikan($c_time);
$err = "前回の投稿から$timedelay時間経過していない為、投票できません。
前回投票 $date";
}
if (!$vote){
$err .= "選択項目のセレクトまたは、記入がありません。
";
}
if (length($name1) < 2 && $nam){
$err .= "名前が書かれていないか短すぎます。
";
}
if (!$email && $mail) {
$err .= "メールアドレスの記入がありません。
";
}
if (length($comment) < 6 && $com){
$err .= "コメントが短すぎるか書かれていません。
";
}
if (length($comment) > $comment_max ){
$err .= "コメントが長すぎます。$comment_max文字(全角でその半分)以内でお願いします。
";
}
if ($err) { &error("$err") };
if ($email){
$name1="$name1";
}
return unless( ($ENV{'HTTP_REFERER'} eq '') || ($ENV{'HTTP_REFERER'} =~/$cginame/));
#うまく動作しない場合は、上記の行をコメントアウトしてください。(先頭に#)
$flag = 1;
if ($cookies ne '2'){
foreach $line(@lines) {#重複投票は過去のものに上書き
if ($cookies eq '0') {
next unless ($line=~/^$id/i);
}
if ($cookies eq '1') {
($id1, $koumoku1) = split(/:#/, $line);
next unless (($id eq "$id1") && ($vote eq "$koumoku1"));
}
$flag = 0;
$line = "$id:#$vote:#$name1:#$comment:#$date:#$host:#$times:#\n";
last;
}
}
if($flag){ #新規投票は、加える
unshift(@lines,"$id:#$vote:#$name1:#$comment:#$date:#$host:#$times:#\n");
}
(@lines < $max-1) || (@lines = @lines[0 .. $max - 1]);
if ($lockkey == 1) { &lock1($lockfile,0); }
elsif ($lockkey == 2) { &lock2($lockfile,0); }
open(DB,"+<$vote_file") || &error("Can't open $vote_file");
eval 'flock(DB,2);';
truncate(DB,0);
seek(DB,0,0);
print DB @lines;
#eval 'flock(DB,8);';
close(DB);
&unlock($lockfile);
&setcookie;
}#writelog END
sub header { #HTMLヘッダ
print "Content-type: text/html\n\n";
print <<"_HTML_";
$title
$head
$body
$banner1
_HTML_
}
sub votehtml {#投票前画面
&getcookie;
$total = 0;
undef %votes;
foreach $line (@lines) {
next unless($line=~/:#/);
($id, $koumoku, $name, $comment,$dmy) = split(/:#/, $line);
$votes{$koumoku}++;
$total++;
}
&header;
#カウンタの表示
if ($count ne '0'){&counter;}
print <<"_HTML_";
$title2
戻る
_HTML_
if ($jouge){ &formhtml; &resulthtml; }
else { &resulthtml; &formhtml; }
&footer;
exit;
}#votehtml END
sub formhtml{
print <<"_HTML_";
_HTML_
}#formhtml END
sub resulthtml{ #投票結果画面
print <<"_HTML_";
$date 現在のアンケート集計結果(11/03/16ハッキングデータを除去して修復)は以下の通りです。
それぞれの選択項目をクリックすると各コメントを見ることができます。
| 順位 | 選択項目 | 回答数 | 割合 | グラフ |
_HTML_
$flag=0;
$rank1 = 0;
$rank2 = 1;
$count_tmp = 0;
foreach (sort { $votes{$b} <=> $votes{$a} } keys %votes) {
($votes{$_} == $count_tmp) || ($rank1 = $rank2);
$percent = $votes{$_} / $total * 100;
if ($flag ==0){$bai = 300 / $percent; $flag=1;}
$mrk = int($bai*$percent)+1; $percent = int($percent);
$decode=$_;
$encode=&URLEncoder($_);
print "| No\.$rank1 | $decode | $votes{$decode} | $percent\% |  |
\n";
$count_tmp = $votes{$decode};
$rank2++;
}
print "
\n";
}#resulthtml END
sub footer {
print "
\n";
print "$banner2";
print "
[管理用]
\n";
print "\n";
#この行だけは消さないでください!!
}
sub detailhtml {#コメント画面
&header;
foreach $line (@lines) {
next unless($line=~/:#/);
($id, $koumoku, $name, $comment,$dmy) = split(/:#/, $line);
if($koumoku eq $FORM{'detail'}){
push(@com,$line);
}
}
if ($page eq '') { $page = 0; }
$end_data = $#com; $comtotal = $#com + 1;
$page_end = $page + ($pagelog - 1);
if ($page_end >= $end_data) { $page_end = $end_data; }
print <<"_HTML_";
[投票結果に戻る]
[$FORM{'detail'}]についてのコメント
$comtotal件の投票があります。
_HTML_
$detail = &URLEncoder($FORM{'detail'});
&backnext;
print <<"_HTML_";
| お名前 | コメント |
_HTML_
foreach ($page .. $page_end){
$com[$_] =~ s/\n$//;
($id,$koumoku,$name,$comment,$date,$host,$dmy,$dmy) = split(/:#/, $com[$_]);
if ($date && $host_sw){
$comment .= "($date $host)";
}elsif($date){
$comment .= "($date)";
}
print "| $name | $comment |
\n";
}
print <<"_HTML_";
_HTML_
&backnext;
&footer;
exit;
}#detailhtml END
#ページリンク(OLD,NEW)
sub backnext{
# 改頁処理
$next_line = $page_end + 1;
$back_line = $page - $pagelog;
print "\n";
# 次頁処理
if ($page_end ne $end_data) {
print "OLD ";
}
# 前頁処理
if ($back_line >= 0) {
print "NEW";
}
print "\n";
}
sub error {
print "Content-type: text/html\n\n";
print "$body\n";
print "
エラー発生
\n";
print "$_[0]
\n";
print "\n";
exit;
}
sub URLEncoder {
$_[0] =~ s/([^0-9A-Za-z_ ])/"%".unpack("H2",$1)/ge;
$_[0] =~ tr/ /+/;
$_[0];
}
# カウンタ (KENTさん式 改良バージョン
sub counter {
print "| \n";
# ログ読込み
if (!open(NO,"$countfile")){
print "Can't open $countfile |