#!/usr/local/bin/perl
################################################################################
# 清き一票！（コメント表示用）
# Ver 2.1
# Copyright(C) futomi 2001 - 2004
# http://www.futomi.com/
###############################################################################
use strict;

#デモモード設定
# 0:デモモード解除
# 1:デモモードON
my $DemoMode = 0;

require './config.cgi';
require './jcode.pl';
use Time::Local;
use CGI;
my $q = new CGI;

#設定
my $ADMINPASSWORD = &config::ADMINPASSWORD;
my $GRAPHIMAGEURL = &config::GRAPHIMAGEURL;
my $CONFIRMFLAG = &config::CONFIRMFLAG;
my $MultiAnsFlag = &config::MultiAnsFlag;
my $ExpireDate = &config::ExpireDate;
my $ExpireErrMsg = &config::ExpireErrMsg;
my $ResultPrintFlag = &config::ResultPrintFlag;
my $REDIRECTFLAG = &config::REDIRECTFLAG;
my $REDIRECTURL = &config::REDIRECTURL;
my $GRAPHMAXLENGTH = &config::GRAPHMAXLENGTH;
my $GRAPHLINECOLOR1 = &config::GRAPHLINECOLOR1;
my $GRAPHLINECOLOR2 = &config::GRAPHLINECOLOR2;
my $MAXLISTNUM = &config::MAXLISTNUM;
my $HANDLEMAXLENGTH = &config::HANDLEMAXLENGTH;
my $COMMENTMAXLENGTH = &config::COMMENTMAXLENGTH;
my $CHECKHANDLE = &config::CHECKHANDLE;
my $CHECKCOMMENT = &config::CHECKCOMMENT;
my $LOGDIR = &config::LOGDIR;
my $NameAttribute = &config::NameAttribute;


my $Item = $q->param('item');
my $Next = $q->param('next');	unless($Next) {$Next = 1;}
my $Mode = $q->param('mode');
my $SearchYear = $q->param('SearchYear');
my $SearchMonth = $q->param('SearchMonth');
my $SearchDay = $q->param('SearchDay');
my $SearchIp = $q->param('SearchIp');
my $SearchItem = $q->param('SearchItem');
my $SearchHandle = $q->param('SearchHandle');
my $SearchComment = $q->param('SearchComment');


#このCGIのURLを取得する
my $ThisCgiUrl = $q->url();
my $AbsoluteUrl = $q->url(-absolute=>1);

######################################################################
#Main Routine
######################################################################

my $AdminFlag = &AdminCheck;

if($Mode eq 'delete') {
	if($AdminFlag) {
		&DeleteItem;
		&Redirect($ThisCgiUrl);
	} else {
		&ErrorPrint("管理者モードでなければ削除できません。");
	}
} else {
	my %LogDataList = &GetVoteLogData;
	&PrintList(\%LogDataList, $Next);
}
exit;

######################################################################
#Sub Routine
######################################################################

sub AdminCheck {
	my %cookies = &GetCookie;
	my $cookie_pass  = $cookies{'adminpass'};
	if($cookie_pass eq '') {
		return 0;
	}
	my $salt;
	if($cookie_pass =~ /^\$1\$([^\$]+)\$/) {
		$salt = $1;
	} else {
		$salt = substr($cookie_pass, 0, 2);
	}
	my $pass = crypt($ADMINPASSWORD, $salt);
	if($pass eq $cookie_pass) {
		return 1;
	} else {
		return 0;
	}
}

sub DeleteItem {
	my @DelIdentList = $q->param('delete');
	my $DelNum = scalar @DelIdentList;
	unless($DelNum) {&ErrorPrint("削除する項目を選択して下さい。");}
	if($DemoMode) {&ErrorPrint("デモモードでは削除できません。");}
	open(VOTELOG, "+<${LOGDIR}/votelog.cgi") || &ErrorPrint("ログファイル ${LOGDIR}/votelog.cgi をオープンできませんでした。");
	if(my $result = &Lock(*VOTELOG)) {
		&ErrorPrint("只今、混雑しております。しばらくお待ちください。: $result");
	}
	my @DataList = <VOTELOG>;
	my @NewDataList = ();
	my $NewDataLength = 0;
	for my $LineBuff (@DataList) {
		my @SplitedList = split(/,/, $LineBuff);
		my $DelIdent = "$SplitedList[0]-$SplitedList[1]";
		unless(grep(/^$DelIdent$/, @DelIdentList)) {
			push(@NewDataList, $LineBuff);
			$NewDataLength += length($LineBuff);
		}
	}
	seek(VOTELOG, 0, 0);
	print VOTELOG @NewDataList;
	truncate(VOTELOG, $NewDataLength);
	close(VOTELOG);
}


