#!/usr/local/bin/perl
#↑perlへのパス。詳しくはお使いのサーバー管理者にお確かめください。
#use strict;
#----------------
#キリ番表示カウンターCGI Ver.0.2
#----------------

#gif画像ファイル連結ライブラリgifcat.plの呼び出し
require "gifcat.pl";

#---------設定----------
#カウンターの桁数
my $fig = 5;

#昨日・今日のカウンターの桁数
my $mfig = 3;

#同一日内の同IPアドレスからの重複カウント防止　Yes→1;No→0;
my $nosameday = 0;

#$nosameday=0;の場合に有効。同一IPアドレスからの重複カウント防止期間
#同一IPアドレスからのアクセスはここで設定した時間が経過しないとカウント・記録しない
my $nocounthour = 0;		#単位は時間。

#通常カウントの場合
my $pimgdir = "";			#カウンター用数字画像の冠頭詞ここで設定した文字列を数字画像ファイル名の最初に付ける。ディレクトリ名でもOK。その場合は、$pimgdir = "img/";とする。（imgディレクトリに数字画像ファイルがある場合。）
my $pname = 'ok.gif';		#imageで表示される画像
my $pimgtype = 'gif';		#$pnameで設定した画像のファイルタイプ（拡張子がgifならgif、jpgならjpeg）
my $purl = 'http://www.yahoo.co.jp/';		#linkでジャンプするURL。http://から始まるURLを記述。
my $ppage = 'setumei.html';		#pageで表示されるページCGIと同じサーバにあるファイルであること。

#キリ番の場合
my $simgdir = "s";		#カウンター用数字画像の冠頭詞
my $sname = 'good.gif';		#imageで表示される画像
my $simgtype = 'gif';		#snameで設定した画像のファイルタイプ（拡張子がgifならgif、jpgならjpeg）
my $surl = 'http://www.google.com/';		#linkでジャンプするURL。http://から始まるURLを記述。
my $spage = 'form.html';		#pageで表示されるページ。CGIと同じサーバにあるファイルであること。

#カウントファイル
my $countfile = "count.dat";

#キリ番設定ファイル
my $specialcountsfile = "specialcount.dat";

#ログファイル名
my $logfile = "countlog.dat";

