#!/usr/bin/perl
#
# DownCounter+x: CGI Program for counting downloaded times
# file: downcntx.cgi
#
# Copyright (C) 2001 KOMORIYA Takeru
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See http://www.paken.org:8080/aaf/download/GPL for more details.
#
# Contact to author:
# KOMORIYA Takeru, AAF Sendai Lab., Japan
# E-mail: komoriya@paken.org
# URL: http://www.paken.org:8080/
#
#---------------------------------------------------------------------
# Ver 1.0(12/15,2001): Changed file invoking method.
# Ver 0.9(10/13,2001): Bug fixed for multiple domain.
# Ver 0.1(8/21,2001) : First release
#-------------------------------------------------------------------
# Usage
# 1.Save this file as "/cgi-bin/downcntx.cgi".
# 2.Edit this file and give correct path to perl(at first line),
# give $password, $serverurl and $local_ip.
# 3.Change permission of this file "chmod 755 downcntx.cgi"
# 4.Create file "touch downcntx.log" and "chmod 666 downcntx.log"
# 5.Create directory "mkdir downcntx_data" and "chmod 777 downcntx_data"
#
# To invoke DownCounter by link:
#
# ex)
#
# To show result:
# access to "/cgi-bin/downcntx.cgi?mode=view"
#-------------------------------------------------------------------
# Password for administration
$password = 'password';
# Server URL
$serverurl ="http://www.yourserver.com";
# Local IP (do not count if accessed from this address)
$local_ip ="192.168.1.2";
# Test mode
$testmode = 0;
# Log file
$logfile = './downcntx.log';
# Path for data directory
$basedir = './downcntx_data/';
# Lock for inhibit multiple invocation
# 0: Don't lock, 1: Lock(symlink), 2: Lock(mkdir)
$lock_key = 1;
# Lock-file
$lockfile = $basedir . ".lock";
#-------------------------------------------------------------------
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 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
$in{$name} = $value;
}
# Input parameters
$url = $in{'url'};
$nickname = $in{'name'};
# Full-path to log file for given name
$accesslog = $basedir . $nickname;
# View mode
if ($in{'mode'} eq "view"){
&report;
exit;
}
# View access-log mode
if ($in{'mode'} eq "accesslog"){
if ($password eq $in{'passwd'}){
&report_accesslog;
exit;
}
}
# Check wrong file name
if ($nickname =~ /[^\w\.+-]|^$/) { &error('ERROR',"Wrong name: $nickname"); }
# Accessed from Local PC?
if($ENV{'REMOTE_ADDR'} =~ /$local_ip/){
$fromserverurl=0;
}else{
$fromserverurl=1;
}
if (($fromserverurl == 1) || ($testmode == 1)){
# Lock
&lock if ($lockkey);
# Open and read log-file
open(IN,"$logfile") || &error("ERROR","Cannot open logfile.");
@lines = ;
close(IN);
# Increment matched entry
$flag=0;
@new=();
foreach $line (@lines) {
($name,$count) = split(/\t/, $line);
chomp($count);
if ($nickname eq "$name") {
$flag=1;
$count++;
$newcount=$count;
$line = "$name\t$count\n";
}
push(@new,$line);
}
# Update logfile
if ($flag == 1) {
open(OUT,">$logfile") || &error("ERROR","Cannot open logfile.");
print OUT @new;
close(OUT);
}
# Add to logfile
elsif ($flag == 0 && $nickname ne "") {
$newcount=1;
open(OUT,">>$logfile") || &error("ERROR","Cannot open logfile.");
print OUT "$nickname\t$newcount\n";
close(OUT);
}
# Format Date and Time
$ENV{'TZ'} = "JST-9";
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year +=1900;
$new_date = sprintf("%04d/%02d/%02d", $year , $mon + 1, $mday);
$new_hour = sprintf("%02d:%02d", $hour,$min);
# Get remote host
if($ENV{'REMOTE_HOST'} !~/[a-zA-Z]/){
$n_host = $ENV{'REMOTE_ADDR'};
$ENV{'REMOTE_HOST'} = gethostbyaddr(pack('C4',split(/\./,$n_host)),2) || $n_host;
}
# Create access log file for given name
if (!-e $accesslog) {
if (!open(OUT,"> $accesslog")) { &error('ERROR',"Cannot create: $accesslog"); }
$newaccesslog = 1;
}else{
if (!open(OUT,">> $accesslog")) { &error('ERROR',"Cannot create: $accesslog"); }
}
print OUT "$newcount"."\t";
print OUT "$ENV{'REMOTE_HOST'}"."\t";
print OUT "$new_date"."\t";
print OUT "$new_hour"."\n";
close OUT;
# Change file permission
if ($newaccesslog == 1) {
chmod(0666,$accesslog);
}
# unlock
&unlock if ($lockkey);
}
if($fromserverurl == 1){
$url = $serverurl . $url;
}else{
$url = "http://" . $local_ip . $url;
}
# invoke target file
print <<"EOF";
Content-type: text/html
ダウンロード
↓右クリックして保存してください.
$url
EOF
exit;
sub lock {
local($retry)=5;
# delete old lock (older than 3 minutes)
if (-e $lockfile) {
($mtime) = (stat($lockfile))[9];
if ($mtime && $mtime < time - 180) { &unlock; }
}
# symlink lock
if ($lockkey == 1) {
while (!symlink(".", $lockfile)) {
if (--$retry <= 0) { &error('Server Busy',"Please retry later."); }
sleep(1);
}
# mkdir lock
} elsif ($lockkey == 2) {
while (!mkdir($lockfile, 0755)) {
if (--$retry <= 0) { &error('Server Busy',"Please retry later."); }
sleep(1);
}
}
}
sub unlock {
if ($lockkey == 1) { unlink($lockfile); }
elsif ($lockkey == 2) { rmdir($lockfile); }
}
sub error {
if (-e $lockfile) { unlink($lockfile); }
print "Content-type: text/html\n\n";
print "\n";
print "$_[0]
\n";
print "$_[1]
\n";
print "