#!/usr/local/bin/perl
#
######################################################################
###
###
### CGI投票システム T-Vote Ver.7.01
### [1/1] 本体 (tvote.cgi)
### (c) 1996-1999 Takahiro Nishida
### http://www.mytools.net/
###
###
######################################################################
#
### 変数設定部 (詳細は上記ページをご覧下さい) ######################
$ext = "cgi";
$basedir = ".";
$method = "post";
$code = "sjis";
$password = "TVoteV7";
$admin_email = "your\@mail.address";
### 変数設定部 (ここまで)###########################################
require "./jcode.pl";
$verno = '7.01';
$lockfile="$basedir/lockdir/tv7.lock";
print "Content-type: text/html\n\n";
&main;
##### メイン関数
sub main{
&lock;
&check_input;
&open_datafile;
&exec_admin;
&check_right;
&add_point;
&add_datas;
&show_html;
&update_datafile;
&unlock;
}
##### 入力のチェック
sub check_input{
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);
$FORM{$vn} = &decode($value);
}
$event = $FORM{'event'};
$item = $FORM{'item2'} || $FORM{'item1'};
$show = $FORM{'show'};
$com = $FORM{'com'};
$pwd = $FORM{'pwd'};
$sid = $FORM{'sid'};
$add = $FORM{'add'};
$act = $FORM{'act'};
($event =~ /^\w+$/) || &error(4);
$user_ip = $ENV{'REMOTE_ADDR'};
$user_host = $ENV{'REMOTE_HOST'} || $user_ip;
$time_sec = time();
$new_sid = $time_sec;
# 拡大表示の対象(初期値)
$insert_point = 0;
}
##### データファイルのオープン
sub open_datafile{
$datafile = "$basedir/$event.txt";
$tpfile = "$basedir/$event.html";
$logfile = "$basedir/$event.log";
$comfile = "$basedir/$event.com";
$rightfile = "$basedir/$event.rgt";
$admtpfile = "$basedir/tvadmin.tp";
$acomfile = "$basedir/allcom_$event.html";
&openfile($tpfile, *tps);
&openfile($datafile, *datas, 1);
&openfile($rightfile, *rights, 1);
unless($act){
&openfile($logfile, *logs, 1);
&openfile($comfile, *coms, 1);
}
else{
&openfile($admtpfile, *atps);
}
### Ver.6 → Ver.7 バージョンアップ用
unless($datas[0] =~ /^\d+\t\d+\t\d+\t/){
unshift(@datas, "1\t20\t0\t10\t10\t-1\t5\t#FFFFFF\t#000000\t#FFCCCC\t#DD0000\t400\t\n");
$upf_data = 1;
}
### コンフィグ行の取得
$configline = shift(@datas);
($inew, $icom, $ircom, $ilog, $ishow, $iltime, $ilnum, $nback, $nfont, $eback, $efont, $igraph) = split("\t", $configline);
}
########## 管理関数 ここから ##########
##### 管理モードの実行
sub exec_admin{
($pwd eq $password) || return;
($act) || &error(5, "作業が選択されていません。");
if($FORM{'admitem'}){
$mode = "admitem";
($act =~ /^d/) && &fix_data;
}
elsif($FORM{'admcfg'}){
$mode = "admcfg";
($act eq "fix") && &fix_config;
}
($admmsg) || ($admmsg = "$event の管理用フォームを開きました。");
}
##### 項目の修正
sub fix_data{
local($an, $ai, $vn, $i, $bitem, $bvalue);
$an = $FORM{'an'};
$ai = $FORM{'ai'};
$vn = $FORM{'vn'};
($act eq 'ddel') || ($vn =~ /^\d+$/) || (&error(5, "票数が不正です。"));
# 新規だったら入力項目を有効に
($act eq 'dnew') && (($ai = $an) || &error(5, "新規項目が記述されていません。"));
# 重複チェック
push(@datas, "$ai\t-1"); # ダミー行
for (0..$#datas){
($bitem, $bvalue) = split("\t", $datas[$_]);
if($bitem eq $ai){
$i = $_;
last;
}
}
# 削除
if($act eq 'ddel' || $act eq 'dfix'){
($i < $#datas) || &error(5, "指定された項目は存在しません。");
splice(@datas, $i, 1);
$admmsg = "$event の項目 $ai を削除しました。";
}
# 追加
if($act eq 'dfix' || $act eq 'dnew'){
for (0..$#datas){
($bitem, $bvalue) = split("\t", $datas[$_]);
if($bvalue < $vn){
splice(@datas, $_, 0, "$ai\t$vn\t\n");
last;
}
}
$admmsg = "$event の項目 $ai を $vn 票に修正しました。";
}
pop(@datas);
# 新規のチェック
if($act eq 'dnew'){
($i == $#datas) || &error(5, "指定された項目は既に存在しています。$i, $#datas");
$admmsg = "$event の項目 $ai を $vn 票で新規追加しました。";
}
$upf_data = 1;
}
##### 設定の変更
sub fix_config{
# 制限時間のみあらかじめ値を取得
$piltime = $iltime;
### 入力の受け取り
$inew = $FORM{'fnew'};
$icom = $FORM{'fcom'};
$ircom = $FORM{'frcom'};
$ilog = $FORM{'flog'};
$ishow = $FORM{'fshow'};
$iltime = $FORM{'fltime'};
$ilnum = $FORM{'flnum'};
$nback = $FORM{'fnback'};
$nfont = $FORM{'fnfont'};
$eback = $FORM{'feback'};
$efont = $FORM{'fefont'};
$igraph = $FORM{'fgraph'};
### 妥当性チェック
($inew =~ /^[01]$/) || &error(5, "【項目追加】 の値が不正です。($inew)");
($icom =~ /^\d+$/) || &error(5, "【コメント表\示】 の値が不正です。($icom)");
($ircom =~ /^\d+$/) || &error(5, "【コメント保存】 の値が不正です。($ircom)");
($ilog =~ /^\d+$/) || &error(5, "【ログ表\示】 の値が不正です。($ilog)");
($ishow > 0) || &error(5, "【初期表\示】 の値が不正です。($ishow)");
($iltime =~ /^-?\d+(\.\d+)?$/) || &error(5, "【投票制限】 の値が不正です。($iltime)");
($ilnum =~ /^\d+$/) || &error(5, "【投票制限】 の値が不正です。($ilnum)");
($igraph =~ /^\d+$/) || &error(5, "【グラフ】 の値が不正です。($igraph)");
### 標準の配色に戻す
if($FORM{'initcolor'}){
$nback = "#FFFFFF";
$nfont = "#000000";
$eback = "#FFCCCC";
$efont = "#DD0000";
}
### コメント全保存ファイルのクリア
($FORM{'clearallcom'}) && &updatefile($acomfile);
### 制限時間が変わっていたら権利ファイルを初期化
($piltime == $iltime) || ($rights[0] = 0);
$configline = "$inew\t$icom\t$ircom\t$ilog\t$ishow\t$iltime\t$ilnum\t$nback\t$nfont\t$eback\t$efont\t$igraph\t\n";
$upf_data = 1;
$admmsg = "$event の設定を変更しました。($piltime, $iltime)";
}
########## 管理関数 ここまで ##########
##### 権利のチェック
sub check_right{
### 無制限なら無視
($iltime < 0) && return;
chop($rights[0]); # 改行を切り落とす
# 初期化(一番近い0時)
$rtime = ($rights[0]) || ($time_sec - ($time_sec + 32400) % 86400);
# 一生でないなら時間のチェック
if(($iltime > 0) && ($rtime < $time_sec)){
while($rtime < $time_sec){
$rtime += 3600 * $iltime;
}
$rights[0] = $rtime . "\n";
$#rights = 0;
$upf_right = 1;
}
# 投票済み項目
foreach (@rights){
(/$user_ip\t/) && push(@uright, $_);
}
# 残り権利数
$vrlest = $ilnum - @uright;
# 投票があった場合、権利のチェック
if($item && $add){
(--$vrlest >= 0) || &error(6);
push(@rights, "$user_ip\t$item\t\n");
push(@uright, "$user_ip\t$item\t\n");
$rights[0] = $rtime . "\n";
$upf_right = 1;
}
}
##### 票数を加える
sub add_point{
($item && $add) || return;
local($i, $bitem, $bvalue, $value_of_point);
$value_of_point = (split("\t",$datas[0]))[1];
$i = 0;
push(@datas, "$item\t0\t\n"); # ダミー行
foreach (@datas){
($bitem, $bvalue) = split("\t");
if($value_of_point > $bvalue){
$insert_point = $i; # 票の変わり目の場所と票数を記録
$value_of_point = $bvalue;
}
if($bitem eq $item){
splice(@datas, $i, 1);
$bvalue++;
($bvalue < $value_of_point) && ($insert_point = $i); # 追いつかなかったら同じ場所
splice(@datas, $insert_point, 0, "$bitem\t$bvalue\t\n");
last;
}
$i++;
}
# 新しい項目だった場合
if($i == $#datas){
($inew) || &error(7);
$flag_new = 1;
}
else{
pop(@datas); # ダミー行の削除
}
$upf_data = 1;
}
##### 票数以外のデータの書換
sub add_datas{
($item && $add) || return;
local($date, $newline, $bnew);
$date = &get_time($time_sec);
### ログ
($flag_new) && ($bnew .= "[NEW]");
$newline = "
$date $item ($user_host) $bnew \n";
unshift(@logs, $newline);
(@logs <= $ilog) || ($#logs = $ilog - 1);
$upf_log = 1;
### コメント
if($icom && $com){
$newline = "$date $item ($user_host)
...$com\n";
($coms[0] =~ /--$sid--/) && &error(9); # 連続コメント防止
unshift(@coms, $newline);
(@coms <= $icom) || ($#coms = $icom - 1);
$upf_com = 1;
# 全コメント保存の場合(ちょっと処理が汚い。。。)
($ircom) && &updatefile($acomfile, "", $newline, 1);
}
}
##### ファイルの更新
sub update_datafile{
unshift(@datas, $configline); # コンフィグ行を戻す
($upf_data) && &updatefile($datafile, *datas);
($upf_log) && &updatefile($logfile, *logs);
($upf_com) && &updatefile($comfile, *coms);
($upf_right) && &updatefile($rightfile, *rights);
}
#################### HTML表示関数 ここから ####################
##### メイン
sub show_html{
local($htmlbuf);
### 選択項目(管理でも使用する)
foreach (@datas){
($bitem, $bvalue) = split("\t");
$bsel = ($bitem eq $item) ? "SELECTED" : "";
$html_select_options .= "