#!/usr/local/bin/perl # # Website Access Analyzer - Webアクセス統計解析プログラム # # Creadted 1997-06-30 T.Hashimoto Ver 1.00 初版作成 # Revised 1998-02-15 T.Hashimoto Ver 1.01 ちまちまと改造 # Revised 1998-03-06 T.Hashimoto Ver 1.02 リモートホスト保存方法変更 # Revised 1998-03-29 T.Hashimoto Ver 1.10 二重起動対策&説明文等追加 # Revised 1998-04-04 T.Hashimoto Ver 1.11 DynamicHTML対応(個人的趣味) # Revised 1998-08-27 T.Hashimoto Ver 1.20 解析結果にHTTP_REFERRER(リンク元)を追加 # HTMLレイアウト、ログ保存行数等をiniファイル化 # Revised 1998-10-20 T.Hashimoto Ver 1.23 ホスト名が表示されないバグの改修 # Timezoneの考慮 # Revised 1998-11-10 T.Hashimoto Ver 1.24 HP管理者をログ保存しないオプション追加 # Revised 1998-11-25 T.Hashimoto Ver 1.25 とりあえずIE5対応 # Revised 1998-12-08 T.Hashimoto Ver 1.26 ログファイル保存を日毎に変更 # Revised 1999-04-20 T.Hashimoto Ver 2.00 ログファイル形式を変えたので、Versionを2.xに変更 # Revised 1999-09-17 T.Hashimoto Ver 2.01 Y2K対応 # 排他待ちタイムアウト処理方法変更 # Windows2000対応 # Revised 2000-01-10 T.Hashimoto Ver 2.01 Y2K対応(今度こそ) # Revised 2000-09-01 T.Hashimoto Ver 2.02 iモード対応 # UserAgentとOSの設定ファイル化 # Revised 2000-12-01 T.Hashimoto Ver 2.03 LogのUserAgentをチップヘルプで出力 # VIDEO環境保存対応 # Revised 2001-02-10 T.Hashimoto Ver 2.031 自己アクセスログ保存処理のバグ修正 # Revised 2001-03-20 T.Hashimoto Ver 2.04 IE6対応 # 転送アドレス対策 # OS定義ファイルとブラウザ定義ファイルのフォルダ指定が抜けていた。 # ロックファイル削除漏れ対策 # { #パスワードファイル名 # WAAの設定を変更するページで使用されるパスワードを保存するファイル名を指定します。 # パスワードファイル名をURLに直接入力すると見られてしまうプロバイダもありますので、 # 必ず変更するようにして下さい。 $waaPasswdFile = "./unyounya.ini" ; #データファイルディレクトリ指定 # プロバイダによっては、CGIスクリプトファイルとデータファイルを別ディレクトリに # 保存しないといけないようになっているところがあります。 # そういう場合には、下記変数を変更して下さい。 $waaDataFolder = "./statistics" ; # ログ・個別設定ファイルの保存ディレクトリ名 $waaFolder = "." ; # 共通設定ファイルの保存ディレクトリ名 #CGIスクリプト名 # プロバイダによっては、CGIスクリプトファイル名の拡張子を指定されている場合があります。 # その場合は、以下の変数にCGIスクリプトファイル名を変更して下さい。 $waaSFLoging = "loging.cgi" ; # ログ保存CGIスクリプトファイル名 $waaSFSS = "showstatistics.cgi" ; # 解析結果表示CGIスクリプトファイル名 $waaSFMisc = "waamisc.cgi" ; # 環境設定CGIスクリプトファイル名 #HTTP_X_FORWARDED_FOR対策(Rev 2.04) # プロバイダによっては、リモートホストが転送されている場合があります。 # (現象としては、アクセス元のドメイン名が全て同一になってしまいます) # その場合は、以下に転送元の変数(殆どがHTTP_X_FORWARDED_FORです)をセットして下さい。 # 通常は変更不要です。 $waaForwardedFor = "" ; #General Version $WAAVer = "2.04" ; # Rev 2.04 #パラメータ取出し #( $Key_LogName , $Key_Contents , $Key_URL ,$GIF ) = @ARGV ; %form=&form ; $Key_LogName = $form{"Site"} ; $Key_Contents = $form{"Contents"} ; $GIF = $form{"Image"} ; $Key_Video = $form{"Video"} ; #Rev 2.03 if ($Key_Video ne '') { $Key_Video = ' ; Video=' . $Key_Video ; } #$Key_URL = $form{"Option"} ; if ( $ENV{'QUERY_STRING'} =~ /.*Option=/ ) { $Key_URL = $ENV{'QUERY_STRING'}; $Key_URL =~ s/.*Option=// ; } else { $Key_URL = "" ; } #デバッグ用 #$Key_LogName = "waaBeta" ; #$Key_Contents = "test" ; #$GIF = "SSI" ; #初期値設定ファイル読込み &read_inifile() ; &read_Security($Key_LogName) ; &read_cookies() ; #URLに画像ファイルが指定されてないなら、デフォルトの画像を使用 if ( $GIF eq '' ) { $GIF = $DefImage ; } #リンク元URLがリンク元対象外なら保存しない @NotReferences = split (/,/,$NotReferences) ; foreach $NotReference ( @NotReferences ) { if ( $Key_URL =~ /$NotReference/ ) { $Key_URL = '' ; last ; } } # ログファイル名作成 local($BaseDate) = time + $WTimeZone ; @dat = localtime($BaseDate) ; @dat[5] = (100 <= @dat[5]) ? (@dat[5] - 100) : @dat[5] ; # Rev 2.01 local($Year) = ((@dat[5] < 70 ) ? 2000 : 1900) + @dat[5] ; $fname = sprintf("%s/%s_%02d%02d%02d.log",$waaDataFolder,$Key_LogName,$Year,@dat[4] + 1,@dat[3]) ; $flock = $waaDataFolder . "/" . $Key_LogName . ".lock" ; $fininame = $waaDataFolder . "/" . $Key_LogName . ".ini" ; #ログ自動作成有り or ログファイル有り if ( ( $AutoCreate eq 'true' ) || ( -e $fininame ) ) { # ログ用ディレクトリが無い場合は作成 if(!(-d $waaDataFolder)) { mkdir($waaDataFolder,0777) ; chmod (0777,$waaDataFolder) ; } #ログ保存対象外ユーザならログ保存 if ( $cookie{$OwnerAccessKey} ne $OwnerAccess ) { #連続アクセスチェック if ( &RepeatCheck eq 'true') { #排他待ち時間算出 # Rev 2.01 local($TimeOut) = time + ($TimeOutCount - 1) * $TimeOutWait ; # Rev 2.01 #ロックファイル削除漏れチェック用 # Rev 2.04 @flockstat = stat $flock ; # Rev 2.04 local($TimeOut2) = $flockstat[9] + ($TimeOutCount - 1) * $TimeOutWait ; # Rev 2.04 #二重起動チェック $Count = 0 ; while ( -f $flock ) { if ( ( $TimeOutCount < $Count ) || ( $TimeOut < time ) || ( $TimeOut2 < time ) ) { # Rev 2.04 unlink($flock) ; break ; } sleep($TimeOutWait) ; # Rev 2.01 $Count++ ; } #ロックファイル作成 open(LOCK,">$flock") ; printf LOCK "%02d/%02d/%02d %02d:%02d:%02d\n",@dat[5],@dat[4] + 1,@dat[3],@dat[2],@dat[1],@dat[0] ; close(LOCK) ; # ログを保存 $rh = $ENV{'REMOTE_HOST'}; $addr = $ENV{'REMOTE_ADDR'}; if ( $waaForwardedFor ne '' ) { $addr = $ENV{$waaForwardedFor}; } #Rev 2.04 if ($rh eq $addr) { $rh = gethostbyaddr(pack('C4',split(/\./,$rh)),2) || $addr ; } elsif ($rh eq '') { $rh = gethostbyaddr(pack('C4',split(/\./,$addr)),2) || $addr ; } open(WTXT,">>$fname") ; #printf WTXT "%02d/%02d %02d:%02d:%02d %-16s %-24s %-s\n",@dat[4] + 1,@dat[3],@dat[2],@dat[1],@dat[0],$Key_Contents,$ENV{'REMOTE_HOST'},$Key_URL ; #printf WTXT "%02d/%02d/%02d %02d:%02d:%02d,%s,%s,%s,%s\n",@dat[5],@dat[4] + 1,@dat[3],@dat[2],@dat[1],@dat[0],$Key_Contents,$rh,$ENV{'HTTP_USER_AGENT'},$Key_URL ; #Rev 2.03 printf WTXT "%02d/%02d/%02d %02d:%02d:%02d,%s,%s,%s%s,%s\n",@dat[5],@dat[4] + 1,@dat[3],@dat[2],@dat[1],@dat[0],$Key_Contents,$rh,$ENV{'HTTP_USER_AGENT'},$Key_Video,$Key_URL ; #Rev 2.03 #printf WTXT "%02d/%02d/%02d %02d:%02d:%02d,%s,%s,%s,%s / %s\n",@dat[5],@dat[4] + 1,@dat[3],@dat[2],@dat[1],@dat[0],$Key_Contents,$rh,$ENV{'HTTP_USER_AGENT'},$Key_URL,$NotReference ; close(WTXT) ; chmod (0777,$fname) ; #ログ保存期間を指定されていたなら、保存期間を過ぎたログを削除 if ( 0 < $LogDays ) { &UnlinkLogFiles($BaseDate,$LogDays) ; } #ロックファイル削除 unlink($flock) ; } } } # めくらイメージ送出 if ( $GIF ne '' && $GIF ne 'SSI' ) { ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat $GIF ; $ImageSize = $size ; print "Content-type: image/gif\n" ; printf "\n" ; open (Image,$GIF) ; binmode(Image) ; binmode(STDOUT) ; read(Image,$buff,$ImageSize) ; print $buff ; close (Image) ; } } # # iniファイル読込み # sub read_inifile { local(@Lines) ; #Default HTML Layout $bgcolor = "#000000" ; #Background Color $text = "#9999ff" ; #Text Color $link = "#33ccff" ; #Link Color $vlink = "#99ccff" ; #Visited Link Color $alink = "#cc9900" ; #Active Link Color $background = "" ; #Background Image File $TailOutDef = 20 ; #Log Line Count $DefImage = "waa_banner.gif" ; #Image File $DefFormats = "Contents,Domain,Browser,OS,Ref,Time,Log" ; # $DynaFormats = "Contents,Domain,Browser,OS,Ref,Time,Day,Month,Log" ; $DynaFormats = "Contents,Domain,Browser,OS,Ref,Time,Log" ; $LogLineMax = 3000 ; #LogFileMax(大きすぎると解析に時間が掛かります) $LogDays = 28 ; #Log保存期間(大きすぎると解析に時間が掛かります) $NotReferences = "" ; $WTimeZone = 0 ; #WebサーバとCGIサーバの時刻差(分単位) $OwnerAccess = "None" ; #所有者アクセスのログ保存可否(保存) #falseにしてないのはcookieと同値だからだよん) $RepeatAccess = "true" ; $TimeOutCount = "36" ; #排他待ちタイムアウトカウント回数 # Rev 2.01 $TimeOutWait = "5" ; #排他待ちタイムアウト秒数 # Rev 2.01 # iniファイル名作成 $fininame = $waaDataFolder . "/" . $Key_LogName . ".ini" ; $fdefininame = $waaFolder . "/waa.ini" ; if ( -e $fininame ) { # ユーザ設定iniファイル読込み open(INI,"$fininame") ; @Lines = ; close(INI) ; } elsif ( -e $fdefininame ) { # デフォルト設定iniファイル読込み open(INI,"$fdefininame") ; @Lines = ; close(INI) ; } if ( @Lines ) { foreach $Line ( @Lines ) { if ( $Line !=~ /~#/ ) { ( $name , $value ) = split ( /=/ , $Line ) ; $value =~ s/\r\n// ; $value =~ s/\n// ; $value =~ s/\r// ; $INI{$name} = $value ; } } $OwnerAccessKey = "WaaOwnerAccess_" . $Key_LogName ; $RepeatAccessKey = "WaaRepeatAccess_" . $Key_LogName ; if ( $INI{"bgcolor"} ne '' ) { $bgcolor = $INI{"bgcolor"} ; } if ( $INI{"text"} ne '' ) { $text = $INI{"text"} ; } if ( $INI{"link"} ne '' ) { $link = $INI{"link"} ; } if ( $INI{"vlink"} ne '' ) { $vlink = $INI{"vlink"} ; } if ( $INI{"alink"} ne '' ) { $alink = $INI{"alink"} ; } if ( $INI{"background"} ne '' ) { $background = $INI{"background"} ; } if ( $INI{"DefTailOut"} ne '' ) { $DefTailOut = $INI{"DefTailOut"} ; } if ( $INI{"DefFormats"} ne '' ) { $DefFormats = $INI{"DefFormats"} ; } if ( $INI{"LogLineMax"} ne '' ) { $LogLineMax = $INI{"LogLineMax"} ; } if ( $INI{"LogDays"} ne '' ) { $LogDays = $INI{"LogDays"} ; } if ( $INI{"NotReferences"} ne '' ) { $NotReferences = $INI{"NotReferences"} ; } if ( $INI{"DefImage"} ne '' ) { $DefImage = $INI{"DefImage"} ; } if ( $INI{"DefTime"} ne '' ) { $DefImage = $INI{"DefImage"} ; } if ( $INI{"TimeZone"} ne '' ) { $WTimeZone = $INI{"TimeZone"} * 60 ; } if ( $INI{$OwnerAccessKey} ne '' ) { $OwnerAccess = $INI{$OwnerAccessKey} ; } if ( $INI{$RepeatAccessKey} ne '' ) { $RepeatAccess = $INI{"$RepeatAccessKey"} ; } if ( $INI{TimeOutCount} ne '' ) { $TimeOutCount = $INI{"TimeOutCount"} ; } # Rev 2.01 if ( $INI{TimeOutWait} ne '' ) { $TimeOutWait = $INI{"TimeOutWait"} ; } # Rev 2.01 } } sub form { local ($buffer, @pairs, $pair, $name, $value, %FORM); # Read in text $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $FORM{$name} = $value; } %FORM; } sub read_cookies { foreach $pair ( split(/;/,$ENV{'HTTP_COOKIE'}) ) { ($name, $value) = split(/=/, $pair); $name =~ s/ //g; $cookie{$name} = $value; } } # # セキュリティ設定読込み # sub read_Security { #パラメータ取得 local($targetName) = ($_[0]) ; local(@Lines) ; $fininame = $waaPasswdFile ; $AutoCreate = "true" ; #ログファイル自動作成可否(自動作成可) if ( -e $fininame ) { open(INI,"$fininame") ; @Lines = ; close(INI) ; } if ( @Lines ) { foreach $Line ( @Lines ) { if ( $Line !=~ /~#/ ) { ( $name , $value ) = split ( /=/ , $Line ) ; $value =~ s/\r\n// ; $value =~ s/\n// ; $value =~ s/\r// ; $INI{$name} = $value ; } } # 初期設定ファイルに指定があれば、パラメータを変更 if ( $INI{"AutoCreate"} ne '' ) { $AutoCreate = $INI{"AutoCreate"} ; } } # if ( $OwnerAccess eq 'true' ) { $OwnerAccess = "true_" . $INI{"password_" . $targetName} ; # } } # # ログ削除 # sub UnlinkLogFiles { #パラメータ取得 local($BaseDate,$Days) = ($_[0],$_[1]) ; #ローカル変数定義 local($dir) = $waaDataFolder ; local($links,$dev,$ino,$mode,$ubcount) ; local($LimitDateVal,$LimitDate,@LimitDate,$Year,$FileDate) ; #保存期限算出 $LimitDateVal = $BaseDate - (60 * 60 * 24 * $Days) ; @LimitDate = localtime($LimitDateVal) ; local($Year) = ((@LimitDate[5] < 70 ) ? 2000 : 1900) + @LimitDate[5] ; $LimitDate = sprintf ("%4d%02d%02d",$Year,@LimitDate[4] + 1,@LimitDate[3]) ; #ファイル情報取出し ($dev,$ino,$mode,$links) = stat($dir) unless $links ; #ディレクトリオープン opendir(DIREC,"$dir") || die "Can't open $dir." ; local(@logfiles) = readdir(DIREC) ; closedir(DIREC) ; #対象ログファイルを日にち順にチェック local($TotalCount) = 0 ; foreach (sort @logfiles) { next if ( $_ eq '.' || $_ eq '.' || !( $_ =~ /^$Key_LogName/i && $_ =~ /_[0-9]+\.log$/i ) ) ; #日付取出し $FileDate = $_ ; $FileDate =~ s/^.*_// ; $FileDate =~ s/\.log//i ; #保存期限日以内のログファイルなら削除終了 if ( $LimitDate < $FileDate ) { last ; } # ログファイル削除 $UnlinkFile = $dir . "/" . $_ ; unlink $UnlinkFile ; } } # #連続アクセスチェック # sub RepeatCheck { #連続アクセス設定は? if ( $RepeatAccess eq 'false' ) { #参照済? if ( $cookie{$RepeatAccessKey} =~ /$Key_Contents/ ) { #ログ非保存 $RepeatCheck = 'false' ; } else { #ログ保存 & クッキー保存(期限:セッション終了) $RepeatCheck = 'true' ; print "Set-Cookie: $RepeatAccessKey=$Key_Contents:$cookie{$RepeatAccessKey}; \n"; } } else { #ログ保存 $RepeatCheck = 'true' ; } $RepeatCheck ; }