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

my $dn = `dirname $0`;chomp($dn);
my $pwd = `pwd`;chomp($pwd);
if ($dn !~ /^\//) { $dn = $pwd . "/" . $dn; }
push @INC,$dn;

use DateTime;

require CanDBReader;
require ModuleContained;
require UpdateInfoReader;
UpdateInfoReader->import_images();
require SMASHData;

sub
getscore($) {
	my ($cve) = @_;

	my $basescore = "unknown";
	read_smash_issue($cve);

	if (defined($SMASHData::cvssv3{$cve}))  {
		my %entry = %{$SMASHData::cvssv3{$cve}};
		my %score;
		if (defined($entry{'SUSE'})) {
			%score = %{$entry{'SUSE'}};
			$basescore = $score{'base_score'};
		} else {
			if (defined($entry{'National Vulnerability Database'})) {
				%score = %{$entry{'National Vulnerability Database'}};
				$basescore = $score{'base_score'};
			}
		}
	}
	return $basescore;
}

my %scores = ();
sub
cvsscmp($$) {
	my ($cvea,$cveb) = @_;
	my $scorea;
	my $scoreb;

	if (!defined($scores{$cvea})) {
		$scorea = getscore($cvea);
		$scores{$cvea} = $scorea;
	} else {
		$scorea = $scores{$cvea};
	}
	if (!defined($scores{$cveb})) {
		$scoreb = getscore($cveb);
		$scores{$cveb} = $scoreb;
	} else {
		$scoreb = $scores{$cveb};
	}
	return -1 if ($scorea < $scoreb);
	return  1 if ($scorea > $scoreb);
	return $cvea cmp $cveb;
}


read_all_cached_issues();

my %cstate = ();

# squid CVE which is tagged as released, but was not mentioned in updateinfo
delete $SMASHData::pkgstate{"CVE-2016-5408"};

# 9.x salt CVEs which are tagged as released, but was not mentioned in updateinfo
delete $SMASHData::pkgstate{"CVE-2021-3197"};
delete $SMASHData::pkgstate{"CVE-2021-3148"};
delete $SMASHData::pkgstate{"CVE-2021-25282"};
delete $SMASHData::pkgstate{"CVE-2021-25281"};
delete $SMASHData::pkgstate{"CVE-2020-25592"};
delete $SMASHData::pkgstate{"CVE-2020-16846"};
delete $SMASHData::pkgstate{"CVE-2020-35662"};
delete $SMASHData::pkgstate{"CVE-2021-3144"};


foreach my $cve (keys %SMASHData::pkgstate) {
	# SMASH Status Info
	if (defined($SMASHData::codestreampkgstate{$cve})) {
		my %state = %{$SMASHData::codestreampkgstate{$cve}};

		foreach my $codestream (keys %state) {
			my %pkg = %{$state{$codestream}};

			foreach my $pkg (keys %pkg) {
				next unless (defined($UpdateInfoReader::codestreampkg2container{"$codestream.$pkg"}));

				next if ($pkg{$pkg} eq "Not affected");
				next if ($pkg{$pkg} eq "Already fixed");
				next if ($pkg{$pkg} eq "Ignore");

				foreach my $container (keys %{$UpdateInfoReader::codestreampkg2container{"$codestream.$pkg"}}) {
					# "Codestream released" does not imply "container released"... we pick this up
					# from the last container info we loaded.
					$cstate{$cve}->{$container}->{$pkg} = $pkg{$pkg};
					if (($pkg{$pkg} eq "Released") && (!defined($UpdateInfoReader::containerpkgfixedcve{$container}->{$pkg}->{$cve}))) {
						$cstate{$cve}->{$container}->{$pkg} = "Unreleased";
					}
				}
			}
		}
	}
}

# CVE -> {container}
my %unreleased = ();
my %inprogress = ();
my %affected = ();

foreach my $cve (keys %cstate) {
	my %xcstate = %{$cstate{$cve}};

	foreach my $container (keys %xcstate) {
		next if ($container =~ /LI-BYOS/);	# skip VLI-BYOS and LI-BYOS currently.
		next if ($container =~ /Manager-4-0/);	# Manager 4.0 is EOL on pubcloud
		next if ($container =~ /OCI/);		# OCI wont get refreshed

		next if ($container =~ /SLES15-SP2-HPC-Azure/);		#	EOL
		next if ($container =~ /SLES15-SP2-EC2-ECS-HVM/);	#	EOL
		next if ($container =~ /CAP-DEPL/);	#	cap-deployment is EOL

		my %pkgs = %{$xcstate{$container}};
		foreach my $pkg (keys %pkgs) {
			if ($pkgs{$pkg} eq "Unreleased") {
				$unreleased{$cve}->{$container} = $pkg;
			}
			if ($pkgs{$pkg} eq "In progress") {
				$inprogress{$cve}->{$container} = $pkg;
			}
			if ($pkgs{$pkg} eq "Affected") {
				$affected{$cve}->{$container} = $pkg;
			}
		}
	}
}

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year += 1900;
$mon += 1;

my $ts = sprintf("%04d-%02d-%02d",$year,$mon,$mday);


open(PUBCLOUD,">logs/pubcloud-unreleased-$ts.txt");
foreach my $cve (reverse sort cvsscmp keys %unreleased) {
	my %pkg = ();
	foreach my $container (keys $unreleased{$cve}) {
		$pkg{$unreleased{$cve}->{$container}} = 1;
	}
	print PUBCLOUD "$cve - $scores{$cve} - " . join(",",sort keys %pkg) . " - " .join(",",sort keys $unreleased{$cve}) . "\n";
}
close(PUBCLOUD);

open(PUBCLOUD,">logs/pubcloud-inprogress-$ts.txt");
foreach my $cve (reverse sort cvsscmp keys %inprogress) {
	my %pkg = ();
	foreach my $container (keys $inprogress{$cve}) {
		$pkg{$inprogress{$cve}->{$container}} = 1;
	}
	print PUBCLOUD "$cve - $scores{$cve} - " . join(",",sort keys %pkg) . " - " .join(",",sort keys $inprogress{$cve}) . "\n";
}
close(PUBCLOUD);

open(PUBCLOUD,">logs/pubcloud-affected-$ts.txt");
foreach my $cve (reverse sort cvsscmp keys %affected) {
	my %pkg = ();
	foreach my $container (keys $affected{$cve}) {
		$pkg{$affected{$cve}->{$container}} = 1;
	}
	print PUBCLOUD "$cve - $scores{$cve} - " . join(",",sort keys %pkg) . " - " .join(",",sort keys $affected{$cve}) . "\n";
}
close(PUBCLOUD);
print "SUCCESS\n";
