#!/usr/local/bin/perl # ############################################################# ### ### CGIカウンター SDcount ログ表示 Ver.1.00 ### (SDcountシリーズ対応) ### ### (C) 2001 Sentora Dori ### http://lowpower.iis.u-tokyo.ac.jp/~hat ### ############################################################# # #################### 変数設定 #################### # ログファイルのあるディレクトリのパス $basedir = "."; # 管理用のパスワード(何も書かないとパスワードなしでログを見れる) $validpass = 'wanitanma'; # 棒グラフの最大の幅(値が全体の100%のときの幅) $graphwidth = 500; # 棒グラフの高さ $graphheight = 15; # 1:ホスト別、ドメイン別のログをアクセス回数順に並び替えて表示する 0:並びかえない $usesort = 1; # 1:ホスト別、ドメイン別のログを並びかえるためのボタンを表示する 0:表示しない $showsort = 0; # post: postメソッド get: getメソッド $method = 'post'; # 2: flockを使用する 1: ロックファイルでロックする 0: ロックしない (通常は変更必要なし) $uselock = 2; #################### 変数設定(ここまで) #################### # 各ログデータの区切り記号 (変更必要なし) $delimiter ="---nextlog---\n"; # flockを使用しないロックのときのロックファイル名のベース (変更必要なし) $baselockfile = './SDlock'; # このファイル名 $thisurl = 'SDcountlog.cgi'; # タイトル $title = 'SDcountログ表示'; @logtitle = ("アクセス順ログ", "日にち別ログ", "ホスト別ログ", "ドメイン別ログ"); ### data format ### &init_form(); $countname = $form{'countname'}; $logtype = $form{'logtype'}; $pass = $form{'pass'}; $command = $form{'command'}; $logfile = "$basedir/$countname.log"; if ($logtype eq 'total') { $showlog = 4; $lognumber = 0; } elsif ($logtype eq 'simple') { $showlog = 1; $lognumber = 0; } elsif ($logtype eq 'day') { $showlog = 1; $lognumber = 1; } elsif ($logtype eq 'host') { $showlog = 1; $lognumber = 2; } elsif ($logtype eq 'domain') { $showlog = 1; $lognumber = 3; } else { $showlog = 0; } ##### branch ##### if ($command eq 'sort') { &do_sort; } if ($validpass ne '') { if ($command ne '') { if ($validpass eq $pass) { &show_log; } else { &print_error('[password mismatch]'); } } else { &do_showpass; } } else { &show_log; } exit(0); #----- パスワード入力画面表示 ----- sub do_showpass { print "Content-type: text/plain\n\n"; print <<"END_SHOWPASS"; $title
$title - パスワード入力


パスワード
END_SHOWPASS } #----- ログ表示 ----- sub show_log { local($i, $j); local(@logaddr, @logname, @logtime, @logvalue, @domain); local(@bakip, @bakname, @bakvalue); local(@bak, @line, @cutname); if ($showlog) { if (!open(LOGF, "$logfile")) { &print_error('[log file not found]'); } } @logf = ; $txtlist = join('', @logf); @loglist = split(/$delimiter/, $txtlist); # ヘッダ表示 print "Content-type: text/plain\n\n"; print <<"END_SHOWLOG_1"; $title
$title


カウンタ名
どのログを見ますか?

カウンタ名: $countname

