#!/usr/bin/perl
#------------------------------------------------------------------------------
# $Id$
#------------------------------------------------------------------------------
# Download apache log files CGI
#
# Copyright (c) BAYBITS LLC. All rights reserved.
#------------------------------------------------------------------------------

use strict;
use utf8;
use CGI;
use TF::CommonUtils;
use Encode;

binmode(STDOUT, ":utf8");

# global
my $LOCATION     = $ENV{'TF_LOCATION'} || '';
my $USERTYPE     = $ENV{'TF_USERTYPE'} || 'normal';
my $LANGPARAM    = TF::CommonUtils::getLangPriority();
my $TF_LOGACCESS = $ENV{'TF_LOGACCESS'} || 'off';
my $dir_pass     = $ENV{'TF_LOGFILE_ROOT'} || '/var/log/teamfile';
my $MSGTABLE_ja  = {
					mErrNoLogEntryT => 'インフォメーション',
					mErrNoLogEntry  => '対象ロケーションのログデータは存在しませんでした。',
					mErrRangeParam  => '「範囲」が正しく指定されておりません。',
					mErrTypeParam   => '「種類」が正しく指定されておりません。',
					mErrCGI         => 'CGIモジュールの生成に失敗しました。',
				};
my $MSGTABLE_en  = {
					mErrNoLogEntryT => 'Information',
					mErrNoLogEntry  => 'The log entry for this location was not found.',
					mErrRangeParam  => 'Invalid "Range" parameter.',
					mErrTypeParam   => 'Invalid "Type" parameter.',
					mErrCGI         => 'Failed to create cgi module.',
				};
my $MSGTABLE     = ($LANGPARAM eq 'ja') ? $MSGTABLE_ja : $MSGTABLE_en;


if (!$LOCATION || !$USERTYPE || $USERTYPE ne 'admin' || !$TF_LOGACCESS || $TF_LOGACCESS eq 'off') {
	TF::CommonUtils::showAccessDeny();
	die '';
}
my $IS_LC_FILTER = ($TF_LOGACCESS eq "on-all") ? 0 : 1;

main();


#
# main 
#
sub main {

	my $query = new CGI;
	if (!$query) {
		TF::CommonUtils::showErrorPage(	$MSGTABLE->{mErrCGI}, $LANGPARAM);
		die "CGI Object error";
	}

	if ($query->cgi_error) {
		TF::CommonUtils::showErrorPage(	$MSGTABLE->{mErrCGI}, $LANGPARAM);
		die "CGI Error (" . $query->cgi_error . ")";
	}

	my $logtype  = $query->param('selLogType');
	my $logdays  = $query->param('selLogRange');
	my $downflag = $query->param('hidCmd');
    my $filename = $query->param('hidLogFileName');
	my $virname  = $query->param('hidVirtualFileName');
	# (note) for CRLF injection problem
	$virname =~ s/\r//g;
	$virname =~ s/\n//g;

	# (note) for OS command injection problem
	if ($filename =~ /[^0-9a-zA-Z\._]/) {
		TF::CommonUtils::showMessagePage(   $MSGTABLE->{mErrNoLogEntry},
											$LANGPARAM,
											$MSGTABLE->{mErrNoLogEntryT});
		return;
	}
	
	my $found    = undef;
	my $REG_LOCATION = TF::CommonUtils::escapeRegularExpression($LOCATION);

# 各ログのダウンロード
	if($downflag eq "down") {
		
		open (FH, "$dir_pass/$filename") || die "$!";
		if($filename =~/access_log.\d\d\d\d\d\d\d\d$/){
			while(<FH>)
			{
				if(!$IS_LC_FILTER || $_=~ /\"[A-Z][A-Z]*[ ][ ]*$REG_LOCATION[\/| ]/){
					if (!$found) {
						print "Content-type:application/octet-stream\r\n";
						print "Content-Disposition:attachment; filename=$virname\n\n";
						$found = 1;
					}
					print ($_);
				}
			}
		}
		elsif($filename =~/error_log\.\d\d\d\d\d\d\d\d$/){
			while(<FH>){
				if(!$IS_LC_FILTER || $_=~ /]\ \[[a-z:_]*\]\ \[pid\ [0-9]*\]\ $REG_LOCATION\ .*/){
					if (!$found) {
						print "Content-type:application/octet-stream\r\n";
						print "Content-Disposition:attachment; filename=$virname\n\n";
						$found = 1;
					}
					print ($_);
				}
			}
		}
		close(FH);

		if (!$found) {
			TF::CommonUtils::showMessagePage(	$MSGTABLE->{mErrNoLogEntry},
												$LANGPARAM,
												$MSGTABLE->{mErrNoLogEntryT});
			return;
		}
	}