#管理用CGI（countkanri.cgi）で管理者に発行する、クッキーの値。"="は使わないこと。英数半角数字で。
my $kanripath = "master";
#---------設定は以上----------------------
my $kanriflag=0;
my (%COOKIE);
my @pairs = split(/\;/,$ENV{'HTTP_COOKIE'});
foreach (@pairs) {
	my ($name, $value) = split(/\=/, $_);
	$name =~ s/ //g;
	$COOKIE{$name} = $value;
}
($COOKIE{'count_kanri'} eq $kanripath) && ($kanriflag=1);
my $buffer = $ENV{'QUERY_STRING'};
$buffer =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;		#count.cgiの?以降を$bufferという変数として取得。
my ($countflag,$count) = &match;		#ログファイルチェック。$countflagが1ならば、新しくカウントすることはない。また、$countが以前その人が来たときのカウントとなる。
if ($countflag==0){
	$count = &countget;
	($kanriflag) || $count++;
}
my $flag = &smatch;			#キリ番かどうかのチェック。キリ番ならば$flag=1;
if ($buffer eq "image") {&image;}		#画像を表示する。
elsif ($buffer eq "link"){&link;}		#リンク先に飛ぶ
elsif($buffer eq "page"){&page;}		#ファイルを取り込んで表示
elsif ($buffer eq "yesterday"){&yesterday;}	#昨日のカウントを表示
elsif ($buffer eq "today"){&today;}		#今日のカウントを表示
elsif ($buffer eq "nextkiri"){&nextkiri;}	#次回キリ番を表示する。
else {
	if ($countflag==0 && $kanriflag==0){		#カウントを記録
		open(FILE, "+<$countfile") || die;
		my $count = <FILE>;
		chomp $count;
		$count++;
		seek(FILE,0,0);
		print FILE "$count";
		close(FILE);
		my $host = &get_username;
		open(FILE, ">>$logfile") || die;
		eval 'flock(FILE,2);';
		seek (FILE,0,0);
		print FILE ("$host\t".&gettime($^T)."\t$^T\t$count\n");
		eval 'flock(FILE,8);';
		close(FILE);
	}
	my $imgdir;
	($flag==1)? ($imgdir=$simgdir):($imgdir=$pimgdir);
	&view($count,$imgdir,$fig);
}
exit;
#-----------------------------------
sub yesterday{	#昨日のカウントを表示する。
	my $yesterday = &gettime($^T-24*60*60);
	my $yesterdaycount=0;
	open(FILE,"<$logfile") || die;
	while (<FILE>){
		my ($user,$day,$time,$num) = split(/\t/,$_);
		($yesterday eq $day) ? ($yesterdaycount++) : next;
		($day eq &gettime($^T)) && last;
	}
	close(FILE);
	&view($yesterdaycount,$pimgdir,$mfig);
}
sub today{	#今日のカウントを表示する。
	my $today = &gettime($^T);
	my $todaycount=0;
	open(FILE,"<$logfile") || die;
	while (<FILE>){
		my ($user,$day,$time,$num) = split(/\t/,$_);
		($today eq $day) ? ($todaycount++) : next;
	}
	close(FILE);
	&view($todaycount,$pimgdir,$mfig);
}
sub nextkiri{	#次回キリ番を表示する。
	my $nextkiri = $count;
	open(FILE,"<$specialcountsfile") || die;
	while (<FILE>){
		chomp $_;
		if ($_ > $nextkiri){$nextkiri=$_;last;}
	}
	close(FILE);
	&view($nextkiri,$pimgdir,$fig);
}
sub page{			#ファイルを取り込んで表示
	my $page;
	if ($flag==1){$page=$spage;}
	else{$page = $ppage;}
	print "Content-type: text/html\n\n";
	open(FILE,"<$page") || die;
	while (<FILE>){
		$_ =~ s/<count>/$count/g;
		print "$_";
	}
	close(FILE);
}
sub link{			#リンク先に飛ぶ
	my $url;
	if ($flag==1){$url=$surl;}
	else{$url = $purl;}
	print "Location:$url\n\n";
}
sub image{	#画像を表示する。
	my ($fname,$imgtype);
	if ($flag==1){
		$fname = $sname;
		$imgtype = $simgtype;
	}
	else{$fname=$pname;$imgtype=$pimgtype;}
	  open(IMG, "$fname")  || die;
	  binmode IMG;
	  binmode STDOUT;
	  print "Content-type: image/$imgtype\n\n";
	  print while(<IMG>);
	  close(IMG);
}
sub get_username{
	my $host = $ENV{'REMOTE_HOST'};
	my $add = $ENV{'REMOTE_ADDR'};
	($host eq "" ) && ($host = $add);
	($host eq $add) && ($host = ((gethostbyaddr(pack('C4',split(/\./,$add)),2))[0])) || ($host=$add);
	return $host;
}
sub match{	#ログファイルチェック。$countflagが1ならば、新しくカウントすることはない。また、$countが以前その人が来たときのカウントとなる。
	my $host = &get_username;
	my ($countflag,$count);
	open(FILE,"<$logfile") || die;
	while (<FILE>){
		chomp;
		my ($user,$day,$time,$num) = split(/\t/,$_);
		if ($nosameday==0 && $^T-$time<$nocounthour*60*60 && $host eq $user){
			$countflag=1;$count=$num;last;
		}
		(&gettime($^T)>$day) && next;
		if ($host eq $user && $nosameday){$countflag=1;$count=$num;last;}
	}
	close(FILE);
	return ($countflag,$count);
}
sub countget{
	my $count;
	open(FILE, "<$countfile") || die;
	$count = <FILE>;
	close(FILE);
	chomp $count;
	return $count;
}
sub smatch{
	my $flag=0;
	open(FILE,"<$specialcountsfile") || die;
	while (<FILE>){
		chomp $_;
		if ($_==$count){ $flag=1;last;}
	}
	close(FILE);
	($kanriflag) && ($flag=0);
	return $flag;
}
sub view{
	my ($count,$imgdir,$k) = @_;
	my (@files);
	$count = sprintf(sprintf("%%0%dld", $k), $count);
	printf("Content-type: image/gif\n\n");
	for(my $i = 0; $i < length($count); $i++){
		my $n = substr($count, $i, 1);
		push(@files, "$imgdir$n.gif");
	}
	binmode(STDOUT);
	print &gifcat'gifcat(@files);
}

#秒数を年月日に変換
sub gettime{
	my($time) = @_;
	my($sec,$min,$hour,$dy,$mon,$year,$wday,$yday,$isdst) = gmtime($time+60*60*9);
	$time = sprintf("%04d%02d%02d",$year+1900,$mon+1,$dy);
	return $time;
}
