WEB相談室

Webページ作成に関しての何でも掲示板です。

タイトル:カウンターの設置のしかた

0:[投稿] saori [2002/07/20 23:21 ][環境:WIN+IE UNIX系+Perl]

こんにちわ、いつもお世話になっています。
カウンターを付けてi-modeの画面でみると画像が表示されない印の×がでます。
これ↓のせいだと思うんですけど、どうしたらいいですか?
<img src="counter/count.cgi?ID=omikuji;FILE=../i.html" width=1 height=1>

それから複数のページでどこにアクセスしてもカウントが取れるけれど、
同一IPからのアクセスは1時間は重複カウントをしないように
設定してあるはずなのですが、カウントされてしまいます。
ソースが長いんですけど貼ります。お願いします。
#! /usr/bin/perl

;# ↑ ◎ Perl処理系の[パス]  分からない場合はプロバイダに確認。
;#
;#   テキストカウンタ [CGIテキストカウンタ] ver.1.01 (Free)
;#   Copyright(C)2001 WiS. All Rights Reserved.
;#

#-----------------------------------------------------------------------------#
# ここから初期設定(サーバーへの設置方法は同梱の'readme.txt'をご覧ください)  #
#-----------------------------------------------------------------------------#
#
#   ●印の項目は必ず変更してください。
#   ○印の項目は主にレイアウト関連です。基本的に変更不要です。
#   △印の項目は上の項目を有効にしている場合のみ設定してください。
#   ◎印の項目はサーバー環境によって変更する必要があります。(1行目も含みます)
#
#  ・ ''内に記述しますが、'を入れたい場合は 中の'は \'にしてください。
#  ・ 行の頭に"#"を付けると、その行は無効になります。(コメントアウト)
#  ・ "$"、";"、"="等は間違って消さないようにしてください。エラーになります。
#  ・ 詳しくは本サイトの解説/FAQ等を参照してください。


# ○ ファイルロック [1:使う/0:使わない]
#    * 通常は使うを設定しておく。(mkdir方式ロック)
$uselock = 1;

# ○ 同一IPから一定時間カウントしない場合の有効[時間]
#    * 同一IP排除を使わない場合は0にする
$expires = 1;

# ○ 時間帯 (GMT=英国ロンドンとの時差 日本は9時間)
$time_zone = 9;

# ○ 日計カウンタを [1:取る/0:取らない]
#    * "*.count.daily"の名前で保存されます。
$daily_count = 1;


#---<パスについて>-------------------------------------------------------------
#
#  ・ パスとはサーバー内での場所です。httpで始まるURIとは違うものです。
#  ・ 相対パスとはスクリプトの場所を基準としたパスの指定です。
#      ../ => 1つ上のディレクトリ  ./ => 同じディレクトリ
#  ・ 絶対パスとはサーバー内の一番上のディレクトリを基準としたパスの指定です。
#      /usr/lib/sendmail  /home/foo/public_html/cgi-bin/script.cgi
#  ・ 仮想アドレスとはURIの一部分(ドメイン名以降)を指します。
#     http://www.domain.com/~foo/cgi-bin/script.cgi
#                          ^ ドメイン名の後のスラッシュ"/"以降の部分
#                             (/~foo/cgi-bin/script.cgi のこと)


# ○ カウンタ値を保存するファイルのディレクトリの[パス]
$data_dir = 'data/';

# ○ カウンターを貼り付けるページのURLの一部
#    * 外部からの利用を防止する場合に設定します。
#    * 複数のサイトから利用する場合は、"|"で区切ります。
#$set_url = 'www.provider.ne.jp/~foo/';


#-----------------------------------------------------------------------------#
# 初期設定ここまで (以下、修正不要。変更した場合は動作未保証&サポート対象外) #
#-----------------------------------------------------------------------------#

$expires *= 3600;

onError('OK') if ($ENV{'QUERY_STRING'} eq "");

#  今日の日付を取得
{
   local(@time) = gmtime(time + 3600 * $time_zone);
   $now_date = sprintf("%04d/%02d/%02d", $time[5]+1900, $time[4]+1, $time[3]);
}