# まとめてダウンロードの場合
	elsif($downflag eq "alldown") {
		my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
		$year = $year+1900;
		$mon  = $mon+1;

		my ($ysec, $ymin, $yhour, $ymday, $ymon, $yyear, $ywday, $yyday, $yisdst) = localtime(time-24*3600);
		$yyear = $yyear+1900;
		$ymon  = $ymon+1;

		opendir(DIR,"$dir_pass");

		my @dirfile = readdir(DIR);

		my @dirfile = sort @dirfile;

	    closedir(DIR);

		my $fname = undef;
		my $dname = undef;
		my $data;
		my $datefmt = "";

		if ($logdays eq "TODAY") {
			$mon  = sprintf("%02d",$mon);
			$mday = sprintf("%02d",$mday);

			$data = "$year$mon$mday";
			$datefmt = "$year$mon$mday";
		}
		elsif ($logdays eq "YESTERDAY") {
			$ymon  = sprintf("%02d",$ymon);
			$ymday = sprintf("%02d",$ymday);

			$data = "$yyear$ymon$ymday";
			$datefmt = "$yyear$ymon$ymday";
		}
		elsif($logdays eq "THISMONTH") {
			$mon = sprintf("%02d",$mon);

			$data = "$year$mon\\d\\d";
			$datefmt = "$year$mon";
		}
		elsif($logdays eq "LASTMONTH") {
			$mon = $mon-1;
		
			if($mon == 0){
				$mon = 12;
				$year = $year-1;
			}
			
			$mon = sprintf("%02d",$mon);
		
			$data = "$year$mon\\d\\d";
			$datefmt = "$year$mon";
		}
		elsif ($logdays eq "ALLRANGE") {
			if ($logtype eq "ACLOG") {
				$fname = "access_log.\\d\\d\\d\\d\\d\\d\\d\\d";
				$dname = "access_log.log";
			}
			else {
				$fname = "error_log.\\d\\d\\d\\d\\d\\d\\d\\d";
				$dname = "error_log.log";
			}
		}
		else{
			TF::CommonUtils::showErrorPage(	$MSGTABLE->{mErrRangeParam}, $LANGPARAM);
			return;
		}
	
		if ($logtype eq "ACLOG") {
			if (!$fname) {
				$fname = "access_log.$data";
			}
			if (!$dname) {
				$dname = "access_$datefmt.log";
			}

    		foreach my $line (@dirfile) {
	    		if($line =~/$fname$/){
		    		open (FH, "$dir_pass/$line");
					while (<FH>)
					{
						if(!$IS_LC_FILTER || $_=~ /\"[A-Z][A-Z]*[ ][ ]*$REG_LOCATION[\/| ]/){
							if (!$found) {
								print "Content-type:application/octet-stream\r\n";
								print "Content-Disposition:attachment; filename=$dname\n\n";
								$found = 1;
							}
					    	print ($_);
						}
					}
					close(FH);
				}
			}
		}
		elsif($logtype eq "ERRLOG") {
			if (!$fname) {
				$fname = "error_log.$data";
			}
			if (!$dname) {
				$dname = "error_$datefmt.log";
			}
		
			foreach my $line (@dirfile) {
				if($line =~/$fname$/) {
					open (FH, "$dir_pass/$line");
					while (<FH>)
					{
						if(!$IS_LC_FILTER || $_=~ /]\ \[[a-z:_]*\]\ \[pid\ [0-9]*\]\ $REG_LOCATION\ .*/){
							if (!$found) {
								print "Content-type:application/octet-stream\r\n";
								print "Content-Disposition:attachment; filename=$dname\n\n";
								$found = 1;
							}
					    	print ($_);
						}
					}
					close(FH);
			    }
	    	}
		}
		else {
			TF::CommonUtils::showErrorPage(	$MSGTABLE->{mErrTypeParam}, $LANGPARAM);
			return;
		}

		if (!$found) {
			TF::CommonUtils::showMessagePage(	$MSGTABLE->{mErrNoLogEntry},
												$LANGPARAM,
												$MSGTABLE->{mErrNoLogEntryT});
		}

	}
	else {
		TF::CommonUtils::showErrorPage(	$MSGTABLE->{mErrTypeParam}, $LANGPARAM);
		return;
	}
}
