アクセス記録収集ソフト 技術的解説


    アクセス記録のためのCGI起動、情報取得、ファイルへの書き込みは以下の手順で行います。

  1. リンク元情報をJavaScriptのdocument.referrerで取得
  2. ページを見た時すぐにCGIが起動されるように、<img>タグを使用
    さらに、JavaScriptはファイルの書き込みができないので、 上記リンク元情報をCGIに渡す。
  3. <img>タグで呼ばれたCGIの責任として、何かの画像データを出力
    例えばCGIは目立たない方が良いなら、縦横各1ピクセルで透明の画像を出力する。
  4. CGIは引数で渡されたリンク元を時刻やクライアントの情報と一緒にファイルに保存

  1. リンク元情報をJavaScriptのdocument.referrerで取得
    調査対象となるページに次のようなJavaScriptのスクリプトを書けば、 リンク元が取得できます。
    <script language="JavaScript">
    <!--
    document.write(document.referrer);
    //-->
    </script>
    
    この例はリンク元をページの中に表示するだけです。

  2. ページを見た時すぐにCGIが起動されるように、<img>タグを使用
    前述のdocument.write()は以下のように変更します。
    <script language="JavaScript">
    <!--
    document.write("<img src=\"tflog.cgi?情報保存ファイル名+",document.referrer , "\">");
    //-->
    </script>
    
    拡張子はここではcgiにしていますが、サーバによってはplにすべき場合もあります。

  3. <img>タグで呼ばれたCGIの責任として、何かの画像データを出力
    CGIをperlで書く場合は以下のようにします。
    print("Content-type: image/gif\n\n");
    $img = pack("c43",
    	0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00,
    	0x01, 0x00, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff,
    	0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x00,
    	0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00,
    	0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44,
    	0x01, 0x00, 0x3b);
    print($img);
    
    上記は1×1ピクセルの透明なGIF画像です。 適当なお絵描きソフトで画像を作ってデータをダンプしてみれば良いでしょう。

  4. CGIは引数で渡されたリンク元を時刻やクライアントの情報と一緒にファイルに保存
    CGIの実行環境において、環境変数にクライアントの情報等が設定されています。 CGIは適当な環境変数の内容をファイルに保存すれば良いのです。
    if ( open(FILE, ">>$logFile") ){
    	($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
    		= localtime(time);
    	$date = sprintf("%d/%02d/%02d %02d:%02d:%02d\t",
    		$year, $mon + 1, $mday, $hour, $min, $sec);
    	if ( length($referrer) == 0 ){ $referrer = "Unknown_Referrer"; }
    	print FILE $date, $referrer, "\t",
    		$ENV{"REMOTE_HOST"}, "(", $ENV{"REMOTE_ADDR"}, ")\t",
    		$ENV{"HTTP_USER_AGENT"}, "\n";
    	close(FILE);
    }
    
    $logFileは情報保存用のファイル名、 $referrerはJavaScriptからの呼び出し時に渡されたリンク元です。
    なお、ファイル保存を行うので多重アクセス対策として、 前後にファイルのロック・アンロック処理が必要です。
    また、ファイルの追加書き込みをしているので、このままではファイルは無限に大きくなります。 適当な大きさになった時に内容を削除する必要があります。

    私の場合は、削除前に内容を自分宛にメールで送信しています。
    以下の例の$sendmailにはUNIXのsendmailを絶対パスで設定してください。
    たいていの場合は $sendmail = "/usr/lib/sendmail"; ですが、 $sendmail = "/usr/sbin/sendmail"; とすべきサーバーもありますので、 インストールするマシンについて調査してから設定してください。
    この設定を間違えると、ファイルのロックを解除しないデッドロックになってしまいます。

    if ( -s $logFile > 10240 ){
    	open(LOG, $logFile);
    	open(MAIL, "|$sendmail -t");
    	print MAIL "Reply-to: $mailFrom\n";
    	print MAIL "From: $mailFrom\n";
    	print MAIL "To: $mailTo\n";
    	print MAIL "Subject: $mailSubject\n";
    	while(<LOG>){
    		print MAIL $_;
    	}
    	close(MAIL);
    	close(LOG);
    	# clear log file
    	if ( open( FILE, ">$logFile") ){ close(FILE); }
    }

リンク元の情報はCGIの環境変数HTTP_REFERERで取得する方法もあります。
(JavaScriptのreferrerとは微妙にスペルが異なります。 英単語としてはrを2つ重ねる方が正しいと思いますが)

長所は、JavaScriptを使わずCGIだけでスッキリと作れる、 MSIE3.0xでもリンク元情報を取得できる、などです。
短所は、SSIにしないと正しいリンク元情報が得られないことです。 つまり、ドキュメントをshtmlにする必要があります。 htmlで使うと現在表示中のページのURLしか取れなくてハマります。

この方法で、CGIのみで作るのも一興かと思います。