#!/usr/bin/perl -w
use strict;

use XML::Bare;
use Data::Dumper;

my $osc="osc -A https://api.opensuse.org/";

my $data = "data/ga/opensuse_tumbleweed.csv";

my ($dummy1,$dummy2,$dummy3,$mday,$mon,$year,$dummy4,$dummy5,$dummy6) = localtime(time);
my $currentdate = sprintf("%04d%02d%02d",$year+1900,$mon+1,$mday);

# package -> cve -> 1
my $havecves;

open(DATA,"<$data")||die "$data:$!\n";
while (<DATA>) {
	#libXxf86vm-devel-1.1.4-1.7;libXxf86vm-devel-32bit-1.1.4-1.7;libXxf86vm1-1.1.4-1.7;libXxf86vm1-32bit-1.1.4-1.7,CVE-2013-2001
	chomp;

	my ($date,$srcpkg,$packages,@cves) = split(/,/);

	my @packages = split(/;/,$packages);
	foreach my $pkg (@packages) {
		$pkg =~ s/-[^-]*-[^-]*$//;
		foreach my $cve (@cves) {
			$havecves->{$pkg}->{$cve} = 1;
		}
	}
}
close(DATA);

my $packages;
if (open(PREVIOUSFACTORY,"<smash/factory.xml")) {
	my $xml = join("\n", <PREVIOUSFACTORY>);
	close(PREVIOUSFACTORY);
        my $xmlparser = new XML::Bare( text => $xml ) || die "smash/factory.xml XML: $xml";
        my $xmlroot = $xmlparser->parse()||die;

        $packages = XML::Bare::forcearray($xmlroot->{'packages'});
}

my %packageversions = ();

#print STDERR "xx: " . Dumper($packages);


foreach my $pkg (@{$packages->[0]->{package}}) {
	my $name = $pkg->{name}->{value};
	my $version = $pkg->{version}->{value};
	my $release = $pkg->{release}->{value};
	#print STDERR $name ." . ". $version . " . " . $release . "\n";

	next if (!defined($version));
	$packageversions{$name} = $version . "-" . $release;
}

my $newpackages;
system("$osc api /status/project/openSUSE:Factory > smash/factory.new.xml");
if (open(NEWFACTORY,"<smash/factory.new.xml")) {
	my $xml = join("\n", <NEWFACTORY>);
	close(NEWFACTORY);
        my $xmlparser = new XML::Bare( text => $xml ) || die "smash/factory.xml XML: $xml";
        my $xmlroot = $xmlparser->parse()||die;

        $newpackages = XML::Bare::forcearray($xmlroot->{'packages'});
}

my @changed = ();

foreach my $pkg (@{$newpackages->[0]->{package}}) {
	my $name = $pkg->{name}->{value};
	my $version = $pkg->{version}->{value};
	my $release = $pkg->{release}->{value};

	#print STDERR $name ." . ". $version . " . " . $release . "\n";

	next if (!defined($version));
	if (!defined($packageversions{$name})) {
		print STDERR "NEW package: $name $version-$release\n" if -t STDERR;
		push @changed, $name;
	} else {
		if ( $packageversions{$name} ne "$version-$release") {
			print STDERR "CHANGE $name: " . $packageversions{$name} . " to " . "$version-$release\n" if -t STDERR;
			push @changed, $name;
		}
		# else unchanged
	}
}
#print STDERR Dumper($packages);

rename("smash/factory.new.xml","smash/factory.xml");

open(NEWDATA,">>$data")||die "$data:$!";

foreach my $srcpkg (@changed) {
	open(CHANGES,"$osc api /source/openSUSE:Factory/$srcpkg/$srcpkg.changes|");
	my %cves = ();
	while (<CHANGES>) {
		chomp;
		if (/(CVE-\d\d\d\d-\d\d\d\d\d*)/) {
			$cves{$1} = 1;
			s/(CVE-\d\d\d\d-\d\d\d\d\d*)//;
		}
	}
	# print STDERR "$srcpkg: " . join(",",sort keys %cves) . "\n";
	next unless (%cves);

	close(CHANGES);
	open(BINARIES,"$osc api /build/openSUSE:Factory/standard/x86_64/$srcpkg|");
	my %binpkgs = ();
	my $version;
	while (<BINARIES>) {
		# too lazy to write xml parser
		next unless (/<binary filename="([^"]*)" /);
		my $binpkg = $1;

		next unless ($binpkg =~ /(noarch|x86_64).rpm/);

		next if ($binpkg =~ /-debuginfo/);
		next if ($binpkg =~ /-debugsource/);

		$binpkg =~ s/::import::i586:://;

		$binpkg =~ s/.(noarch|x86_64).rpm$//;
		$binpkgs{$binpkg} = 1;

		my $binpkgnoversion = $binpkg;
		$binpkgnoversion =~ s/-([^-]*-[^-]*)$//;	# will strip -version-release.arch.rpm
		$version = $1;
		foreach my $cve (keys %cves) {
			if ($havecves->{$binpkgnoversion}->{$cve}) {
				# print STDERR "have $cve for $binpkgnoversion already, skipping.\n";
				delete $cves{$cve};
			}
		}
	}
	close(BINARIES);
	if (%cves && %binpkgs) {
		print NEWDATA "$currentdate,$srcpkg," . join(";",sort keys %binpkgs) . "," . join(",",sort keys %cves) . "\n";
		print "$currentdate,$srcpkg," . join(";",sort keys %binpkgs) . "," . join(",",sort keys %cves) . "\n";
	}
	if (!%binpkgs) {
		print "no binpkgs for $srcpkg?\n";
	}
}
close(NEWDATA);
print "SUCCESS\n";
0;
