GIFカウンタ 《 画像連結型 》

《 INDEX 》    《 HOME 》   

■ 概要

 《 必要条件 》 

 《 機能 》 

 《 呼出し方 》 

○ノーマルな呼出し 《 indexのデータファイルが使用され6桁で表示されます 》

<IMG SRC="スクリプトパス/counter.cgi">


○データファイルを変更する 《 perlのデータファイルが使用されます、これで複数のサイトに対応します。 》

<IMG SRC="スクリプトパス/counter.cgi?key=perl">


○桁数を変更する 《 indexのデータファイルが使用され8桁で表示されます 》

<IMG SRC="スクリプトパス/counter.cgi?keta=8">


○データファイル、桁数を変更する 《 perlのデータファイルが使用され4桁で表示されます 》

<IMG SRC="スクリプトパス/counter.cgi?key=perl&keta=4">


 《 完成版サンプル 》 


■ 処理の手順

カウンタ処理フロー

■ ソースの解説

初期処理


#!/usr/local/bin/perl5

#################################################
# 初期設定 #
#################################################

#
# gifcatへのパス《デフォルトは同一ディレクトリ》
#
$gifcat= './' ;
#
# datファイルへのパス《デフォルトは同一ディレクトリ》
#
$dat_path= './' ;
#
# GIFファイルへのパス《gifディレクトリ以下》
#
$gif_path= 'gif/' ;



《 解説 》

  1. Perlへのパスはプロバイダの環境によって異なります、各プロバイダの設定を参考にして下さい。
    詳しくは 《CGI作成講座》 を参照

    #!/usr/local/bin/perl5


  2. ここではgifcatへのパスdatファイルへのパスGIFファイルへのパス、を指定します。 《ダウンロードと設置法》 の指定に合わせていますが変更したい場合は変えて下さい。

    #
    # gifcatへのパス《デフォルトは同一ディレクトリ》
    #
    $gifcat= './' ;
    #
    # datファイルへのパス《デフォルトは同一ディレクトリ》
    #
    $dat_path= './' ;
    #
    # GIFファイルへのパス《gifディレクトリ以下》
    #
    $gif_path= 'gif/' ;


Main処理

# Query復元処理
%query = &decode;

# datファイル名
$file_name = $query{key}.'.dat' ;

# 表示するカウンタの桁数
$keta = $query{keta};

# データファイルのフルパス
$dat_file = $dat_path.$file_name;

# 新規キーの作成
unless(-e $dat_file){

    open( FH, ">$dat_file") || &error_exist ;
    print FH 0 ; close(FH) ;
    chmod(0666,$dat_file) ;

}

# ロック開始
$lf = &lock || &error_exist ;

    # 現在のデータファイルの読込み
    open( FH, "<$dat_file") || &error_exist ;
    $data = <FH> ;
    close(FH);

    # データファイルの足し込み
    chomp $data; $data++;

    # 更新データの出力
    open( FH, ">$dat_file") || &error_exist ;
    print FH $data;
    close(FH);

# ロック解除
&unlock($lf);

# GIFデータ出力処理
&put_gif($data, $keta);

exit;



《 解説 》

  1. スクリプトに渡されたクエリの解読します。この処理の詳細は後で解説しますが、この処理によってハッシュ《query》にデータファイル、表示桁数等の情報が格納されます。

    # Query復元処理
    %query = &decode;


  2. クエリで与えられたキー値のデータファイルが無い場合、新規でデータファイルを作成します。CGIによって更新されるファイルなのでパーミッションは[0666]とします。

    # 新規キーの作成
    unless(-e $dat_file){

        open( FH, ">$dat_file") || &error_exist ;
        print FH 0 ; close(FH) ;
        chmod(0666,$dat_file) ;

    }


  3. データファイルの内容に+1して更新します。複数のユーザから同時にリクエストがあった場合を考えファイルをロックを行います。ロック処理を呼び出してから、ロック解除処理が呼び出されるまでロックされている状態です。

    # ロック開始
    $lf = &lock || &error_exist ;  #ロック期間の始まり(^o^)//"""

        # 現在のデータファイルの読込み
        open( FH, "<$dat_file") || &error_exist ;
        $data = <FH> ;
        close(FH);

        # データファイルの足し込み
        chomp $data; $data++;

        # 更新データの出力
        open( FH, ">$dat_file") || &error_exist ;
        print FH $data;
        close(FH);

    # ロック解除
    &unlock($lf);  #ロック期間の終了(^o^)//"""


  4. GIFデータ出力処理を呼び出します、引数としてカウントされた人数と表示する桁数を渡します。
    ※サブルーチンの内容は後で説明してあります

    &put_gif($data, $keta);


