#!/usr/bin/perl
################################################################################
# 高機能アクセス解析CGI Professional版 (解析結果表示用)
# Ver 4.6
# Copyright(C) futomi 2001 - 2003
# http://www.futomi.com/
###############################################################################
use strict;
my $JFLAG;
BEGIN {
use Time::Local;
use CGI;
eval "use Jcode";
if($@) {
$JFLAG = 0;
} else {
$JFLAG = 1;
}
}
my $q = new CGI;
$| = 1;
require "./jcode.pl";
######################################################################
# グローバル変数の定義
######################################################################
my $FREE_SERVER_NAME = '\.tok2\.com|\.infoseek\.co\.jp|\.xrea\.com';
#設定値を取得
my %CONF = &GetConf('./data/config.cgi');
my %URL2PATH = ();
$URL2PATH{$CONF{'URL2PATH_URL'}} = $CONF{'URL2PATH_PATH'};
my @MY_SITE_URLs = split(/,/, $CONF{'MY_SITE_URLs'});
my @REJECT_HOSTS = split(/,/, $CONF{'REJECT_HOSTS'});
my @DIRECTORYINDEX = split(/,/, $CONF{'DIRECTORYINDEX'});
#ディレクトリの定義
my $TEMPLATEDIR = './template';
my $LOGDIR = './logs';
my $PRE_LOGNAME = 'access_log';
#著作権表示の定義
my $COPYRIGHT = "";
my $COPYRIGHT2 = "";
my $COPYRIGHT3 = "";
my $COPYRIGHT4 = "";
#入力パラメータの取得
my $MODE = $q->param('MODE');
my $ANA_MONTH = $q->param('MONTH');
my $ANA_DAY = $q->param('DAY');
my $TARGET_FRAME = $q->param('FRAME');
my $ITEM = $q->param('ITEM');
my $TARGET_VISITOR = $q->param('VISITOR');
# このCGIのURL
my $CGI_URL = 'acc.cgi';
# 解析対象のログファイル名を特定
my $TARGET_LOGNAME = &SpecifyLogFileName;
######################################################################
# メインルーチン
######################################################################
# パスワード認証
if($CONF{'AUTHFLAG'}) {&Auth;}
# ターゲットフレームの指定がなければ、親フレームを出力する。
if($TARGET_FRAME eq 'menu') {
&PrintMenuFrame;
} elsif($TARGET_FRAME eq 'result') {
&PrintResultFrame;
} else {
&PrintMainFrame;
}
exit;
######################################################################
# サブルーチン
######################################################################
sub PrintMainFrame {
my $menu_url = "$CGI_URL?FRAME=menu";
my $result_url = "$CGI_URL?FRAME=result";
if($TARGET_LOGNAME) {
$menu_url .= "\&LOG=$TARGET_LOGNAME";
$result_url .= "\&LOG=$TARGET_LOGNAME";
}
if($ANA_MONTH) {
$menu_url .= "\&MONTH=$ANA_MONTH";
$result_url .= "\&MONTH=$ANA_MONTH";
if($ANA_DAY) {
$menu_url .= "\&DAY=$ANA_DAY";
$result_url .= "\&DAY=$ANA_DAY";
}
} else {
if($ANA_DAY) {
&ErrorPrint("日を指定する場合には、月を指定して下さい。");
}
}
my $html = &ReadTemplate("$TEMPLATEDIR/mainframe.html");
$html =~ s//$menu_url/;
$html =~ s//$result_url/;
if($ENV{'SERVER_NAME'} =~ /($FREE_SERVER_NAME)/) {
$html =~ s///;
} else {
$html =~ s///;
}
&HtmlHeader;
print "$html\n";
}
sub PrintMenuFrame {
my(@DateList) = &GetLogDateList("$LOGDIR/$TARGET_LOGNAME");
my $Today = &GetToday;
my $MaxDate = pop @DateList;
my $MinDate = $MaxDate;
if(scalar(@DateList) >= 1) {
$MinDate = shift @DateList;
}
my $TargetMonth;
if($ANA_MONTH) {
$TargetMonth = $ANA_MONTH;
} elsif($MaxDate) {
$TargetMonth = substr($MaxDate, 0, 6);
} else {
$TargetMonth = substr($Today, 0, 6);
}
my $DspYear = substr($TargetMonth, 0, 4);
my $DspMonth = substr($TargetMonth, 4, 2);
my $LastMonth = &GetLastMonth($TargetMonth);
my $NextMonth = &GetNextMonth($TargetMonth);
my $ThisMonthTag = "$DspYear年 $DspMonth月";
my $LastMonthTag;
if($LastMonth >= substr($MinDate, 0, 6)) {
$LastMonthTag = "
\n";
} else {
$LastMonthTag = "
\n";
}
my $NextMonthTag;
if($NextMonth <= substr($MaxDate, 0, 6)) {
$NextMonthTag = "
\n";
} else {
$NextMonthTag = "
\n";
}
my $LastDay = &LastDay($DspYear, $DspMonth);
my $StartWeekNo = &Youbi($DspYear, $DspMonth, "01");
my $flag = 1;
my $WeekNo = 0;
my $day = 1;
my ($i, $DateBuff, $DspDay, $CalendarTag);
while($flag) {
$CalendarTag .= "
\n";
for($i=0;$i<7;$i++) {
if($WeekNo < 1 && $i < $StartWeekNo) {
$CalendarTag .= " | | \n";
} elsif($day > $LastDay) {
$CalendarTag .= " | \n";
$day ++;
} else {
$DateBuff = $DspYear . $DspMonth;
if($day < 10) {
$DateBuff .= "0$day";
} else {
$DateBuff .= "$day";
}
if($DateBuff == $Today) {
$DspDay = "$day";
} else {
$DspDay = "$day";
}
if($i == 0) {
$DspDay = "$DspDay";
} elsif($i == 6) {
$DspDay = "$DspDay";
} elsif(&CheckHoliday($DspYear, $DspMonth, $day)) {
$DspDay = "$DspDay";
}
if($DateBuff >= $MinDate && $DateBuff <= $MaxDate) {
$CalendarTag .= " $DspDay | \n";
} else {
$CalendarTag .= " $DspDay | \n";
}
$day ++;
}
}
$CalendarTag .= "
\n";
$WeekNo ++;
if($day > $LastDay) {
$flag = 0;
}
}
my $LogListTag = "\n";
my $AccModeTag;
if($ANA_DAY) {
$AccModeTag = "日指定
".substr($ANA_MONTH, 0, 4)."/".substr($ANA_MONTH, 4, 2)."/$ANA_DAY";
} elsif($ANA_MONTH) {
$AccModeTag = "月指定
".substr($ANA_MONTH, 0, 4)."/".substr($ANA_MONTH, 4, 2);
} else {
$AccModeTag = "全指定";
}
my $CgiUrl = "$CGI_URL\?FRAME=result\&LOG=$TARGET_LOGNAME";
if($ANA_MONTH) {
$CgiUrl .= "&MONTH=$ANA_MONTH";
if($ANA_DAY) {
$CgiUrl .= "&DAY=$ANA_DAY";
}
}
my $AllAccUrl = "$CGI_URL\?LOG=$TARGET_LOGNAME";
my $template;
if($ENV{'HTTP_USER_AGENT'} =~ /Opera/i) {
$template = "$TEMPLATEDIR/menuframe.html";
}elsif($ENV{'HTTP_USER_AGENT'} =~ /MSIE/i) {
$template = "$TEMPLATEDIR/menuframe_ie.html";
} else {
$template = "$TEMPLATEDIR/menuframe.html";
}
my $html = &ReadTemplate($template);
$html =~ s//$LastMonthTag/;
$html =~ s//$ThisMonthTag/;
$html =~ s//$NextMonthTag/;
$html =~ s//$AllAccUrl/;
$html =~ s//$CalendarTag/;
$html =~ s//$LogListTag/;
$html =~ s//$AccModeTag/;
$html =~ s//$CGI_URL/;
$html =~ s//$CgiUrl/g;
$html =~ s//$CONF{'IMAGE_URL'}/g;
print $q->header(-type=>'text/html; charset=Shift_JIS');
print "$html\n";
}
sub IsInDate {
my($date_check) = @_;
my($date_check_mon, $date_check_day) = $date_check =~ /^(\d{6})(\d{2})/;
$date_check_day =~ s/^0//;
if($ANA_MONTH) {
unless($date_check_mon eq $ANA_MONTH) {
return 0;
}
if($ANA_DAY) {
unless($date_check_day eq $ANA_DAY) {
return 0;
}
}
}
return 1;
}
sub PrintResultFrame {
if($ITEM eq '') {
&GeneralStatistics;
} elsif($ITEM eq 'AccessLogInformation') {
&AccessLogInformation;
} elsif($ITEM eq 'LogSearch') {
&LogSearchForm;
} elsif($ITEM eq 'LogSearchGo') {
&LogSearchGo;
} elsif($ITEM eq 'TopVisitors') {
&TopVisitors;
} elsif($ITEM eq 'MostActiveCountries') {
&MostActiveCountries;
} elsif($ITEM eq 'MostActivePrefecture') {
&MostActivePrefecture;
} elsif($ITEM eq 'MostActiveOrganization') {
&MostActiveOrganization;
} elsif($ITEM eq 'NewVsReturningVisitors') {
&NewVsReturningVisitors;
} elsif($ITEM eq 'TopPagesByViews') {
&TopPagesByViews;
} elsif($ITEM eq 'TopPagesByVisits') {
&TopPagesByVisits;
} elsif($ITEM eq 'TopPagesByVisitors') {
&TopPagesByVisitors;
} elsif($ITEM eq 'VisitorTrace') {
&VisitorTrace;
} elsif($ITEM eq 'ActivityByDayOfTheMonth') {
&ActivityByDayOfTheMonth;
} elsif($ITEM eq 'ActivityByDayOfTheWeek') {
&ActivityByDayOfTheWeek;
} elsif($ITEM eq 'ActivityByHourOfTheDay') {
&ActivityByHourOfTheDay;
} elsif($ITEM eq 'TopReferringSites') {
&TopReferringSites;
} elsif($ITEM eq 'TopReferringURLs') {
&TopReferringURLs;
} elsif($ITEM eq 'TopSearchKeywords') {
&TopSearchKeywords;
} elsif($ITEM eq 'TopSearchEngines') {
&TopSearchEngines;
} elsif($ITEM eq 'TopBrowsers') {
&TopBrowsers;
} elsif($ITEM eq 'TopPlatforms') {
&TopPlatforms;
} elsif($ITEM eq 'TopAcceptLanguage') {
&TopAcceptLanguage;
} elsif($ITEM eq 'TopResolution') {
&TopResolution;
} elsif($ITEM eq 'TopColorDepth') {
&TopColorDepth;
} elsif($ITEM eq 'TopVideoMemorySize') {
&TopVideoMemorySize;
} else {
&ErrorPrint("不正なリクエストです。");
}
}
sub GeneralStatistics {
if(-e "$LOGDIR/$TARGET_LOGNAME") {
open(LOGFILE, "$LOGDIR/$TARGET_LOGNAME") || &ErrorPrint("アクセスログ「$LOGDIR/$TARGET_LOGNAME」をオープンできませんでした");
} else {
&ErrorPrint("アクセスログ($LOGDIR/$TARGET_LOGNAME)がありません。");
}
my $i = 0;
my $min_date = 99999999999999;
my $max_date = 0;
my(%all_date, %date, %remote_host, %cookies, @LogNoList);
while() {
chop;
my($date_part, $host_part, $cookie_part);
if(/^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+\"([^\"]+)\"\s+\"([^\"]+)\"\s+\"([^\"]+)\"/) {
$date_part = $1;
$host_part = $2;
$cookie_part = $3;
} else {
next;
}
next if($date_part eq '');
$all_date{$i} = $date_part;
next unless(&IsInDate($date_part));
$date{$i} = $date_part;
$remote_host{$i} = $host_part;
$cookies{$i} = $cookie_part;
$max_date = $date_part;
if($i == 0) {$min_date = $date_part;}
push(@LogNoList, $i);
$i ++;
}
close(LOGFILE);
my $PageViewNum = $i;
# 総セッション数を調べる
my $AllSessionNum = &GetSessionNum(\@LogNoList, \%date, \%remote_host, \%cookies);
# 総ユニークユーザー数を調べる。
my $AllUniqueUserNum = &GetUniqueUserNum(\@LogNoList, \%remote_host, \%cookies);
my $PVperUser = sprintf("%.2f", $PageViewNum / $AllUniqueUserNum);
# 今日のログ番号を取得する
my $Today = &GetToday;
my @TodayLogNoList = ();
for my $i (keys %date) {
if($date{$i} =~ /^$Today/) {
push(@TodayLogNoList, $i);
}
}
my $TodayPV = @TodayLogNoList;
my $TodaySessionNum = &GetSessionNum(\@TodayLogNoList, \%date, \%remote_host, \%cookies);
my $TodayUniqueUserNum = &GetUniqueUserNum(\@TodayLogNoList, \%remote_host, \%cookies);
my $TodayPVperUser;
if($TodayUniqueUserNum > 0) {
$TodayPVperUser = sprintf("%.2f", $TodayPV / $TodayUniqueUserNum);
} else {
$TodayPVperUser = 0;
}
my($min_year, $min_mon, $min_mday, $min_hour, $min_min, $min_sec) = $min_date =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
my($max_year, $max_mon, $max_mday, $max_hour, $max_min, $max_sec) = $max_date =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
my @Keys = (
'解析対象期間',
'ページビュー',
'セッション数',
'ユニークユーザー数',
'一人あたりのページビュー'
);
my %Data = (
'解析対象期間' => "$min_year/$min_mon/$min_mday $min_hour:$min_min:$min_sec 〜 $max_year/$max_mon/$max_mday $max_hour:$max_min:$max_sec",
'ページビュー' => $PageViewNum,
'セッション数' => $AllSessionNum,
'ユニークユーザー数' => $AllUniqueUserNum,
'一人あたりのページビュー' => $PVperUser
);
my $Str;
$Str .= &MakeTable(\@Keys, \%Data);
$Str .= "
\n";
$Str .= "本日のアクセス状況
\n";
@Keys = (
'ページビュー',
'セッション数',
'ユニークユーザー数',
'一人あたりのページビュー'
);
%Data = (
'ページビュー' => $TodayPV,
'セッション数' => $TodaySessionNum,
'ユニークユーザー数' => $TodayUniqueUserNum,
'一人あたりのページビュー' => $TodayPVperUser
);
$Str .= &MakeTable(\@Keys, \%Data);
my $Title = '統計概要';
&PrintResult($Title, $Str);
}
sub AccessLogInformation {
# 過去ログリストを取得する
my %LogList = ();
unless($LOGDIR) {$LOGDIR = '.';}
opendir(LOGDIR, "$LOGDIR") || &ErrorPrint("ログ格納ディレクトリ「$LOGDIR」をオープンできませんでした。");
my @log_namaes = readdir(LOGDIR);
closedir(LOGDIR);
my($key);
for $key (@log_namaes) {
if($key =~ /^$PRE_LOGNAME/) {
$LogList{$key} = "$LOGDIR\/$key";
}
}
my($Str);
$Str .= "