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

#my $datematch = "^20210[234]";
#my $isodatematch = "(Feb|Mar|Apr).*2021\$";

#my $datematch = "^20210[567]";
#my $isodatematch = "(May|Jun|Jul).*2021\$";

#q4 2021
#my $datematch = "^2021(10|08|09)";
#my $isodatematch = "(Aug|Sep|Oct).*2021\$";

# q1 2022
#my $datematch = "^(2021(11|12)|2022(01))";
#my $isodatematch = "((Nov|Dec).*2021|Jan.*2022)\$";

# full year 2022
#my $datematch = "^2023";
#my $isodatematch = "2023";

# q2 2022
#my $datematch = "^20220[234]";
#my $isodatematch = "(Feb|Mar|Apr).*2022\$";

# q3 2022
#my $datematch = "^20220[567]";
#my $isodatematch = "(May|Jun|Jul).*2022\$";

# FY 2022
#my $datematch = "^(20211[12]|2022(0|10))";
#my $isodatematch = "(((Nov|Dec).*2021)|((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct).*2022))";
# FY 2021
#my $datematch = "^(20201[12]|2021(0|10))";
#my $isodatematch = "(((Nov|Dec).*2020)|((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct).*2021))";

#q4 2022
#my $datematch = "^2022(10|08|09)";
#my $isodatematch = "(Aug|Sep|Oct).*2022\$";

#q4 2023
#my $datematch = "^2023(10|08|09)";
#my $isodatematch = "(Aug|Sep|Oct).*2023\$";

# q1 2024
my $datematch = "^(2023(11|12)|2024(01))";
my $isodatematch = "((Nov|Dec).*2023|Jan.*2024)\$";

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

use DateTime;

require CanDBReader;
require SMASHData;
require UpdateInfoReader;
UpdateInfoReader->import_product_updates();

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

	my $basescore = "unknown";
	&SMASHData::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'} (SUSE)";
		} else {
			if (defined($entry{'National Vulnerability Database'})) {
				%score = %{$entry{'National Vulnerability Database'}};
				$basescore = "$score{'base_score'}";
			}
		}
	}
	return $basescore;
}


my %cves = ();
my %cves4 = ();
my %cves7 = ();
my %cves9 = ();

# collect incoming CVEs...

foreach my $cve (keys %CanDBReader::firstdate) {
	next unless ($CanDBReader::firstdate{$cve} =~ /$datematch/);

	# print "$cve $CanDBReader::firstdate{$cve}\n";

	&SMASHData::read_smash_issue($cve);

	next unless ($SMASHData::pkgstate{$cve});	# at least 1 product has the package...
	$cves{$cve} = 1;

	my $score = getscore($cve);

	# print "$cve has score $score\n";

	next if ($score eq "unknown");
	next if ($score =~ /^[0-3]/);
	$cves4{$cve} = 1;
	next if ($score =~ /^[0-6]/);
	$cves7{$cve} = 1;
	next if ($score =~ /^[7-8]/);
	$cves9{$cve} = 1;
}

my @cves = keys %cves;
my @cves4 = keys %cves4;
my @cves7 = keys %cves7;
my @cves9 = keys %cves9;

print "IM:\n";
print "	All CVEs: "  . $#cves . "\n";
print "		of those, CVEs with score >= 4.0: "  . $#cves4 . "\n";
print "		of those, CVEs with score >= 7.0: "  . $#cves7 . "\n";
print "		of those, CVEs with score >= 9.0: "  . $#cves9 . "\n";

my $updatecount = 0;
my $updatecount4 = 0;
my $updatecount7 = 0;
my $updatecount9 = 0;
my $lpupdatecount = 0;
my $sleupdatecount = 0;
my $sleupdatecount4 = 0;
my $sleupdatecount7 = 0;
my $sleupdatecount9 = 0;
my %releasedcves = ();
my %slereleasedcves = ();

my %ltssupdates = ();

