#!/usr/local/bin/perl # ↑この行をプロバイダの環境にあわせて変更してください。 # たとえば BIGLOBE の場合は #!/usr/mesh/bin/perl となります。 # #! の前には空行もスペース文字も入れないようにしてください。 #================================================================== # 名称: wwwcount.cgi Ver2.7 # 作者: とほほ ( s-hasei@mtg.biglobe.ne.jp ) # 最新版入手先: http://www2e.biglobe.ne.jp/~s-hasei/ # 取り扱い: フリーソフト。利用/改造/再配布可能。確認不要。 #================================================================== #================================================================== # 使いかた: #================================================================== # (書式1) wwwcount.cgi # CGIが使用できるかテストを行う。 # # (書式2) wwwcount.cgi?text # カウントアップを行い、カウンタをテキストで表示する。 # # (書式3) wwwcount.cgi?gif # カウントアップを行い、カウンタをGIFで表示する。 # # (書式4) wwwcount.cgi?hide+xxx.gif # カウントアップを行い、xxx.gifを表示する。 #================================================================== # 履歴: #================================================================== # 1997.03.16 Ver1.0 # ・初版 # 1997.04.10 Ver1.1 # ・スクリプトが途中で停止してもロックファイルが残らないように # シグナル処理を追加した。 # 1997.04.28 Ver2.0 # ・大幅改造 # ・テスト機能を付加した。 # ・GIFファイルを連結して表示するようにした。 # 1997.05.08 Ver2.1 # ・ロックファイルが残ってしまうバグを修正。 # 1997.05.11 Ver2.2 # ・%7E や \~ を ~ と表示するようにした。 # ・自分自身のURLからのFROMは表示しない機能を追加した。 # 1997.07.06 Ver2.3 # ・10分以上古いロックファイルを消すようにした。 # 1997.09.14 Ver2.4 # ・前日アクセスした人が再アクセスするとカウントアップされない # ことがあるというバグを修正。 # ・メールのサブジェクトに前日のアクセス件数を表示するようにした。 # 1997.10.19 Ver2.5 # ・自己診断機能の強化。 # 1998.02.15 Ver2.6 # ・セキュリティ改善。hide+で.gifしか読み取れないようにした。 # 1998.09.20 Ver2.7 # ・SSIで使用する際に text の引数を不要とした #================================================================== # カスタマイズ: #================================================================== # # SSIのテキストモードで使用する場合は、$mode = "text"; としてください。 # $mode = ""; # # 表示桁数を例えば5桁に指定する場合は「$figure = 5;」のように指定する。 # 自動調整するには「$figure = 0;」と指定する。 # $figure = 5; # # ファイルロック機能をオンにする場合は「$do_file_lock = 1;」とする。 # ファイルロック機能をオフにする場合は「$do_file_lock = 0;」とする。 # $do_file_lock = 1; # # 同アドレスチェック機能をオンにする場合は「$do_address_check = 1;」とする。 # 同アドレスチェック機能をオフにする場合は「$do_address_check = 0;」とする。 # $do_address_check = 0; # # レポート機能を使う場合は「$mailto = "abc@xxx.yyy.zzz";」のように自分の # メールアドレスを設定する。また、/usr/local/bin/nkf, /usr/lib/sendmail # が存在することを確認しておく。別の場所にある場合は、$nkf, $sendmail も # 適切に変更する。詳細メールの場合は「$account_detail = 1;」とし、アクセ # ス件数のみをメールする場合は「$account_detail = 0;」とする。 # $mailto = ''; $nkf = '/usr/local/bin/nkf'; $sendmail = '/usr/lib/sendmail'; $account_detail = 1; # # このアドレスにマッチするサイトからの FROM は表示しない。 # $my_url = ''; #================================================================== # 処理部: #================================================================== # # 関連するファイルを洗い出しておく # このCGIスクリプトのファイル名の拡張子を変更したものになる。 # $file_count = "wwwcount.cnt"; $file_date = "wwwcount.dat"; $file_access = "wwwcount.acc"; $file_lock = "lock/wwwcount.loc"; # # CGIが使用できるかテストを行う。 # if ($ARGV[0] eq "test") { print "Content-type: text/html\n"; print "\n"; print "\n"; print "Test\n"; print "\n"; print "OK. CGIスクリプトは動作可能です。\n"; print "
\n"; if ($mailto ne "") { if (! -f $nkf) { print "
NG. $nkf が存在しません。\n"; } if (! -f $sendmail) { print "
NG. $sendmail が存在しません。\n"; } } if (-d $file_lock) { print "
NG. $file_lock が残っています。\n"; } if (! -r $file_count) { print "
NG. $file_count が存在しません。\n"; } elsif (! -w $file_count) { print "
NG. $file_count が書き込み可能ではありません。\n"; } if (! -r $file_date) { print "
NG. $file_date が存在しません。\n"; } elsif (! -w $file_date) { print "
NG. $file_date が書き込み可能ではありません。\n"; } if (! -r $file_access) { print "
NG. $file_access が存在しません。\n"; } elsif (! -w $file_access) { print "
NG. $file_access が書き込み可能ではありません。\n"; } print "\n"; print "\n"; exit(0); } # # 引数を解釈する # for ($i = 0; $i <= $#ARGV; $i++) { if ($ARGV[$i] eq "text") { $mode = "text"; } elsif ($ARGV[$i] eq "gif") { $mode = "gif"; } elsif ($ARGV[$i] eq "hide") { $mode = "hide"; $giffile = $ARGV[++$i]; if (!($giffile =~ /\.gif$/i)) { exit(1); } if ($giffile =~ /[<>|&]/) { exit(1); } } elsif ($ARGV[$i] eq "ref") { $reffile = $ARGV[++$i]; } } # # 環境変数TZを日本時間に設定する # $ENV{'TZ'} = "JST-9"; # # 途中で終了してもロックファイルが残らないようにする # sub sigexit { rmdir($file_lock); exit(0); } $SIG{'INT'} = $SIG{'HUP'} = $SIG{'QUIT'} = $SIG{'TERM'} = "sigexit"; # # ロック権を得る # if ($do_file_lock) { foreach $i ( 1, 2, 3, 4, 5, 6 ) { if (mkdir("$file_lock", 755)) { # ロック成功。次の処理へ。 last; } elsif ($i == 1) { # 10分以上古いロックファイルは削除する。 ($mtime) = (stat($file_lock))[9]; if ($mtime < time() - 600) { rmdir($file_lock); } } elsif ($i < 6) { # ロック失敗。1秒待って再トライ。 sleep(1); } else { # 何度やってもロック失敗。あきらめる。 exit(1); } } } # # カウンターファイルからカウンター値を読み出す。 # open(IN, "< $file_count"); $count = ; close(IN); # # 日付ファイルから最終アクセス日付を読み出す。 # open(IN, "< $file_date"); $date_log = ; close(IN); # # 今日の日付を得る # ($sec, $min, $hour, $mday, $mon, $year) = localtime(time()); $date_now = sprintf("%02d/%02d/%02d", $year, $mon + 1, $mday); $time_now = sprintf("%02d:%02d:%02d", $hour, $min, $sec); # # 日付が異なる、つまり、今日初めてのアクセスであれば # if ("$date_log" ne "$date_now") { # # アクセスログをメールで送信する # if ($mailto ne "") { $tmp_count = 0; open(IN, "< $file_access"); while () { if (/^COUNT/) { $tmp_count++; } } close(IN); open(OUT, "| $nkf -j | $sendmail $mailto"); print OUT "To: $mailto\n"; print OUT "From: wwwcount\n"; print OUT "Subject: ACCESS $date_log $tmp_count\n"; print OUT "\n"; if ($account_detail) { open(IN, "< $file_access"); while () { print OUT $_; } close(IN); } else { print OUT "Access = $tmp_count\n"; } close(OUT); } # # アクセスログを初期化する # open(OUT, "> $file_access"); close(OUT); # # 今日の日付を日付ログファイルに書き出す # open(OUT, "> $file_date"); print(OUT "$date_now"); close(OUT); } # # すでに同アドレスからのアクセスがあればカウントアップしない # $count_up = 1; if ($do_address_check) { open(IN, "$file_access"); while () { if ($_ eq "ADDR = [ $ENV{'REMOTE_ADDR'} ]\n") { $count_up = 0; last; } } close(IN); } # # カウントアップ処理 # if ($count_up == 1) { # # カウンタをひとつインクリメントする # $count++; # # %7E や \~ などを処理する # $referer = $ENV{'HTTP_REFERER'}; $referer =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg; $reffile =~ s/\\//g; # # アクセスログを記録する # open(OUT, ">> $file_access"); print(OUT "COUNT = [ $count ]\n"); print(OUT "TIME = [ $time_now ]\n"); print(OUT "ADDR = [ $ENV{'REMOTE_ADDR'} ]\n"); if ($ENV{'REMOTE_HOST'} ne $ENV{'REMOTE_ADDR'}) { print(OUT "HOST = [ $ENV{'REMOTE_HOST'} ]\n"); } print(OUT "AGENT = [ $ENV{'HTTP_USER_AGENT'} ]\n"); print(OUT "REFER = [ $referer ]\n"); if ($reffile && (!$my_url || ($reffile !~ /$my_url/))) { print(OUT "FROM = [ $reffile ]\n"); } print(OUT "\n"); close(OUT); # # カウンタをカウンタファイルに書き戻す # open(OUT, "> $file_count"); print(OUT "$count"); close(OUT); } # # CGIスクリプトの結果としてカウンターを書き出す # $count += 0; if ($figure != 0) { $cntstr = sprintf(sprintf("%%0%dld", $figure), $count); } else { $cntstr = sprintf("%ld", $count); } if ($mode eq "text") { printf("Content-type: text/html\n"); printf("\n"); printf("$cntstr\n"); } elsif ($mode eq "gif") { printf("Content-type: image/gif\n"); printf("\n"); for ($i = 0; $i < length($cntstr); $i++) { $n = substr($cntstr, $i, 1); push(@files, "$n.gif"); } require "gifcat.pl"; binmode(STDOUT); print &gifcat'gifcat(@files); } elsif ($mode eq "hide") { printf("Content-type: image/gif\n"); printf("\n"); ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($giffile); open(IN, $giffile); binmode(IN); binmode(STDOUT); read(IN, $buf, $size); print $buf; close(IN); } # # ロック権を開放する # if ($do_file_lock) { rmdir($file_lock); }