END_SHOWLOG_1 $print_sort = <<"END_SHOWSORT";
END_SHOWSORT # 日にち別ログの総アクセス数取得 $totalvalue1 = 1; @eachlog = split(/\n/, $loglist[1]); for ($i = 0; $i < @eachlog; $i++) { ($logday, $logvalue) = split(/,/, $eachlog[$i]); $totalvalue1 += $logvalue; } # ホスト別ログの総アクセス数取得 $totalvalue2 = 1; @eachlog = split(/\n/, $loglist[2]); for ($i = 0; $i < @eachlog; $i++) { ($logaddr, $logname, $logvalue) = split(/,/, $eachlog[$i]); $totalvalue2 += $logvalue; } # ログ表示ループ for ($i = 0; $i < $showlog; $i++) { if (($logtype eq 'total' && $i == 0) || $logtype eq 'simple') { @eachlog = split(/\n/, $loglist[0]); } elsif (($logtype eq 'total' && $i == 1) || $logtype eq 'day') { @eachlog = split(/\n/, $loglist[1]); } elsif (($logtype eq 'total' && $i == 2) || $logtype eq 'host') { @eachlog = split(/\n/, $loglist[2]); @eachlog = &sort_log(@eachlog) if ($usesort); } elsif (($logtype eq 'total' && $i == 3) || $logtype eq 'domain') { @eachlog = split(/\n/, $loglist[2]); for ($k = 0; $k < @eachlog; $k++) { ($logaddr[$k], $logname[$k], $logvalue[$k]) = split(/,/, $eachlog[$k]); @cutname = split(/\./, $logname[$k]); $bak[2] = pop(@cutname); $bak[1] = pop(@cutname); $bak[0] = pop(@cutname); $logname = join('.', @bak); $findaddr = 0; for ($l = 0; $l < @bakname; $l++) { if ($logname eq $bakname[$l]) { $bakvalue[$l] += $logvalue[$k]; $findaddr = 1; last; } } if (!$findaddr) { push (@bakname, $logname); push (@bakvalue, $logvalue[$k]); } } for ($k = 0; $k < @bakname; $k++) { @line = ($bakaddr[$k], $bakname[$k], $bakvalue[$k]); @domain[$k] = join(',', @line); } @eachlog = @domain; @eachlog = &sort_log(@eachlog) if ($usesort); } # 実際にログ表示 print "$logtitle[$lognumber]
"; if (($logtype eq 'total' && $i == 2) || $logtype eq 'host') { print $print_sort if ($showsort); } print "
"; if (($logtype eq 'total' && $i == 0) || $logtype eq 'simple') { print""; } elsif (($logtype eq 'total' && $i == 1) || $logtype eq 'day') { print""; } elsif (($logtype eq 'total' && $i == 2) || $logtype eq 'host') { print""; } elsif (($logtype eq 'total' && $i == 3) || $logtype eq 'domain') { print""; } for ($j = 0; $j < @eachlog; $j++) { # アクセス順 if (($logtype eq 'total' && $i == 0) || $logtype eq 'simple') { ($logvalue, $timelog, $logaddr, $logname) = split(/,/, $eachlog[$j]); print ""; } # 日にち別 elsif (($logtype eq 'total' && $i == 1) || $logtype eq 'day') { ($logday, $logvalue) = split(/,/, $eachlog[$j]); $width = int(($logvalue/$totalvalue1)*$graphwidth); print ""; print ""; } # ホスト別 elsif (($logtype eq 'total' && $i == 2) || $logtype eq 'host') { ($logaddr, $logname, $logvalue) = split(/,/, $eachlog[$j]); $width = int(($logvalue/$totalvalue2)*$graphwidth); print ""; print ""; } # ドメイン別 elsif (($logtype eq 'total' && $i == 3) || $logtype eq 'domain') { ($logaddr, $logname, $logvalue) = split(/,/, $eachlog[$j]); $width = int(($logvalue/$totalvalue2)*$graphwidth); print ""; print ""; } } print "
カウンタ値アクセス時間IPアドレスドメイン
日付けアクセス回数
IPアドレスドメインアクセス回数
ドメインアクセス回数
$logvalue$timelog$logaddr$logname
$logday$logvalue
$logaddr$logname$logvalue
$logname$logvalue

"; $lognumber++; } print ""; } #----- ログファイル中のホスト別ログのソート ----- sub do_sort { if (!open(LOGF, "+<$logfile")) { &print_error('[log file not found]'); } if (!&lock_file(LOGF)) { &print_error('[log file lock error]'); } @logf = ; $txtlist = join('', @logf); @loglist = split(/$delimiter/, $txtlist); @eachlog = split(/\n/, $loglist[2]); @eachlog = &sort_log(@eachlog); $loglist[2] = join("\n", @eachlog)."\n"; $txtlist = join("$delimiter", @loglist); seek(LOGF, 0, 0); print LOGF $txtlist; &unlock_file(LOGF); close(LOG); } #----- ホスト別、ドメイン別のログのソート ----- sub sort_log { local(@list) = @_; local($k, $l); local(@addr, @name, @value, @line); local($bakip, $bakname, $bakvalue); for ($k = 0; $k < @list; $k++) { ($ip[$k], $name[$k], $value[$k]) = split(/,/, $list[$k]); } for ($k = 0; $k < @list - 1; $k++) { for ($l = $k + 1; $l < @list; $l++) { if ($value[$k] < $value[$l]) { $bakip = $ip[$k]; $bakname = $name[$k]; $bakvalue = $value[$k]; $ip[$k] = $ip[$l]; $name[$k] = $name[$l]; $value[$k] = $value[$l]; $ip[$l] = $bakip; $name[$l] = $bakname; $value[$l] = $bakvalue; } } } for ($k = 0; $k < @list; $k++) { @line = ($ip[$k], $name[$k], $value[$k]); $list[$k] = join(',', @line); } return @list; } #----- ブラウザへの入力データの取得 ----- sub init_form { local($query, @dataarray, $method, $property, $value); $method = $ENV{'REQUEST_METHOD'}; $method =~ tr/A-Z/a-z/; if ($method eq 'post') { read(STDIN, $query, $ENV{'CONTENT_LENGTH'}); } else { $query = $ENV{'QUERY_STRING'}; } @dataarray = split(/&/, $query); foreach $data (@dataarray) { ($property, $value) = split(/=/, $data); $form{$property} = $value; } } #----- ファイルロック ----- sub lock_file { local($FILE) = @_; local($LOCK) = "LOCK$FILE"; local($lockfile) = "$baselockfile$FILE"; local($retry) = 10; if ($uselock == 2) { eval(flock($FILE, 2)); if ($@) { return 0; } else { return 1; } } elsif ($uselock == 1) { while (-f $lockfile) { sleep(0.3); return 0 if (--$retry <= 0); } open($LOCK, ">$lockfile") || return 0; close($LOCK); return 1; } else { return 1; } } #----- ファイルアンロック ----- sub unlock_file { local($FILE) = @_; local($lockfile) = "$baselockfile$FILE"; if ($uselock == 2) { flock($FILE, 8); } elsif ($uselock == 1) { unlink($lockfile); } } ##### エラー処理 ##### #----- エラー文を出力し終了 ----- sub print_error { local($msg) = @_; print "Content-type: text/plain\n\n"; print $msg; exit(0); }