# リダイレクトする
sub Redirect {
	my($RedirectUrl) = @_;
	if($ENV{'HTTP_USER_AGENT'} =~ /MSIE/i) {
		print "Location: $RedirectUrl\n\n";
	} else {
		print "Content-type: text/html; charset=Shift_JIS\n";
		print "\n";
		print "<html>\n";
		print "<head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=$RedirectUrl\"></head>\n";
		print "<body><a href=\"$RedirectUrl\">こちら</a>をクリックして下さい。</body>\n";
		print "</html>\n";
		print "\n";
	}
}

sub PrintList {
	my($LogDataList, $Next) = @_;
	my $ListString;
	my $i = 0;
	my $PrintedNum = 0;
	my @Keys = keys %{$LogDataList};
	my $RecordNum;
	$RecordNum = scalar @Keys;

	$ListString .= '<table border="0" cellspacing="1"><tr>';
	$ListString .= '<td class=ListHeader>No</td>';
	if($AdminFlag) {
		$ListString .= '<td class=ListHeader>削除</td>';
	}
	$ListString .= '<td class=ListHeader>投票日時</td>';
	if($AdminFlag) {
		$ListString .= '<td class=ListHeader>IPアドレス</td>';
	}
	$ListString .= '<td class=ListHeader>投票</td>';
	$ListString .= '<td class=ListHeader>ハンドル名</td>';
	$ListString .= '<td class=ListHeader>コメント</td>';
	$ListString .= '</tr>';
	$ListString .= "\n";
	for my $key (sort {$b<=>$a} keys %{$LogDataList}) {
		$i ++;
		if($i < $Next) {next;}
		my ($TimeStamp, $IpAddress, $VotedItem, $Handle, $Comment) = split(/,/, $$LogDataList{$key});
		my $TimeStampString = &DateConv($TimeStamp);
		if($PrintedNum % 2 == 1) {
			$ListString .= "<tr bgcolor=\"$GRAPHLINECOLOR2\">";
		} else {
			$ListString .= "<tr bgcolor=\"$GRAPHLINECOLOR1\">";
		}
		$ListString .= "<td align=\"center\">$i</td>";
		if($AdminFlag) {
			$ListString .= "<td><input type=\"checkbox\" name=\"delete\" value=\"$TimeStamp-$IpAddress\"></td>";
		}
		$ListString .= "<td>$TimeStampString</td>";
		if($AdminFlag) {
			$ListString .= "<td>$IpAddress</td>";
		}
		$ListString .= "<td>$VotedItem</td>";
		$ListString .= "<td>$Handle</td>";
		$ListString .= "<td>$Comment</td>";
		$ListString .= "</tr>\n";
		$PrintedNum ++;
		if($PrintedNum >= $MAXLISTNUM) {last;}
	}
	$ListString .= "</table>\n";
	my($SearchString) = &MakeSearchString($LogDataList);
	my $FormStartTag = "<form action=\"$ThisCgiUrl\" method=\"post\">\n";
	$FormStartTag .= '<input type="hidden" name="mode" value="delete">';
	$FormStartTag .= "\n";
	my $FormEndTag = "</form>\n";
	my $DeleteButton = '<input type="submit" name="B1" value="削除">';
	my $PreString = &MakePreString($LogDataList);
	my $NextString = &MakeNextString($LogDataList);
	my $LineString;
	open(LIST, "./template/list.html") || &ErrorPrint("コメント一覧表示用画面テンプレート ./template/list.html をオープンできませんでした。");
	print "Content-type: text/html; charset=Shift_JIS\n";
	print "\n";
	while(<LIST>) {
		chop;
		$LineString = $_;
		$LineString =~ s/<!--sum-->/$RecordNum/;
		$LineString =~ s/<!--list-->/$ListString/;
		$LineString =~ s/<!--cgiurl-->/$ThisCgiUrl/;
		$LineString =~ s/<!--search-->/$SearchString/;
		$LineString =~ s/<!--pre-->/$PreString/;
		$LineString =~ s/<!--next-->/$NextString/;

		if($AdminFlag) {
			$LineString =~ s/<!--formstart-->/$FormStartTag/;
			$LineString =~ s/<!--formend-->/$FormEndTag/;
			$LineString =~ s/<!--deletebutton-->/$DeleteButton/;
		}
		print "$LineString\n";
	}
	close(LIST);
}

