実行結果はこちらから
二重アクセス防止用のログファイルはこちらから参照できます
以下に改造したカウンタのソースを載せる。
改良した点は、二重アクセスの防止、キリ番、ゾロ番判定アルゴリズムを追加し、キリ番については下$kiriketa桁が0ならキリ番扱いとなる。又、キリ番、ゾロ番なら画像が変わるように改良した。
画像はMacromediaのFireWorksにて作成した。
1 #!/usr/bin/perl
2
3 print "Content-type:text/html\n\n";;
4 #------------------------
5 $time=time();
6 ($sec,$min,$hour,$mday,$mon,$year)=localtime();
7 $time=sprintf("%04d/%02d/%02d/%02d/%02d/%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec);
8 #-------------------------
9 #-------二重アクセス防止用-------
10 $sec=10;#何秒間二重アクセスを防止するか
11 $perm=1;
12 $edit="";
13 open(file,"+<double_access.dat")||die "logerror";
14 flock($file,2);
15 $new=1;
16 while($line=<file>){
17 @line=split(/\s/,$line);
18 if($ENV{'REMOTE_ADDR'} eq $line[0]){
19 $new=0;
20 @buf=Compare($time,$line[1]);
21 if($buf[1]>=$sec){
22 $edit=$edit.$ENV{'REMOTE_ADDR'}." ".$time;#ログの更新
23 }elsif(($buf[1]<0)&&(($buf[1]+(24*3600))>=$sec)){
24 $edit=$edit.$ENV{'REMOTE_ADDR'}." ".$time;#ログの更新
25 }else{
26 $perm=0;#多重カウントの禁止
27 $edit=$edit.$line;
28 }
29 }else{
30 $edit=$edit.$line;
31 }
32 }
33 if($new==1){#新しい人なら新たに追加
34 $edit=$edit."\n".$ENV{'REMOTE_ADDR'}." ".$time;
35 }
36 seek(file,0,0);
37 print file $edit;
38 @edit=split(/\n/,$edit);
39 flock(file,8);
40 close(file);
41 #----------時間の計算を行なう部分(長いのでサブルーチンの形にした)---------
42 sub Compare{
43 local($one,$two)=@_;
44 @one=split(/\//,$one);
45 @two=split(/\//,$two);
46 for($i = 0; $i <= 5 ; $i++){
47 $one[ $i ]=$one[ $i ]- $two[ $i ];
48 }
49 $sum[0]=(365*$one[0])+($one[1]*31)+$one[2];
50 $sum[1]=(3600*$one[3])+(60*$one[4])+$one[5];
51 return @sum;
52 }
53
54 $data_file=countdata;
55 open(KAZU,"+<$data_file")||die "CounterRead/WriteError.......\n";
56 flock(KAZU,2);
57 $counter_new=<KAZU>;
58 if($perm==1){
59 $counter_new++;
60 }
61 seek(KAZU,0,0);#先頭へ移動
62 print KAZU $counter_new;
63 close(KAZU);
64 flock(KAZU,8);
65 #-------------ログ書き出し
66 if($perm==1){
67 open(file,">>./logfile.dat")||die "LogReadError...........\n";
68 flock(file,2);
69 if($ENV{'REMOTE_ADDR'}){
70 print file $counter_new." ".$ENV{'REMOTE_ADDR'}." ".$time."\n";
71 }else{
72 print "ImageTraining";
73 }
74 close(file);
75 }
76 #------- キリ番チェック---
77 $kiriketa=3;#キリ番の桁数を設定
78 $buf=$counter_new;
79 $int = 0;
80 $div = 1;
81 $kiri= 0;
82 $flag= 1;
83 $kirikana=0;#キリ番なら1,そうでなかったら0
84 while($flag){
85 $ex=$buf%$div;
86 if($ex==0){
87 $kiri++;
88 }elsif($kiri>=$kiriketa){
89 $flag=0;
90 $kirikana=1;
91 }else{
92 $flag=0;
93 }
94 $int+=1;
95 $div*=10;
96 }
97 #------- ゾロ番チェック
98 $buf=$counter_new;
99 $int = 0;
100 $div = 10;
101 $bb = $buf%$div;
102 $zorokana=1;#ゾロ番なら1,そうでなかったら0
103 while($int!=$counter_new){
104 $int=$buf%$div;
105 $div*=10;
106 if($bb==$int){
107 $bb=$bb*10+($buf%10);
108 $zorokana=1;
109 }else{
110 $zorokana=0;
111 last;
112 }
113 }
114 #------- 実行確認の表示 -------
115 #print "Content-type:text/html\n\n";
116 print "<HTML><HEAD><TITLE>OK</TITLE></HEAD>\n";
117 print "<BODY BGCOLOR=\#ffbbaa>\n";
118 print "<CENTER>\n";
119 print "<H1>ThankYou.</H1>\n";
120 print "<H2>---Counter---</H2>\n";
121 #カウンターの新しい数値の表示。
122 print "$counter_new\n";
123 $mode="/abunormal/";
124 if($kirikana==1){
125 $mode="/akaran/";
126 print "<h1>キリ番なら赤ランだぜぇ〜</h1>";
127 }
128 if($zorokana==1){
129 $mode="/aoran/";
130 print "<h1>ゾロ番なら青ランだぜぇ〜</h1>";
131 }
132
133 $counter_new=sprintf("%05d",$counter_new);
134 for($i=0;$i<length($counter_new);$i++){
135 print "<img src=\"./machine/";
136 print $mode.substr($counter_new,$i,1).".png\" alt=\"counter\">";
137 }
138 print "</CENTER>\n";
139 print "</BODY></HTML>\n";
1行目:おまじない
5〜7行目:今日の日時を作成する。
9〜40行目;前回訪れた日付をdouble_access.datから検索し、そのログがあれば今日の日付と比較し、
前回のアクセスより$sec以上の差があればカウントし、それ以下なら二重カウントとして扱う。
41〜52行目:時間差を計算するサブルーチン。返り値は配列型で日付の差と時間の差を返す。
53〜75行目:カウンタの値を読み出し、$perm(二重アクセスかそうでないかを表す)が1ならカウントアップし、そうでなかったらカウントアップしない。また、クライアントのログもついでに書き出している。
75〜113行目:キリ番ゾロ番の判定を行なっている。アルゴリズムはキリ番の場合、0が何桁目迄続くかをカウントし、$kiriketaとひたすら比較する。ゾロ番は一桁目の値とひたすら比較するようにして判断するようにした。