#  クエリー文字列を取得
foreach (split /;/, $ENV{'QUERY_STRING'}) {
   local($key, $val) = split /=/, $_, 2;
   $STDIN{$key} = $val;
}

#  セキュリティー対策
&onError('パラメーターの値が不正です') if ($STDIN{'ID'}  =~ /(^\/|\.\.|[^\w\-\.\/])/);
&onError('パラメーターの値が不正です') if ($STDIN{'IMG'} =~ /(^\/|\.\.\/\.\.|[^\w\-\.\/])/);

if ($set_url && $ENV{'HTTP_USER_AGENT'} !~ /^DoCoMo/) {
   $set_url =~ s/\./\\./g;
   $SENV{'HTTP_REFERER'} = $ENV{'HTTP_REFERER'};
   $SENV{'HTTP_REFERER'} =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
   if ($SENV{'HTTP_REFERER'} !~ /$set_url/i) {
       &onError('HTTP_REFERERの値が不正です');
   }
}

$STDIN{'ID'} = 'default' if ($STDIN{'ID'} eq "");
$file = $data_dir . $STDIN{'ID'} . ".count";

count: {

   if (-f $file) {

       if (!&lock($file, $uselock)) {
           onError('busy');
       }
       onError('ファイルの読み込みに失敗しました') if (!open(IN, $file));
       ($total, $today, $ysday, $save_date) = split /\t/, <IN>;

       if ($expires) {
           last count if (!&logicalLock("$file.adr", $expires, $ENV{'REMOTE_ADDR'}, $ENV{'HTTP_USER_AGENT'}));
       }

       #  カウント
       $total ++;
       if ($save_date ne $now_date) {
           $ysday = $today;
           $today = 1;
           if ($daily_count) {
               if (open(OUT, ">>$file.daily")) {
                   print OUT "$save_date\t$ysday\n";
                   close(OUT);
               }
           }
       } else {
           $today ++;
       }

   #  初めてのカウント
   } else {
       $total = $today = 1;
       $ysday = 0;

       onError('busy') if (!&lock($file, $uselock));
   }

   #  ファイル更新
   onError('ファイルの書き込みに失敗しました') if (!open(OUT, ">$file"));
   print OUT "$total\t$today\t$ysday\t$now_date";
   close(OUT);

   if ($STDIN{'FIG'} > 4 && $STDIN{'FIG'} < 12) {
       $total = sprintf("%0$STDIN{'FIG'}d", $total);
       $today = sprintf("%0$STDIN{'FIG'}d", $today);
       $ysday = sprintf("%0$STDIN{'FIG'}d", $ysday);
   }

   if ($STDIN{'FIG'} == -1) {
       1 while $total =~ s/(\d+)(\d{3})/$1,$2/;
       1 while $today =~ s/(\d+)(\d{3})/$1,$2/;
       1 while $ysday =~ s/(\d+)(\d{3})/$1,$2/;
   }

   onError('ファイルのオープンに失敗しました') if (!open(IO, "+<$STDIN{'FILE'}"));
   while (<IO>) {
       s/<counter(\s+type="?total"?)>[\d\,]*<\/counter>/<counter$1>$total<\/counter>/i;
       s/<counter(\s+type="?today"?)>[\d\,]*<\/counter>/<counter$1>$today<\/counter>/i;
       s/<counter(\s+type="?ysday"?)>[\d\,]*<\/counter>/<counter$1>$ysday<\/counter>/i;
       $data .= $_;
   }
   seek(IO, 0, 0);
   print IO $data;
   close(IO);
}

&unlock($uselock);

print "Contnet-Type: image/gif\n";
print "Status: 204 No Content\n";
print "\n";

exit(0);


sub onError #($_)
{
   local($_) = $_[0];
   
   print "Content-Type: text/plain\n";
   print "\n";
   print;

   exit(0);
}

sub lockCheck #($file_name, $use_lock)
{
   local($file_name, $use_lock) = @_;
   local($lockFlag) = $file_name . ".lock";
   local($i) = 0;

   return 1 if (!$use_lock);
   rmdir($lockFlag) if (-d $lockFlag && time - (stat($lockFlag))[9] > 60);
   while (-d $lockFlag) {
       select(undef, undef, undef, 1);
       return 0 if (++ $i >= 3);
   }
   return 1;
}