sub MakeNextString {
	my($LogDataList) = @_;
	my @Keys = keys %{$LogDataList};
	my $RecordNum;
	$RecordNum = scalar @Keys;
	my $FirstNo = $Next + $MAXLISTNUM;
	my $RemainNum = $RecordNum - $FirstNo + 1;
	if($RemainNum <= 0) {return '';}

	my $NextString;
	$NextString .= "<form action=\"$ThisCgiUrl\" method=\"post\">\n";
	$NextString .= "<input type=\"hidden\" name=\"next\" value=\"$FirstNo\">\n";
	if($SearchYear) {
		$NextString .= "<input type=\"hidden\" name=\"SearchYear\" value=\"$SearchYear\">\n";
	}
	if($SearchMonth) {
		$NextString .= "<input type=\"hidden\" name=\"SearchMonth\" value=\"$SearchMonth\">\n";
	}
	if($SearchDay) {
		$NextString .= "<input type=\"hidden\" name=\"SearchDay\" value=\"$SearchDay\">\n";
	}
	if($SearchIp) {
		$NextString .= "<input type=\"hidden\" name=\"SearchIp\" value=\"$SearchIp\">\n";
	}
	if($SearchItem) {
		$NextString .= "<input type=\"hidden\" name=\"SearchItem\" value=\"$SearchItem\">\n";
	}
	if($SearchHandle) {
		$NextString .= "<input type=\"hidden\" name=\"SearchHandle\" value=\"$SearchHandle\">\n";
	}
	if($SearchComment) {
		$NextString .= "<input type=\"hidden\" name=\"SearchComment\" value=\"$SearchComment\">\n";
	}
	if($RemainNum < $MAXLISTNUM) {
		$NextString .= "<input type=\"submit\" name=\"pre\" value=\"次の$RemainNum件>>\">\n";
	} else {
		$NextString .= "<input type=\"submit\" name=\"pre\" value=\"次の$MAXLISTNUM件>>\">\n";
	}
	$NextString .= "</form>\n";
	return $NextString;
}

sub MakePreString {
	my($LogDataList) = @_;
	my @Keys = keys %{$LogDataList};
	my $RecordNum;
	$RecordNum = scalar @Keys;
	my $FirstNo = $Next - $MAXLISTNUM;
	if($FirstNo < 0) {return '';}

	my $RemainNum = $RecordNum - $FirstNo + 1;
	my $PreString;
	$PreString .= "<form action=\"$ThisCgiUrl\" method=\"post\">\n";
	$PreString .= "<input type=\"hidden\" name=\"next\" value=\"$FirstNo\">\n";
	if($SearchYear) {
		$PreString .= "<input type=\"hidden\" name=\"SearchYear\" value=\"$SearchYear\">\n";
	}
	if($SearchMonth) {
		$PreString .= "<input type=\"hidden\" name=\"SearchMonth\" value=\"$SearchMonth\">\n";
	}
	if($SearchDay) {
		$PreString .= "<input type=\"hidden\" name=\"SearchDay\" value=\"$SearchDay\">\n";
	}
	if($SearchIp) {
		$PreString .= "<input type=\"hidden\" name=\"SearchIp\" value=\"$SearchIp\">\n";
	}
	if($SearchItem) {
		$PreString .= "<input type=\"hidden\" name=\"SearchItem\" value=\"$SearchItem\">\n";
	}
	if($SearchHandle) {
		$PreString .= "<input type=\"hidden\" name=\"SearchHandle\" value=\"$SearchHandle\">\n";
	}
	if($SearchComment) {
		$PreString .= "<input type=\"hidden\" name=\"SearchComment\" value=\"$SearchComment\">\n";
	}
	$PreString .= "<input type=\"submit\" name=\"pre\" value=\"<<前の$MAXLISTNUM件\">\n";
	$PreString .= "</form>\n";
	return $PreString;
}

