#!/usr/local/bin/perl
#------------------------------------------#
# ↑このperlのパスはプロバイダによって違う #
# ので、分からないときはプロバイダに聞く。 #
#------------------------------------------#

###########################################################
#  PerlCounter Ver.1.02                                   #
#                                                         #
#  種別　　　　　： Free                                  #
#  作成日　　　　： 11/14/1998                            #
#  更新日　　　　： 04/19/1999                            #
#  著作権者　　　： 飾り職人ひで(Hideyuki Chikada)        #
#  メールアドレス： hideyuki@din.or.jp                    #
#  ホームページ　： http://www.din.or.jp/~hideyuki/home/  #
#                                                         #
#  Copyright (c) 1998-1999 Hideyuki Chikada               #
#  All rights reserved.                                   #
#=========================================================#
#          この著作権表示は書き換えないで下さい           #
###########################################################


########## ↓ 初期設定(必ず書き換える) ↓ ##########

##### カウントファイル格納ディレクトリ用のディレクトリのパス
$datadir = './data/';

##### 画像ファイル用のディレクトリのパス
$imgdir = './img/';

##### カウンターを表示させるページのURL
#----------------------------------------------------------------#
# ここで指定した文字列を含むURLのページ以外からの不正な呼び出し  #
# を拒否します。例えば、下記のように指定した場合は、「http://www #
# .domain.or.jp/~userID/xxx.html」や「http://www.din.or.jp/~hide #
# yuki/xxxx/xxx.html」などのページでのみカウンターを表示させるこ #
# とが出来ます。　　　　　　　　　　　　　　　　　　　　　　　　 #
# 複数のページを指定するには、下のようにカンマで区切って下さい。 #
#----------------------------------------------------------------#
@mysite = ('http://www.mark-net.co.jp/test/gnexco/index.html','http://www.mark-net.co.jp/test/gnexco/index-mob.html');

########## ↑ 初期設定終了 ↑ ##########


#----------------------------------------------------------#
# ここから下をカスタマイズするには、Perlの知識が必要です。 #
# Perlについて十分な知識のない方は、変更しないで下さい。　 #
#----------------------------------------------------------#

##### 不正な呼び出しを拒否
$ENV{'HTTP_REFERER'} =~ s/\%7e/~/gi;
@pairs = split(/&/,$ENV{'QUERY_STRING'});
if ($#pairs < 1 || $#pairs > 2 || $pairs[0] !~ /^[1-8]$/) { &Error("x_param"); }

##### IPアドレスの取得（proxy対応）
if ($ENV{'HTTP_X_FORWARDED_FOR'} =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/) {
    $ENV{'REMOTE_ADDR'} = "$1.$2.$3.$4";
}

##### カウントファイルとロックファイル
$datadir = "$datadir$pairs[1]";
$lockfile = "$datadir\/lock";

##### 時間の取得
$now = time;

##### メイン処理
&OpenLock; &ReadFile;
foreach (0..$#datas) {
    @part = split(/,/,$datas[$_]);
    if ($part[1] eq $ENV{'REMOTE_ADDR'} && $now - $part[0] < 1800) {
        $flg = 1;
        last;
    }
}
if ($flg != 1) {
    &Count; &WriteFile;
}
&CloseLock;

foreach (8-$pairs[0]..7) {
    $img = substr($count,$_,1);
    $img = "$imgdir$pairs[2]$img.gif";
    push (@img,$img);
}
&PrintGif;

##### ロックファイル作成
sub OpenLock {
    $lockchek = 0;
    while (! mkdir($lockfile,0755)) {
        if (++$lockchek > 10) { &CloseOld; &Error("x_busy"); }
        sleep(1);
    }
}

##### 古いロックファイル消去
sub CloseOld {
    @stat = stat($lockfile);
    if ($now - $stat[9] > 90) { &CloseLock; }
}

##### ロックファイル消去
sub CloseLock {
    rmdir($lockfile);
}

##### カウントファイル読み込み（ファイル破損防止処理）
sub ReadFile {
    for ($filechek = 0; $filechek < 5; $filechek++) {
        if (! opendir(DIR,"$datadir")) { &CloseLock; &Error("x_open"); }
        $datafile = (grep(/^\d+\.dat$/,readdir(DIR)))[0];
        closedir(DIR);
        $count = substr($datafile,0,length($datafile)-4);
        $datafile = "$datadir\/$datafile";
        if (! open(DATA,"$datafile")) { &CloseLock; &Error("x_open"); }
        @datas = <DATA>;
        close(DATA);
        if (@datas) { last; }
        sleep(1);
    }
}

##### カウントファイル書き込み
sub WriteFile {
    if (! open(DATA,">$datafile")) { &CloseLock; &Error("x_open"); }
    print DATA @datas;
    close(DATA);
    rename($datafile,$newfile);
}

##### カウントアップ
sub Count {
    foreach (0..$#datas) {
        @part = split(/,/,$datas[$_]);
        if ($now - $part[0] > 1800 && $part[0]) {
            splice(@datas,$_,1);
            redo;
        }
    }
    $count++;
    $count = sprintf("%.8d",$count);
    $newfile = "$datadir\/$count\.dat";
    $add = "$now,$ENV{'REMOTE_ADDR'},\n";
    push(@datas,$add);
}

##### カウンター表示
sub PrintGif {
    require './gifcat.pl'; #-- Copyright (c) 1997,2001 http://tohoho.wakusei.ne.jp/ --#
    print "Content-type: image/gif\n\n";
    binmode(STDOUT);
    print &gifcat'gifcat(@img);

    exit;
}

##### エラー表示
sub Error {
    $img = "$imgdir$_[0].gif";
    @stat = stat($img);
    open(GIF,"$img");
    binmode(GIF);
    read(GIF,$img,$stat[7]);
    close(GIF);
    print "Content-type: image/gif\n";
    print "Content-Length: $stat[7]\n\n";
    binmode(STDOUT);
    print $img;

    exit;
}
