package PVE::APLInfo;

use strict;
use IO::File;
use PVE::SafeSyslog;
use PVE::I18N;
use LWP::UserAgent;
use PVE::Config;
use POSIX qw(strftime);

my $logfile = "/var/log/pveam.log";

# Default list of GPG keys allowed to sign aplinfo
#
#pub   1024D/5CAC72FE 2004-06-24
#      Key fingerprint = 9ABD 7E02 AD24 3AD3 C2FB  BCCC B0C1 CC22 5CAC 72FE
#uid                  Proxmox Support Team <support@proxmox.com>

my $valid_keys = {
    '9ABD7E02AD243AD3C2FBBCCCB0C1CC225CAC72FE' => 1, # fingerprint support@proxmox.com
    '25CAC72FE' => 1,                                # keyid support@proxmox.com
};

sub import_gpg_keys {

    my $keyfile = '/usr/share/doc/pve-manager/support@proxmox.com.pubkey';

    return system ("/usr/bin/gpg --batch --no-tty --status-fd=1 -q " .
		   "--logger-fd=1 --import $keyfile >>$logfile");
}

sub logmsg {
    my ($logfd, $msg) = @_;

    chomp $msg;

    my $tstr = strftime ("%b %d %H:%M:%S", localtime);

    foreach my $line (split (/\n/, $msg)) {
	print $logfd "$tstr $line\n";
    }
}

sub url_get {
    my ($ua, $url, $file, $logfh) = @_;

    my $req = HTTP::Request->new(GET => $url);

    logmsg ($logfh, "start download $url");
    my $res = $ua->request($req, $file);

    if ($res->is_success) {
	logmsg ($logfh, "download finished: " . $res->status_line);
	return 0;
    }

    logmsg ($logfh, "download failed: " . $res->status_line);

    return 1;
}

sub update {
    my ($proxy) = @_;

    my $aplurl = "http://download.proxmox.com/appliances";
    my $aplsrcurl = "$aplurl/aplinfo.dat.gz";
    my $aplsigurl = "$aplurl/aplinfo.dat.asc";

    my $size;
    if (($size = (-s $logfile) || 0) > (1024*50)) {
	system ("mv $logfile $logfile.0");
    }
    my $logfd = IO::File->new (">>$logfile");
    logmsg ($logfd, "starting update");

    import_gpg_keys();

    my $tmp = "/tmp/pveam.tmp.$$";
    my $tmpgz = "$tmp.gz";
    my $sigfn = "$tmp.asc";

    # this code works for ftp and http
    # always use passive ftp
    local $ENV{FTP_PASSIVE} = 1;
    my $ua = LWP::UserAgent->new;
    $ua->agent("PVE/1.0");

    if ($proxy) {
	$ua->proxy(['http'], $proxy);
    } else {
	$ua->env_proxy;
    }

    eval {
	if (url_get ($ua, $aplsigurl, $sigfn, $logfd) != 0) {
	    die "update failed - no signature\n";
	}

	if (url_get ($ua, $aplsrcurl, $tmpgz, $logfd) != 0) {
	    die "update failed - no data\n";
	}
 
	if (system ("zcat -f $tmpgz >$tmp 2>/dev/null") != 0) {
	    die "update failed: unable to unpack '$tmpgz'\n";
	} 

	# verify signature

	my $cmd = "/usr/bin/gpg --verify --batch --no-tty --status-fd=1 -q " .
	    "--logger-fd=1 $sigfn $tmp";

	open (CMD, "$cmd|") ||
	    die "unable to execute '$cmd': $!\n";

	my $line;
	my $signer = '';
	while (defined ($line = <CMD>)) {
	    chomp $line;
	    logmsg ($logfd, $line);

	    # code borrowed from SA
	    next if $line !~ /^\Q[GNUPG:]\E (?:VALID|GOOD)SIG (\S{8,40})/;
	    my $key = $1;  

	    # we want either a keyid (8) or a fingerprint (40)
	    if (length $key > 8 && length $key < 40) {
		substr($key, 8) = '';
	    }
	    # use the longest match we can find
	    $signer = $key if (length $key > length $signer) && $valid_keys->{$key};
	}

	close (CMD);

	die "unable to verify signature\n" if !$signer;

	logmsg ($logfd, "signature valid: $signer");

	# test syntax
	eval { 
	    my $fh = IO::File->new ("<$tmp") ||
		die "unable to open file '$tmp' - $!\n";
	    PVE::Config::read_aplinfo ($tmp, $fh, 1);
	    close ($fh);
	};
	die "update failed: $@" if $@;

	if (system ("mv $tmp /var/lib/pve-manager/apl-available 2>/dev/null") != 0) { 
	    die "update failed: unable to store data\n";
	}

	logmsg ($logfd, "update sucessful");
    };

    my $err = $@;

    unlink $tmp;
    unlink $tmpgz;
    unlink $sigfn;

    if ($err) {
	logmsg ($logfd, $err);
	close ($logfd);

	return 0;
    } 

    close ($logfd);

    return 1;
}

sub load_data {

    my $filename = "/var/lib/pve-manager/apl-available";

    if (! -f $filename) {
	system ("cp /usr/share/doc/pve-manager/aplinfo.dat /var/lib/pve-manager/apl-available");
    }

    return PVE::Config::read_file ('aplinfo');
}

sub display_name {
    my ($template) = @_;

    my $templates = load_data ();

    return $template if !$templates;

    my $d =  $templates->{'all'}->{$template};

    $template =~ s/\.tar\.gz$//;
    $template =~ s/_i386$//;

    return $template if !$d;

    return "$d->{package}_$d->{version}";
}

sub pkginfo {
    my ($template) = @_;

    my $templates = load_data ();

    return undef if !$templates;

    my $d =  $templates->{'all'}->{$template};

    return $d;
}

sub webnews {
    my ($lang) = @_;

    my $templates = load_data ();

    my $html = '';

    $html .= __("<b>Welcome</b> to the Proxmox Virtual Environment!");
    $html .= "<br><br>";
    $html .= __("For more information please visit our homepage at");
    $html .= " <a href='http://www.proxmox.com' target='_blank'>www.proxmox.com</a>.";

    return $html if !$templates;

    # my $d = $templates->{'all'}->{"pve-web-news-$lang"} ||
    my $d = $templates->{all}->{'pve-web-news'};

    return $html if !$d;

    return $d->{description};
}

1;