#!/usr/bin/perl
#
# This code is distributed under the terms of the GPL
#
# (c) 2006-2008 marco.s - http://update-accelerator.advproxy.net
#
# Portions (c) 2008 by dotzball - http://www.blockouttraffic.de
#
# $Id: checkdeaddl,v 1.1 2008/11/29 00:00:00 marco.s Exp $
#

use strict;

use Fcntl ':flock';  # import LOCK_* constants
use HTTP::Date;

require '/var/ipfire/updatexlrator/updxlrator-lib.pl';

my $repository='/var/updatecache';
my $logfile="/var/log/updatexlrator/download.log";
my $logging=0;
my $debug=0;
my %proxysettings=();
my %xlratorsettings=();
my $updatefile='';
my @downloads=();
my $passive_mode=0;
my $maxusage=0;
my $nice='';
my $lockfile = "/var/log/updatexlrator/checkdeaddl.lck";

&debuglog("Check if there is a lock ");
open SEM, ">$lockfile" or die "Can't write-open $lockfile: $!";
flock SEM, LOCK_EX;
&debuglog("No lock, proceed ");

&writelog("Check for dead downloads ");

if (-e "${UPDXLT::apphome}/settings")
{
	&UPDXLT::readhash("${UPDXLT::apphome}/settings", \%xlratorsettings);
        if ($xlratorsettings{'ENABLE_LOG'} eq 'on') { $logging=1; };
	if ($xlratorsettings{'PASSIVE_MODE'} eq 'on') {	$passive_mode=1; };
	if ($xlratorsettings{'LOW_DOWNLOAD_PRIORITY'} eq 'on') { $nice='/bin/nice --adjustment=15 '; };
	$maxusage = $xlratorsettings{'MAX_DISK_USAGE'};
}
else
{
	&writelog("Updatexlrator not enabled, exit");
	exit 0;
}
if (!$maxusage) { $maxusage=75; };

if($passive_mode || (&UPDXLT::diskusage($repository) > $maxusage))
{
	# nothing to do
	&writelog("Running in passive mode or maximum diskusage exceeded, exit");
	exit 0;
}


if (-e "${UPDXLT::swroot}/proxy/settings") { &UPDXLT::readhash("${UPDXLT::swroot}/proxy/settings", \%proxysettings); }

if (-e "${UPDXLT::swroot}/proxy/advanced/settings")
{
	%proxysettings=();
	&UPDXLT::readhash("${UPDXLT::swroot}/proxy/advanced/settings", \%proxysettings);
}


foreach my $dir (<$repository/download/*>)
{
	if (-d $dir)
	{
		foreach my $updatefile (<$dir/*>)
		{
			unless ($updatefile =~ /.info$/)
			{
				push(@downloads, $updatefile);
			}
		}
	}
}

foreach my $updatefile (@downloads)
{
	if(-e "$updatefile.info")
	{
		&checkdeaddl($updatefile);
	}
}


# clean lock file
close(SEM);
unlink "$lockfile";

# -------------------------------------------------------------------

sub checkdeaddl
{
	my $updatefile = shift;

	my %dlinfo = ();
	&UPDXLT::readhash("$updatefile.info", \%dlinfo);

	my @http_header = ();
	my $http_result = '000 n/a';
	my $returncode = 0;
	my $remote_size = 0;
	my $remote_mtime = 0;
	my $login = '';

	my $cmd_ps = "/bin/ps aux | /bin/grep -E \"(download|wget).*$dlinfo{'SRCURL'}\" | /bin/grep -v \"/bin/grep\"";
	my @runningdl = `$cmd_ps`;

	if(@runningdl > 0)
	{
		# download is still running, no need to restart download
		return;
	}

	if (($proxysettings{'UPSTREAM_PROXY'}) && ($proxysettings{'UPSTREAM_USER'}))
	{
		$login = "--proxy-user=\"$proxysettings{'UPSTREAM_USER'}\"";
		if ($proxysettings{'UPSTREAM_PASSWORD'})
		{
			$login .= " --proxy-password=\"$proxysettings{'UPSTREAM_PASSWORD'}\"";
		}
	}

	$ENV{'http_proxy'} = $proxysettings{'UPSTREAM_PROXY'};
	@http_header = `${UPDXLT::wget} $login --user-agent="${UPDXLT::useragent}" --spider -S $dlinfo{'SRCURL'} 2>&1`;
	$ENV{'http_proxy'} = '';

	foreach (@http_header)
	{
		chomp;
		if (/^\s*HTTP\/\d+\.\d+\s\d+\s+\w+/) { $http_result = $_; $http_result =~ s/^\s*HTTP\/\d+\.\d+\s+//; }
		if (/^\s*Content-Length:\s/) { $remote_size = $_; $remote_size =~ s/[^0-9]//g; }
		if (/^\s*Last-Modified:\s/) { $remote_mtime = $_; $remote_mtime =~ s/^\s*Last-Modified:\s//; $remote_mtime = HTTP::Date::str2time($remote_mtime) }
	}

	&writelog($updatefile);
	&writelog("HTTP result: $http_result");
	&writelog("Source time: $remote_mtime");
	&writelog("Cached time: " . $dlinfo{'REMOTETIME'});

	if ($http_result =~ /\d+\s+OK$/)
	{
		my $cmd = "$nice$UPDXLT::apphome/bin/download $dlinfo{'VENDORID'} $dlinfo{'SRCURL'} $dlinfo{'CFMIRROR'}";

		if ($remote_size > &UPDXLT::diskfree($repository))
		{
			&writelog("Can't download file, because remote filesize exceeds maximum diskusage");
		}
		elsif ($remote_mtime == $dlinfo{'REMOTETIME'})
		{
			# still the same file, continue download
			&writelog("Status: Ok, continue download");
			$cmd .= " 1 &";
			&debuglog("Running command $cmd");
			system("$cmd");
		}
		else
		{
			# File is changed on remote site, download from scratch
			&writelog("Status: Outdated, restart download from scratch");
			unlink($updatefile);
			$cmd .= " 0 &";
			&debuglog("Running command $cmd");
			system("$cmd");
		}
	} else {
		$_ =  $http_result;
		s/\D+//;
		if ($_ eq '404')
		{
			&writelog("Status: No source");
			$dlinfo{'STATUS'} = ${UPDXLT::sfNoSource};
		} else {
			&writelog("Status: Error");
			$dlinfo{'STATUS'} = ${UPDXLT::sfUnknown};
		}
		&UPDXLT::writehash("$updatefile.info", \%dlinfo);
	}
}

# -------------------------------------------------------------------

sub writelog
{
	if ($logging)
	{
		open (LOGFILE,">>$logfile");
		my @now = localtime(time);
		printf LOGFILE "%04d-%02d-%02d %02d:%02d:%02d [%d] %s\n",$now[5]+1900,$now[4]+1,$now[3],$now[2],$now[1],$now[0],$$,$_[0];
		close LOGFILE;
	}
}

# -------------------------------------------------------------------

sub debuglog
{
	if ($debug)
	{
		open(LOGFILE,">>/var/log/updatexlrator/debug.log");
		my @now = localtime(time);
		printf LOGFILE "%04d-%02d-%02d %02d:%02d:%02d [%d] [%s] %s\n",$now[5]+1900,$now[4]+1,$now[3],$now[2],$now[1],$now[0],$$,"updxlrator",$_[0];
		close(LOGFILE);
	}
}

# -------------------------------------------------------------------
