実行結果はこちらから
二重アクセス防止用のログファイルはこちらから参照できます 以下に改造したカウンタのソースを載せる。
改良した点は、二重アクセスの防止、キリ番、ゾロ番判定アルゴリズムを追加し、キリ番については下$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とひたすら比較する。ゾロ番は一桁目の値とひたすら比較するようにして判断するようにした。

indexに戻る
課題7