#!/usr/local/bin/perl

## Lime Counter v1.3 (2000/09/11)
## Copyright(C) Kent Web 2000
## E-Mail: webmaster@kent-web.com
## WWW: http://www.kent-web.com/

#--- [注意事項] ------------------------------------------------#
# 1. このスクリプトはフリーソフトです。このスクリプトを使用した	#
#    いかなる損害に対して作者は一切の責任を負いません。		#
# 2. 設置に関する質問はサポート掲示板にお願いいたします。	#
#    直接メールによる質問は一切お受けいたしておりません。	#
#---------------------------------------------------------------#

# [ 1. ページカウンタの使い方 ] : b.の使い方を推奨
#  a. タグの記述例 (1) ページのURLは自動で取得する場合
#    <IMG SRC="cgi-bin/lime.cgi?page=1&name=ページ名">
#  b. タグの記述例 (2) ページのURLを手動で指定する場合
#    <IMG SRC="cgi-bin/lime.cgi?page=1&name=ページ名
#     &hp=http://www.host.com/~user/">  (注：タグは実際には改行しないで下さい）
#
#  注：・b.のタグ記述例は見やすくするためにわざと２行にして書いていますが、
#        実際に記述する場合には改行せずに「１行で」記述してください。
#      ・「ページ名」の部分は日本語でもOKですが、半角カナや機種依存文字は不可。
#      ・ page=1 の 1 の数値はページ毎に必ず変えてください。
#
#  c. アクセス一覧集計の閲覧例
#     http://www.host.com/~user/cgi-bin/limemgr.cgi
#  d. ファイルロック処理をする場合、lime.cgi を置くディレクトリの
#     パーミッションは 777 とする。
# ----------------------------------------------------------------------------
# [ 2. ダウンロードカウンタの使い方 ] : f.の使い方を推奨
#  e. タグの記述例 (1) ページのURLは自動で取得する場合
#     <a href="cgi-bin/lime.cgi?down=http://www.host.com/data.lzh&name=テスト">
#      DATA.LZH</a>
#  f. タグの記述例 (2) ページのURLを手動で指定する場合
#     <a href="cgi-bin/lime.cgi?down=http://www.host.com/data.lzh&name=テスト
#      &hp=http://www.host.com/~user/">DATA.LZH</a>
#      (注：タグは実際には改行しないで下さい）
#
#  注：・f.のタグ記述例は見やすくするためにわざと２行にして書いていますが、
#        実際に記述する場合には改行せずに「１行で」記述してください。
#      ・「ページ名」の部分は日本語でもOKですが、半角カナや機種依存文字は不可。
#
#  g. アクセス一覧集計の閲覧例
#     http://www.host.com/~user/cgi-bin/limemgr.cgi
#  h. ファイルロック処理をする場合、lime.cgi を置くディレクトリの
#     パーミッションは 777 とする。
# ----------------------------------------------------------------------------
# [ 3. チェックモードの使い方 ]
#  i. http://www.host.com/~user/cgi-bin/lime.cgi?mode=check
#     mode=checkという引数を付けてブラウザから指定する
#
# ----------------------------------------------------------------------------

#============#
#  設定項目  #
#============#

# 文字コードライブラリの取込
require './jcode.pl';

# ログファイル名
$logfile = "./lime.log";

# ロックの形式 (0=no 1=symlink 2=open)
$lockkey = 0;

# ロックファイル
$lockfile = "./lime.lock";

#============#
#  設定完了  #
#============#

$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/\"/&quot;/g;
	$value =~ s/<>/&gt;&lt;/g;

	$in{$name} = $value;
}

$page = $in{'page'};
$name = $in{'name'};
$mode = $in{'mode'};
$hp   = $in{'hp'};
$down = $in{'down'};
$down =~ s/^http\:\/\///;
$down =~ s/^http\:\///;

# チェックモード
if (!$buffer || $mode eq "check") { &check; }

# URLの引数がない場合はリンク元情報を取得する
if ($hp eq "") {
	$hp = $ENV{'HTTP_REFERER'};
	$hp =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
}
$hp =~ s/^http\:\/\///;
$hp =~ s/^http\:\///;
if ($hp eq "") { $hp = "unknown"; }

# IPアドレスを取得
$addr = $ENV{'REMOTE_ADDR'};

