#!/usr/bin/perl # -------------------------------------- # ログ解析(CGI/SSI) $ver = 'ffLog v.2.10'; # 2002/4/8 # (C)2000 Fortunefield # http://www.gem.hi-ho.ne.jp/fortunefield/ # ====================================== # 定数群 # -------------------------------------- $datafile = "fflog.dat"; # データファイル名 $lockkey = 0; # ロック機能(0=no, 1=flock, 2=rename) $lockfile = "fflog.lock"; # ロックファイル名 $nocountkey = 0; # 重複カウント防止機能(0=no, 1=yes) $maxlog = 1000; # 最大ログ保持件数 $freepass = '0123'; # 管理者用ログ回避パスワード $cookname = 'fflog'; # クッキー名 $ENV{'TZ'} = 'JST-9'; # 時間帯(JST-9=日本時間) # ====================================== # 手続き # -------------------------------------- if ($ENV{'QUERY_STRING'} eq 'check') { ✓ } &freepass; &decode; $lockfile2 = "$lockfile"."2"; $time = time; $date = $time; $in = $time; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); $host = $ENV{'REMOTE_HOST'}; $addr = $ENV{'REMOTE_ADDR'}; if ($host eq '' || $host eq $addr) { $host = gethostbyaddr(pack("C4", split(/\./, $addr)), 2); } if ($host eq '') { $host = $addr; } $agent = $ENV{'HTTP_USER_AGENT'}; if ($ENV{'QUERY_STRING'} eq 'ssi') { $path = $ENV{'DOCUMENT_URI'}; $ref = $ENV{'HTTP_REFERER'}; } else { $path = $in{'path'}; $ref = $ENV{'QUERY_STRING'}; $ref =~ s/(.*)&ref=(.*)&cd=(.*)/$2/; $cd = $in{'cd'}; $sc = $in{'sc'}; $cw = $in{'cw'}; $ch = $in{'ch'}; $fs = $in{'fs'}; } &lock; open(IN, "$datafile") || &error("Open Error: $datafile"); local(@data) = ; close(IN); @mons = split(/,/, shift(@data)); @mdays = split(/,/, shift(@data)); @wdays = split(/,/, shift(@data)); @hours = split(/,/, shift(@data)); foreach (0..11) { $mons[$_] =~ s/\s//g; } foreach (0..30) { $mdays[$_] =~ s/\s//g; } foreach (0..6) { $wdays[$_] =~ s/\s//g; } foreach (0..23) { $hours[$_] =~ s/\s//g; } @new = (); $flag1 = 0; $flag2 = 0; if ($nocountkey > 0) { $f1 = 0; if (@data < 1) { $f1 = 1; } foreach (@data) { @a = split(/,/); if ($a[3] eq $hour && $a[4] eq $addr) { $f2 = 0; @b = split(/;/, $a[5]); foreach $b (@b) { if ($b eq $path) { $f2 = 1; } } if ($f2 == 0) { $a[5] .= ";$path"; $a[6] .= ";$time"; $f1 = 1; } if ($a[14] eq '' && $in{'cd'} ne '') { $a[14] = $in{'cd'}; $a[15] = $in{'sc'}; $a[16] = $in{'cw'}; $a[17] = $in{'ch'}; $a[18] = $in{'fs'}; $f1 = 1; } $a[$#a] =~ s/\s//g; push(@new, join(',', @a),"\n"); $flag1 = 1; } else { push(@new, $_); } } if ($f1) { @data = @new; } else { if ($flag1) { $flag2 = 1; } } } if ($flag1 == 0) { @c = split(/,/, $data[0]); if ($c[0] eq ($mon+1)) { $mons[$mon]++; } else { $mons[$mon] = 1; } if ($c[1] eq $mday) { $mdays[$mday-1]++; } else { $mdays[$mday-1] = 1; } if ($c[2] eq $wday) { $wdays[$wday]++; } else { $wdays[$wday] = 1; } if ($c[3] eq $hour) { $hours[$hour]++; } else { $hours[$hour] = 1; } &get_cookie; if ($cook{'visit'}) { $visit = $cook{'visit'} + 1; } else { $visit = 1; } if ($cook{'last'}) { $last = $cook{'last'}; } else { $last = $time; } if ($cook{'first'}) { $first = $cook{'first'}; } else { $first = $time; } while ($maxlog <= @data) { pop(@data); } $mon++; unshift(@data, "$mon,$mday,$wday,$hour,$addr,$path,$in,$date,$host,$agent,$ref,$visit,$last,$first,$cd,$sc,$cw,$ch,$fs\n"); } if ($flag2 == 0) { unshift(@data, join(',', @hours),"\n"); unshift(@data, join(',', @wdays),"\n"); unshift(@data, join(',', @mdays),"\n"); unshift(@data, join(',', @mons),"\n"); open(OUT, ">$datafile") || &error("Write Error: $datafile"); print OUT @data; close(OUT); } &unlock; if ($flag1 == 0) { &set_cookie("visit:$visit,last:$time,first:$first"); } if ($ENV{'QUERY_STRING'} eq 'ssi') { &header; } else { @img = ('47','49','46','38','39','61','01','00','01','00','80','ff','00','ff','ff','ff', '00','00','00','21','f9','04','01','00','00','00','00','2c','00','00','00','00', '01','00','01','00','00','02','02','44','01','00','3b'); print "Content-type: image/gif\n\n"; foreach (@img) { $data = pack('C*', hex($_)); print $data; } } exit; # ====================================== # 関数群 # -------------------------------------- # デコード sub decode { local($query, @params, $param, $key, $val); $query = $ENV{'QUERY_STRING'}; @params = split(/&/, $query); foreach $param (@params) { ($key, $val) = split(/=/, $param); $val =~ tr/+/ /; $val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $in{$key} = $val; } } # -------------------------------------- # ログ回避 sub freepass { if ($freepass) { local($cookie, @cookies, $key, $val); $cookie = $ENV{'HTTP_COOKIE'}; if ($cookie) { @cookies = split(/; */, $cookie); foreach (@cookies) { ($key, $val) = split(/=/); $val =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C", hex($1))/eg; if ($key eq 'ffant_freepass' && $val eq "$freepass") { exit; } } } } } # -------------------------------------- # HTML形式ヘッダ出力 sub header { print "Content-type: text/html\n\n"; } # -------------------------------------- # クッキーを取得 sub get_cookie { local(@cookies, $key, $val); @cookies = split(/; */, $ENV{'HTTP_COOKIE'}); foreach (@cookies) { ($key, $val) = split(/=/); $val =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C", hex($1))/eg; $cook{$key} = $val; } @cookies = split(/,/, $cook{$cookname}); foreach (@cookies) { ($key, $val) = split(/:/); $cook{$key} = $val; } } # -------------------------------------- # クッキー出力 sub set_cookie { local($val) = @_; $val =~ s/(\W)/sprintf("%%%02X", unpack("C", $1))/eg; print "Set-Cookie: $cookname=$val; expires=Wed, 01 Jan 2020 01:01:01 GMT\n"; # print "\n"; } # -------------------------------------- # ロック sub lock { if ($lockkey == 1) { open(LOCK, "$lockfile"); eval { flock(LOCK, 2); }; } elsif ($lockkey == 2) { if (-e $lockfile2) { if (time - (stat($lockfile2))[9] > 300) { rename($lockfile2, $lockfile); } } local($retry) = 10; while (!rename($lockfile, $lockfile2)) { if (--$retry <= 0) { &error("Lock is busy"); } sleep(1); } } } # -------------------------------------- # ロック解除 sub unlock { if ($lockkey == 1) { close(LOCK); } elsif ($lockkey == 2) { rename($lockfile2, $lockfile); } } # -------------------------------------- # エラー処理 sub error { &header; print "$_[0]\n"; exit; } # -------------------------------------- # チェック sub check { print "Content-type: text/html\n\n"; print "$ver$ver"; exit; }