クエリ復元処理

sub decode {

    if($ENV{REQUEST_METHOD} eq 'GET' ){
        $str_query = $ENV{QUERY_STRING};
    } else {
        read(STDIN,$str_query,$ENV{CONTENT_LENGTH});
    }

    foreach ( split('&', $str_query ) ){

        my ($name, $value) = split('=',$_,2);
        $value =~ s/\+/ /g;
        $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
        $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;

        # タグの除去
        $value =~ s/<//g;
        $value =~ s/>//g;
        $tmp{$name} = $value;
    }

    # 省略時デフォルトで"index"を使用する。
    $tmp{key} = $tmp{key} || 'index' ;

    # 桁数は1〜10まで
    unless($tmp{keta} >= 1 && $tmp{keta} <= 10){
        $tmp{keta} = 6 ;
    }

    return %tmp;

}


《 解説 》

  1. タグが渡された場合はタグ文字を除去します。

            # タグの除去
            $value =~ s/<//g;
            $value =~ s/>//g;


  2. 複数のファイルで使用する為にデータファイルを分けています。何も情報が与えられなかった時はデフォルトとしてindexが使用されます。

    index以外をカウントする時は <IMG SCR="counter.cgi?key=perl">の用に呼び出します。

        # 省略時デフォルトで"index"を使用する。
        $tmp{key} = $tmp{key} || 'index' ;


  3. 表示される桁数を指定します。何も指定していなければデフォルトで6になります。その他の値が入力された場合も6になります。

        # 桁数は1〜10まで
        unless($tmp{keta} >= 1 && $tmp{keta} <= 10){
            $tmp{keta} = 6 ;
        }


ロックの開始処理

sub lock{

    my %lf=(lockdir => './lockdir/',
            timeout => 15,
            trytime => 10 );

    $lf{fname} = shift || 'lockfile' ;

    $lf{source} = $lf{lockdir} . $lf{fname};

    for ( my $i = 0; $i < $lf{trytime}; $i++ , sleep 1 ) {

        if( rename( $lf{source}, $lf{lockname} = $lf{source}.time )){
            return \%lf ;
        }

    }

    my @flist = glob($lf{lockdir}.'*' ) ;

    foreach ( @flist ) {

        if ( /^$lf{fname}(\d+)/ ){

            if ( time - $1 > $lf{timeout}
                    and
            rename ( $lf{lockdir} . $_ , $lf{lockname} = $lf{source} . Time ) ){

                return \%lf
                
            }

             last;

        }
    }

    undef;

}


ロックの解除処理

sub unlock{

    rename ( $_[0]->{lockname}, $_[0]->{source} );

}


GIF出力処理

sub put_gif {

# gifcatの読込み
require $gifcat.'gifcat.pl';

    my($cnt,$keta) = @_;

    my @cnt = reverse(split(//,$cnt));
    
    my @gif = ();

    for(0..$keta -1 ){

        unshift @gif , $gif_path .( $cnt[$_] || 0 ).'.gif';

    }
    
    binmode(STDOUT);
    
    print "Content-type: image/gif\n\n";
    print &gifcat'gifcat(@gif);

}


《 解説 》

  1. 人数を一桁ずつ配列へ代入します。

    my @cnt = reverse(split(//,$cnt));


  2. 上の処理で作成した配列を元にgifcatでへ渡す配列を作成します、その桁の数値がまだ無い場合は0で作成されます。

        for(0..$keta -1 ){

            unshift @gif , $gif_path .( $cnt[$_] || 0 ).'.gif';

        }


  3. Win系プラットフォームの為に標準出力をバイナリモードへ変更します。

    binmode(STDOUT);


  4. ヘッダの出力とgifcatの呼出しを行います。

    "Content-type: image/gif\n\n";
    print &gifcat'gifcat(@gif);


エラー処理

sub error_exist {

    # エラー用GIF(0)の定義
    @err_gif = ('47','49','46','38',
                '39','61','0F','00',
                《GIFのバイナリ16進、以下略》);

    binmode(STDOUT);

    print "Content-type: image/gif\n\n";

    foreach (@err_gif) {

        $data = pack('C*',hex($_));
        print $data;

    }

    exit;

}



■ 完成版のダウンロードと設置法



《 INDEX 》    《 HOME 》   

Copyright (C) 2000-2004 Knave
http://www.site-cooler.com/