# ロック開始
if ($lockkey == 1) { &lock1; }
elsif ($lockkey == 2) { &lock2; }

# ログを開く
if ($down) { $page = $down; }

open(IN,"$logfile") || &error("$logfile");
@lines = <IN>;
close(IN);

# マッチング／カウントアップ処理
$flag=0;
@new=();
foreach $line (@lines) {
	($no,$hpg,$count,$title,$ip) = split(/<>/, $line);

	if ($page eq "$no") {
		# IPアドレスが同じ場合はカウントアップしない
		if ($addr eq "$ip") { $flag=2; last; }

		# $hpg, $title がない場合
		if ($hpg eq "") { $hpg = $hp; }
		if ($title eq "") {
			&jcode'convert(*name,'sjis');
			$title = $name;
		}

		$flag=1;
		$count++;
		$line = "$no<>$hpg<>$count<>$title<>$addr<>\n";
	}
	push(@new,$line);
}

# 既存ログ更新
if ($flag == 1) {
	open(OUT,">$logfile") || &error("$logfile");
	print OUT @new;
	close(OUT);
}
# 新規ページ追加更新
elsif ($flag == 0 && $hp ne "") {
	# ページ名を S-JIS コードへ
	&jcode'convert(*name,'sjis');

	open(OUT,">>$logfile") || &error("$logfile");
	print OUT "$page<>$hp<>1<>$name<>$addr<>\n";
	close(OUT);
}

# ロック解除
if (-e $lockfile) { unlink($lockfile); }

# ダウンロードカウンタの場合
if ($down) {
	# IISサーバ(PerlIS)対応
	if ($ENV{'PERLXS'} eq "PerlIS") {
		print "HTTP/1.0 302 Temporary Redirection\r\n";
		print "Content-type: text/html\n";
	}
	print "Location: http://$down\n\n";
}
else {
	# ダミー画像を定義：透明GIF (2x2ピクセル、16色)
	@array = ("47","49","46","38","39","61","02","00","02","00","80","00",
		"00","00","00","00","ff","ff","ff","21","f9","04","01","00","00",
		"01","00","2c","00","00","00","00","02","00","02","00","00","02",
		"02","8c","53","00","3b");

	# ダミー画像を表示
	print "Content-type: image/gif\n\n";
	foreach (@array) {
		$data = pack('C*',hex($_));
		print $data;
	}
}
exit;

#------------------------------------#
#  ロックファイル処理 : symlink関数  #
#------------------------------------#
sub lock1 {
	local($retry) = 5;
	while (!symlink(".", $lockfile)) {
		if (--$retry <= 0) { &error('lock'); }
		sleep(1);
	}
}

#---------------------------------#
#  ロックファイル処理 : open関数  #
#---------------------------------#
sub lock2 {
	local($flag) = 0;
	foreach (1 .. 5) {
		if (-e $lockfile) { sleep(1); }
		else {
			open(LOCK,">$lockfile") || &error('lock');
			close(LOCK);
			$flag = 1;
			last;
		}
	}
	if ($flag == 0) { &error('lock'); }
}

#--------------#
#  エラー処理  #
#--------------#
sub error {
	if (-e $lockfile) { unlink($lockfile); }
	die "Error : $_[0]";
}

#------------------#
#  チェックモード  #
#------------------#
sub check {
	print "Content-type: text/html\n\n";
	print "<html><head><title>LIME COUNTER</title></head>\n";
	print "<body>\n<UL>\n";

	# ログファイルのパス確認
	if (-e $logfile) {
		print "<LI>ログファイルのパス : OK!\n";
	} else {
		print "<LI>ログファイルがありません。\n";
	}

	# ログファイルのパーミッション（読みこみ）
	if (-r $logfile) {
		print "<LI>ログファイルの読みこみパーミッション : OK!\n";
	} else {
		print "<LI>ログファイルの読みこみパーミッションが不正です。\n";
	}

	# ログファイルのパーミッション（書きこみ）
	if (-w $logfile) {
		print "<LI>ログファイルの書きこみパーミッション : OK!\n";
	} else {
		print "<LI>ログファイルが書きこみパーミッションが不正です。\n";
	}

	print "</UL>\n</body></html>\n";
	exit;
}