sub lock #($file_name, $use_lock)
{
   local($file_name, $use_lock) = @_;
   local($lock_flag) = $file_name . ".lock";

   if ($use_lock) {
       local($i) = 0;
       return -1 if (!-d $file_name);
       rmdir($lock_flag) if (-d $lock_flag && time - (stat($lock_flag))[9] > 60);
       while(!mkdir($lock_flag, 0755)) {
           select(undef, undef, undef, 1);
           return 0 if (++ $i >= 3);
       }
       return 1;
   }
   return 1;
}

sub unlock
{
   rmdir("$_[0].lock") if (-d "$_[0].lock");
}

sub logicalLock #($file_name, $timeout, @recode)
{
   local($file_name, $timeout, @record) = @_;
   local($flag) = 1;
   local(@array);

   if (!-s $file_name || time - (stat($file_name))[9] > $timeout) {
       $flag = 1;
   } elsif (-s $file_name && open(IN, $file_name)) {
       while (<IN>) {
           s/\r\n|\r|\n//;
           local($time, @field) = split /\t/o;
           if ($flag) {
               for (0 .. $#record) {
                   if ($record[$_] eq $field[$_]){
                       $flag = 0;
                   } else {
                       $flag = 1;
                       last;
                   }
               }
               if (!$flag && time - $time > $timeout) {
                   $flag = 1;
               }
           } elsif (time - $time > $timeout) {
               $timeout = 1;
               next;
           }
           push(@array, "$_\n");
       }
       close(IN);
   }
   unshift(@array, time . "\t" . join("\t", @record) . "\n") if ($flag);
   if ($flag || $timeout) {
       return -1 if (!open(OUT, ">$file_name"));
       print OUT join "", @array;
       close(OUT);
   }
   return $flag;
}



1:[質問] saori [2002/07/20 23:25 ]

http://www.komonet.ne.jp/~gift/cgi-bin/i/i.html
カウンターをつけているページです
URLを出すのが恥ずかしい(〃∇〃) ので、
どうしようかと思ったんですけど、
見ていただいたほうがいいかも?です。


2:[回答] EYE's [MAIL] [2002/07/21 16:21 ]

EYE'sです。
的確な回答になるかわからないんですけど、まず、i-modeではなく、普通にパソコンで表示されるか確認してみてください。
また、カウンターの呼び出す際に、imgTAG に width&height=1 とされているようなのですが、本当に1ピクセルですか?
それと、同一IPからカウントしないというのも、正確に分析していませんが、多分、以下のような場合からではないでしょうか?
1.特定1のIP Addrにてアクセス。
2.特定2のIP Addrにてアクセス。
3.「1.」の特定1のIP Addrにて一時間以内にアクセス。
そうした場合、カウントされる。ではないでしょうか?
実際にどこから配布されているCGIなのか教えていただけませんでしょうか?


3:[質問] saori [2002/07/21 18:42 ]

>i-modeではなく、普通にパソコンで表示されるか確認してみてください。
パソコンでは×印は表示されていません。
i-modeで確認すると×印が表示されます。

>imgTAG に width&height=1 とされているようなのですが、本当に1ピクセルですか?
そこでは画像は使っていません。
なぜimgタグでcgiを呼ぶのかは、わかりませんが
頂いてきたところの仕様です。

ここで配布されているカウンターです。
http://www-power.net/cgi/counter/text_counter/

>1.特定1のIP Addrにてアクセス。
>2.特定2のIP Addrにてアクセス。
>3.「1.」の特定1のIP Addrにて一時間以内にアクセス。
>そうした場合、カウントされる。ではないでしょうか?
恥ずかしいのですが勉強不足でおっしゃっている意味がわかりません。
自分でページをリロードしてみるとカウントが増えるます。

その他の条件としては、
i-modeで使いたいのでJavaScriptを使うカウンターは使えないです。