foreach my $advisory (keys %CanDBReader::advisoryid2date) {
	next unless ($advisory =~ /SUSE-SU/);

	# we imported opensuse advisory feb 21 ... so skip those inthis round.
	#next if ($advisory =~ /openSUSE-SU-2020/);
	#if ($advisory =~ /openSUSE-SU-2021:(\d*)/) {
	#	#2021:0274-
	#	next if ($1 <= 274);
	#}
	# end of skip

	next unless ($CanDBReader::advisoryid2date{$advisory} =~ /$isodatematch/);
	next unless ($advisory =~ /-2023/);

	#	print "$advisory $CanDBReader::advisoryid2date{$advisory}\n";

	$updatecount++;
	$sleupdatecount++ if ($advisory =~ /^SUSE-SU/);

	if (!defined($CanDBReader::susenotice2patches{$advisory})) {
		print STDERR "no patches for $advisory?\n";
		next;
	}
	my %patches = %{$CanDBReader::susenotice2patches{$advisory}};

	# print "patches: " . join (",", keys %patches);

	my $over4 = 0;
	my $over7 = 0;
	my $over9 = 0;

	my $onlylp = 1;

	my $issle15 = 0;
	foreach my $patch (keys %patches) {
		unless (defined($UpdateInfoReader::patchreferences{$patch})) {
			#print "no references in $patch?\n";
			next;
		}

		foreach my $pkg (keys %{$UpdateInfoReader::patchpackages{$patch}}) {
			if ($pkg !~ /kernel-livepatch/ && $pkg !~ /kgraft-/) {
				$onlylp = 0;
				last;
			}
		}

		#if ($patch =~ /-15-SP3/)	{ # only count SLE15.
		#	$issle15 = 1;
		#} else {
		#	next;
		#}

		# if patchname contains LTSS
		$ltssupdates{$advisory}= 1 if ($patch =~ /LTSS/);

		my %refs = %{$UpdateInfoReader::patchreferences{$patch}};

		foreach my $reference (keys %refs) {
			next unless ($reference =~ /^CVE-/);

			$releasedcves{$reference} = 1;
			$slereleasedcves{$reference} = 1 if ($advisory =~ /^SUSE-SU/);

			my $score = getscore($reference);
			if (($score ne "unknown") && ($score !~ /^[0-3]/)) {
				$over4 = 1;
			}
			if (($score ne "unknown") && ($score !~ /^[0-6]/)) {
				$over7 = 1;
			}
			if (($score ne "unknown") && ($score !~ /^[0-8]/)) {
				$over9 = 1;
			}
		}
	}

	#next unless ($issle15);

	if ($onlylp) {
		#print "$advisory is LP only\n" if -t STDERR;
		$lpupdatecount++ if ($advisory =~ /^SUSE-SU/);
	}
	if ($over4) {
		$updatecount4++;
		$sleupdatecount4++ if ($advisory =~ /^SUSE-SU/);
	}
	if ($over7) {
		$updatecount7++;
		$sleupdatecount7++ if ($advisory =~ /^SUSE-SU/);
	}
	if ($over9) {
		$updatecount9++;
		$sleupdatecount9++ if ($advisory =~ /^SUSE-SU/);
	}
}

my $ltsscount = keys %ltssupdates;

print "UM:\n";
print "	Total SUSE security updates/patches released: $updatecount (SLE $sleupdatecount, openSUSE ". ($updatecount-$sleupdatecount) . ")\n";
print "		of those, containing a CVE with CVSSv3 >= 4.0: $updatecount4 (SLE $sleupdatecount4, openSUSE " . ($updatecount4 - $sleupdatecount4) . ")\n";
print "		of those, containing a CVE with CVSSv3 >= 7.0: $updatecount7 (SLE $sleupdatecount7, openSUSE " . ($updatecount7 - $sleupdatecount7) . ")\n";
print "		of those, containing a CVE with CVSSv3 >= 9.0: $updatecount9 (SLE $sleupdatecount9, openSUSE " . ($updatecount9 - $sleupdatecount9) . ")\n";
print "		of SLES updates are LTSS $ltsscount\n";
print "		of SLES updates are Kernel Livepatch Updates $lpupdatecount\n";
my @releasedcves = keys %releasedcves;
my @slereleasedcves = keys %slereleasedcves;
print "	Total unique CVEs released: " . $#releasedcves ." (unique in SLE Updates: " . $#slereleasedcves . ")\n";
