アクセスカウンタ
 

SSI(Server Side Include)を利用する

このサンプルプログラムはSSIが利用できる場合に有効です。
SSIはHTMLの中に記述され
 
<!--#exec cgi="/cgi-bin/ssi_count.cgi"-->

のような形式です。
サーバの種類や設定にもよりますが、HTMLの拡張子は.shtmlにする必要があるかもしれません。あるいはHTMLがあるディレクトリに.htaccessというファイルに設定を記述する場合もあります。
 
ssi_count.cgi
#!/usr/bin/perl
#
# ssi_count.cgi
#
# (C) Kaoru Fujita
#
use lib './lib';
require 'util.pl';

#
# 定数
#
$Title = 'SSIカウンター サンプルプログラム';
$Location = './tmp';
$File = $Location.'/count';


$thePage = $ENV{'DOCUMENT_URI'};
$thePage =~ s/\//_/g;                           # / を _ に置き換える
$file = "$Location/$thePage.count";

if (-e $file) {
        openLock(CNT, "+<$file")
                or exitError("ファイル $file がオープンできません。");
        $count = <CNT>;
        seek(CNT, 0, 0);
}
else {
        openLock(CNT, ">$file")
                or exitError("ファイル $file が作成できません。");
        $count = 0;
}

$count++;

print CNT $count;

closeUnlock(CNT, $file);

print $count;

exit(0);

#--End of ssi_count.cgi

 
ssi_count.shtml
<HTML>
<HEAD>
<TITLE>SSIカウンタ サンプル</TITLE>
</HEAD>
<BODY>
<!--#exec cgi="/cgi-bin/ssi_count.cgi"--> 回目のアクセス
</BODY>
</HTML>

[サンプルプログラムの実行]
 

SSIを利用しない場合

この例は直接CGIを実行する場合です。

[サンプルプログラムの実行]
 
 
count.cgi
#!/usr/bin/perl
#
# count.cgi
#
# (C) Kaoru Fujita
#
use lib './lib';
require 'util.pl';

#
# 定数
#
$Title = 'カウンター サンプルプログラム';
$Location = './tmp';
$File = $Location.'/count';
$CharSet = 'Shift_JIS';

if (-e $File) {
        openLock(CNT, "+<$File")
                or exitError("ファイル $File がオープンできません。");
        $count = <CNT>;
        seek(CNT, 0, 0);
}
else {
        openLock(CNT, ">$File")
                or exitError("ファイル $File が作成できません。");
        $count = 0;
}

$count++;

print CNT $count;

closeUnlock(CNT, $File);

while (<DATA>) {
 s/__%COUNT%__/$count/;
 print;
}

exit(0);

__END__
Content-type: text/html

<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$CharSet">
<TITLE>$Title</TITLE>
</HEAD>
<BODY>
<P>
<CENTER>__%COUNT%__ 回目のアクセスです。</CENTER>
<P>
</BODY>
</HTML>

<IMG>タグで画像のアクセスカウンタにする場合

「CGIの起動方法」のところで「HTMLのイメージ<IMG>タグを使って起動する」ことの説明がありますが、この方法を利用します。ただし、カウントの数字の数だけ、CGIが起動されるのでサーバの負荷は大きくなり、表示も遅くなります。また、イメージはブラウザでキャッシングされるので、ほとんどの場合リロードしてもカウントアップしません(ブラウザを一度終了させるとカウントアップします)。

[サンプルプログラムの実行]
 
 
img_count.cgi
#!/usr/bin/perl
#
# img_count.cgi
#
# (C) Kaoru Fujita
#
use lib './lib';
require 'util.pl';

#
# 定数
#
$Title = 'イメージカウンタ サンプルプログラム';
$Location = './tmp';
$File = $Location.'/img_count';
$ImgLoc = './images';
$ImgType = 'gif';

*data = parseInput();

# テスト用
#$data{'Col'} = '1';

$col = $data{'Col'};

if (-e $File) {
        openLock(CNT, "+<$File")
                or exitError("ファイル $File がオープンできません。");
        $count = <CNT>;
        seek(CNT, 0, 0);
}
else {
        openLock(CNT, ">$File")
                or exitError("ファイル $File が作成できません。");
        $count = 0;
}

# 1の位のときだけカウントアップ
$count++ if ($col == 1);

print CNT $count;

closeUnlock(CNT, $File);

@num = split(//, $count);               # 各桁を取り出す
@num = reverse(@num);                   # 桁を配列のインデックスに対応させる
                                                                # ために逆順に並べる

# 桁数以上のところは 0 とする
$num = defined($num[$col-1]) ? $num[$col-1] : 0;

sendImage($num);

exit(0);


sub sendImage
{
        my($number) = @_;

        # イメージファイルのオープン
        open(IMG, "$ImgLoc/$number.$ImgType") or
                exitError(qq(ファイル $ImgLoc/$number.$ImgType がオープンできません。));

        # Windows のようなバイナリとテキストを区別する場合は
        # テキストモードでは \r\n が \n に変換されてしまうのを
        # 避ける。UNIX では意味がない。
        binmode IMG;
        binmode STDOUT;

        # イメージの出力
        print qq(Content-type: image/$ImgType\n\n);
        print while (<IMG>);

        # イメージファイルのクローズ
        close(IMG);
}

#--End of img_count.cgi

 
 
img_count.html
<HTML>
<HEAD>
<TITLE>イメージカウンタ</TITLE>
</HEAD>
<BODY>
<IMG SRC="/cgi-bin/img_count.cgi?Col=5">
<IMG SRC="/cgi-bin/img_count.cgi?Col=4">
<IMG SRC="/cgi-bin/img_count.cgi?Col=3">
<IMG SRC="/cgi-bin/img_count.cgi?Col=2">
<IMG SRC="/cgi-bin/img_count.cgi?Col=1">
</BODY>
</HTML>