サーバーの都合でSSIは.shtmlに設置することになっているので
i.html(TOPページ)1枚だけのファイルの拡張子を変えても、
それにリンクしている180枚くらいのファイルを書き換えることになります。
各ページのファイルの拡張子を変えるとなると作業が大変なので避けたいです。
http://www.komonet.ne.jp/~gift/cgi-bin/i/
この↑下に49個のサブディレクトリがあって
その一個のサブディレクトリに最低でも2つのCGIと1枚のindex.htmlがあって
そのすべてからi.html(TOPページ)にリンクがあります。

膨大なファイルを手作業で書き換える根性があるか、
一気に書き換えられるスキルがあれば解決はするんですが・・・・
なので、SSIのカウンターはできれば避けたいです。

お手数をおかけしますがお願いします。


4:[回答] EYE's [MAIL] [2002/07/21 18:49 ]

EYE'sです。
えっと、imgTAGでカウンターを設置する理由としては、画像の0〜9を並べて、カウント数表示するためです。
配布されているところから僕も試してみますので、いましばらくお待ちください。結果がわかり次第、また書き込みします。


5:[質問] saori [2002/07/21 18:59 ]

えーー!そこまでしていただけるなんて(絶句)
ホントにありがとうございます。
i-modeで使いたいのでパケット代をおさえるためにテキストで表示したいです。


6:[回答] EYE's [MAIL] [URL] [2002/07/21 20:07 ]

EYE'sです。
お待たせしました。

えっと、まず先に上の文章を訂正させてください。
imgTAGで呼び出すのは確かに画像を用いてのカウンターが主なのですが、今回のようなテキストカウンターで、なおかつ、cgi側の処理でhtmlに埋め込む形もありました。
申し訳ございませんでした。

さっそく僕のサーバ側に設置してみました。上のURLを直接のぞいていただきたいのですが、お願いします。

補足です。NTT Docomo i-modeの場合どうしても一回一回カウントしてしまいます。その理由は、
そのページを「見に行く」のではなく、そのページを「取得する」
といったもので、取得しにいくたびにIP Addrが変わってしまいます。僕も前にjsky,i-mode,ezweb,dot-i,h"用のサイト制作した際にこれの事情を知って結構ショックでした。ま〜泣くしかったです。
。・°°・(>_<)・°°・。

あと、このcgiの悪口というわけではないのですが、ちょこっと重たい気もします。僕的には「とほほのWWW入門」様で配布されているカウンターのほうが好きですね。あ、ここの部分は余談でした。すいません。

では何かわからなければまた聞いてください。


7:[回答] EYE's [MAIL] [URL] [2002/07/21 20:33 ]

追記です。
saori様がお使いのサーバで、.htaccessなどの設置はできますでしょうか?
.htaccessを使うと(サーバの仕様にもよりますが)、そのディレクトリに一番最初に表示させるファイル、例えばデフォルトですと、index.html が主ですが、これより先に、index.cgi などを表示させることも可能です。
また、デフォルトでは .shtml しかSSIが使えないとなっているものでも、.html なんかでもSSIを使うようにすることができます。
ま〜.htaccess でも設定(有効)できるサーバとできないサーバがありますので、なんともいえませんが、使えるサーバは、ハウジング含めてシェアリングサーバぐらいなものでしょうか。


8:[完了] saori [2002/07/21 20:41 ]

拝見しました。教えていただいたとおりで、
パソコンでリロードしてもカウントは増えませんが
i-modeで取得するたびにカウントが増えました。
仕様ではしかたないですね(TT)

もう少しいろいろなところを見て勉強を続けながら、
どうするかよく考えてみます。
ありがとうございました。


9:[完了] saori [2002/07/21 20:53 ]

共同でページを作っている方のサーバーなのですが
わたし自身は.htaccessの設定についても知識がありませんのでこれから調べてみます。

将来はできたらキャリアーごとにページを作って
index.cgiで飛ばすことも考えていましたのでとっても参考になりました。
ご親切に教えていただいてとってもうれしいです。
お世話になりました。

回答(必須): 状態:

お名前(必須):

e-mail:

URL:




[戻る]

ChaichanPAPA's World