sub MakeSearchString {
	my($LogDataList) = @_;
	my %YearList = ();
	my %MonthList = ();
	my %DayList = ();
	my %ItemList = ();
	for my $key (keys %{$LogDataList}) {
		my @DataList = split(/,/, $LogDataList->{$key});
		my $Year = substr($DataList[0], 0, 4);	$YearList{$Year} ++;
		my $Month = substr($DataList[0], 4, 2);	$MonthList{$Month} ++;
		my $Day = substr($DataList[0], 6, 2);	$DayList{$Day} ++;
		$ItemList{$DataList[2]} ++;
	}

	my $SearchString;
	$SearchString .= "<form action=\"$ThisCgiUrl\" method=\"post\">\n";
	$SearchString .= '<table border="0"><tr><td>投票日時</td><td>';
	$SearchString .= '<select name="SearchYear">';
	$SearchString .= "\n";
	$SearchString .= "<option value=\"\">指定なし</option>\n";
	for my $key (sort keys %YearList) {
		$SearchString .= "<option value=\"$key\"";
		if($key eq $SearchYear) {
			$SearchString .= ' selected';
		}
		$SearchString .= ">$key</option>\n";
	}
	$SearchString .= "</select>\n";
	$SearchString .= '年';
	$SearchString .= '<select name="SearchMonth">';
	$SearchString .= "<option value=\"\">指定なし</option>\n";
	for my $key (sort keys %MonthList) {
		$SearchString .= "<option value=\"$key\"";
		if($key eq $SearchMonth) {
			$SearchString .= ' selected';
		}
		$SearchString .= ">$key</option>\n";
	}
	$SearchString .= "</select>\n";
	$SearchString .= '月';
	$SearchString .= '<select name="SearchDay">';
	$SearchString .= "<option value=\"\">指定なし</option>\n";
	for my $key (sort keys %DayList) {
		$SearchString .= "<option value=\"$key\"";
		if($key eq $SearchDay) {
			$SearchString .= ' selected';
		}
		$SearchString .= ">$key</option>\n";
	}
	$SearchString .= "</select>\n";
	$SearchString .= '日</td></tr>';
	$SearchString .= "<tr><td>投票項目</td><td>\n";
	$SearchString .= '<select name="SearchItem">';
	$SearchString .= "<option value=\"\">指定なし</option>\n";
	for my $key (sort keys %ItemList) {
		$SearchString .= "<option value=\"$key\"";
		if($key eq $SearchItem) {
			$SearchString .= ' selected';
		}
		$SearchString .= ">$key</option>\n";
	}
	$SearchString .= "</select></td></tr>\n";
	$SearchString .= "<tr><td>ハンドル</td><td>\n";
	$SearchString .= "<input type=\"text\" name=\"SearchHandle\"";
	if($SearchHandle) {
		$SearchString .= " value=\"$SearchHandle\"";
	}
	$SearchString .= "></td></tr></table>\n";
	$SearchString .= "<center><input type=\"submit\" name=\"search\" value=\"検索\"></center>\n";
	$SearchString .= "</form>\n";

	return $SearchString;
}


sub DateConv {
	my($TimeStamp) = @_;
	my $TimeStampString = substr($TimeStamp, 0, 4).'/'.substr($TimeStamp, 4, 2).'/'.substr($TimeStamp, 6, 2);
	$TimeStampString .= ' '.substr($TimeStamp, 8, 2).':'.substr($TimeStamp, 10, 2).':'.substr($TimeStamp, 12, 2);
	return $TimeStampString;
}

sub GetVoteLogData {

	open(VOTELOG, "${LOGDIR}/votelog.cgi") || &ErrorPrint("ログファイル ${LOGDIR}/votelog.cgi をオープンできませんでした。");
	if(my $result = &Lock(*VOTELOG)) {
		&ErrorPrint("只今、混雑しております。しばらくお待ちください。: $result");
	}
	my %LogDataList = ();
	while(my $line = <VOTELOG>) {
		chomp $line;
		my @LineBuff = split(/,/, $line);
		unless($LineBuff[1]) {next;}
		if($SearchItem) {
			unless($LineBuff[3] eq $SearchItem) {next;}
		}
		if($SearchYear) {
			unless(substr($LineBuff[0], 0, 4) eq $SearchYear) {next;}
		}
		if($SearchMonth) {
			unless(substr($LineBuff[0], 4, 2) eq $SearchMonth) {next;}
		}
		if($SearchDay) {
			unless(substr($LineBuff[0], 6, 2) eq $SearchDay) {next;}
		}
		if($SearchHandle) {
			unless($LineBuff[4] =~ /$SearchHandle/) {next;}
		}

		$LogDataList{"$LineBuff[0]-$LineBuff[1]"} = "$LineBuff[0],$LineBuff[1],$LineBuff[3],$LineBuff[4],$LineBuff[5]";
	}
	close(VOTELOG);
	return %LogDataList;
}


sub Lock {
	local(*FILE) = @_;
	eval{flock(FILE, 2)};
	if($@) {
		return $!;
	} else {
		return '';
	}
}

sub ErrorPrint {
	my($message) = @_;
	print "Content-type: text/html; charset=Shift_JIS\n";
	print "\n";
	open(ERROR, "./template/error.html");
	while(<ERROR>) {
		chop;
		s/<!--message-->/$message/;
		print "$_\n";
	}
	close(ERROR);
	exit;
}


sub GetCookie {
	my(@CookieList) = split(/\; /, $ENV{'HTTP_COOKIE'});
	my %Cookie = ();
	for my $key (@CookieList) {
		my ($CookieName, $CookieValue) = split(/=/, $key);
		$CookieValue =~ s/\+/ /g;
		$CookieValue =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;
		$Cookie{$CookieName} = $CookieValue;
	}
	return %Cookie;
}

