#!/usr/bin/perl -w
# This is the logic to read can-numbers
use strict;

my $dn = `dirname $0`;chomp($dn);
my $cverepobase=`dirname $dn`;
chomp($cverepobase);

package CanDBReader;

use Data::Dumper;

%CanDBReader::bugzillas=();
%CanDBReader::embargoed=();
%CanDBReader::crds=();
%CanDBReader::allcans=();
%CanDBReader::advisories = ();
%CanDBReader::advisoryids = ();
%CanDBReader::advisoryid2url = ();
%CanDBReader::advisoryid2date = ();
%CanDBReader::advisoryid2cve = ();	# "SUSE-SU" -> { $cve: 1 }
%CanDBReader::note = ();
%CanDBReader::packagenotes = ();
%CanDBReader::kernelcvedates = ();	# SP -> cve -> fixeddate

%CanDBReader::susenotice2patches = ();
%CanDBReader::patch2susenotice = ();

%CanDBReader::firstdate = ();

%CanDBReader::bugzilla_state = ();
%CanDBReader::bugzilla_resolution = ();
%CanDBReader::bugzilla_severity = ();
%CanDBReader::bugzilla_priority = ();

my $can;
my $date;
my $info;
my @info;
my $tag;
my $data;

my @canfiles = (
#	"/suse/meissner/Export/can-numbers",
	"$cverepobase/data/notes",
	"$cverepobase/data/cve2bugzilla"
);

foreach my $canfile (@canfiles) {
print STDERR "Reading $canfile...\n" if (-t STDERR);
open(INFILE,"<$canfile")||die "open:$!";
while (<INFILE>) {
	chomp;
	undef $can;
	undef $date;
	undef $info;
	undef @info;
	($can,$date,@info) = split(/,/);
	$info = join(",",@info);
	
	$can =~ s/^CAN/CVE/;	# all CANs are now CVEs.

	if ($info =~ /^([^:]*):(.*)$/) {
		$tag = $1;
		$data = $2;
	} else {
		next;
	}

	if (	!defined($CanDBReader::firstdate{$can})	||
		($CanDBReader::firstdate{$can} eq "")	||
		($CanDBReader::firstdate{$can} > $date)
	) {
		$CanDBReader::firstdate{$can} = $date;
	}
	$CanDBReader::allcans{$can} = 1;
	if ($tag eq "EMBARGOED") {
		$CanDBReader::embargoed{$can} = 1;
	}
	if ($tag eq "CRD") {
		$CanDBReader::crds{$can} = $data;	# fixme validate date
	}
	if ($tag eq "BUGZILLA") {
		if (!defined($CanDBReader::bugzillas{$can})) {
			$CanDBReader::bugzillas{$can} = $data;
		} else {
			if (!grep(/$data/,$CanDBReader::bugzillas{$can})) {
				$CanDBReader::bugzillas{$can} .= ",$data";
			}
		}
	}
	if ($tag eq "ADVISORY") {
		if (!defined($CanDBReader::advisories{$can})) {
			$CanDBReader::advisories{$can} = $data;
		} else {
			if (!grep(/$data/,$CanDBReader::advisories{$can})) {
				$CanDBReader::advisories{$can} .= ",$data";
			}
		}
	}
	if ($tag eq "ADVISORYID") {
		$CanDBReader::advisoryid2cve{$data}->{$can} = 1;
		if (!defined($CanDBReader::advisoryids{$can})) {
			$CanDBReader::advisoryids{$can} = $data;
		} else {
			if (!grep(/$data/,$CanDBReader::advisoryids{$can})) {
				$CanDBReader::advisoryids{$can} .= ",$data";
			}
		}
	}
	if ($tag eq "NOTE") {
		if (!defined($CanDBReader::note{$can})) {
			$CanDBReader::note{$can} = $data;
		} else {
			# avoid duplication after I split off the notes
			if ($data ne $CanDBReader::note{$can}) {
				$CanDBReader::note{$can} .= ",$data";
			}
		}
	}
}
close(INFILE);
}
print STDERR "Done /suse/meissner/Export/can-numbers...\n" if (-t STDERR);

open(INFILE,"$cverepobase/data/advisories")||die "open $cverepobase/data/advisories:$!";
while (<INFILE>) {
	chomp;
	unless (/^([^,]*),([^,]*),([^:]*):(.*)/) {
		print STDERR;
		next;
	}
	my $cve = $1;
	my $date = $2;
	my $tag = $3;
	my $data = $4;

	$cve =~ s/^CAN/CVE/;	# all CANs are now CVEs.

	if ($tag eq "ADVISORY") {
		if (!defined($CanDBReader::advisories{$cve})) {
			$CanDBReader::advisories{$cve} = $data;
		} else {
			if (!grep(/$data/,$CanDBReader::advisories{$cve})) {
				$CanDBReader::advisories{$cve} .= ",$data";
			}
		}
	}
	if ($tag eq "ADVISORYID") {
		next if ($data  =~ /openSUSE-SU-22022/);	# one bad apple
		next if ($data  =~ /openSUSE-SU-42022-1/);	# one bad apple
		$CanDBReader::advisoryid2cve{$data}->{$cve} = 1;
		if (!defined($CanDBReader::advisoryids{$cve})) {
			$CanDBReader::advisoryids{$cve} = $data;
		} else {
			if (!grep(/$data/,$CanDBReader::advisoryids{$cve})) {
				$CanDBReader::advisoryids{$cve} .= ",$data";
			}
		}
	}
}
close(INFILE);

#print STDERR "Reading /suse/meissner/Export/suse-sa...\n";
open(INFILE,"$cverepobase/data/suse-sa")||die "open $cverepobase/data/suse-sa:$!";
while (<INFILE>) {
	chomp;
	die "$_" unless (/^(.*);(http[s]?:\/\/.*);(.*)$/);

	my $id = $1;
	my $url = $2;
	my $date = $3;

	next if ($id  =~ /openSUSE-SU-22022/);	# one bad apple
	next if ($id  =~ /openSUSE-SU-42022-1/);	# one bad apple

	$url =~ s#support/kb/doc.php#support/kb/doc#;

	$url =~ s#http://lists.suse.com#https://lists.suse.com#;
	$url =~ s#http://lists.opensuse.org#https://lists.opensuse.org#;
	$CanDBReader::advisoryid2url{$id} = $url;
	$CanDBReader::advisoryid2date{$id} = $date;
}
close(INFILE);
#print STDERR "Reading /suse/meissner/Export/suse-sa... done.\n";

#print STDERR "Reading /suse/meissner/Export/package-notes...\n";
open(INFILE,"$cverepobase/data/package-notes")||die "open $cverepobase/data/package-notes:$!";
while (<INFILE>) {
	chomp;
	die "$_" unless (/^([^,]*),(.*)$/);

	$CanDBReader::packagenotes{$1} = $2;
}
close(INFILE);
#print STDERR "Reading /suse/meissner/Export/suse-sa... done.\n";

open(INFILE,"$cverepobase/data/su2patch")||die "open $cverepobase/data/su2patch:$!";
while (<INFILE>) {
	chomp;
	die "$_" unless (/^(.*);(.*)$/);

	my $id = $1;
	my $patches = $2;
	next if ($id  =~ /openSUSE-SU-22022/);	# one bad apple
	next if ($id  =~ /openSUSE-SU-42022-1/);	# one bad apple
	my @patches = sort split (/,/,$patches);
	my %map = ();
	if (defined($CanDBReader::susenotice2patches{$id})) {
		%map = %{$CanDBReader::susenotice2patches{$id}};
	}
	foreach my $xkey (@patches) {
		next if ($xkey =~ /^dbg/);
		$map{$xkey} = 1;

		$CanDBReader::patch2susenotice{$xkey} = $id;
	}
	# inject the SUSE-YEAR-ID patch too.
	if ($id =~ /^SUSE.*-(2019):(\d*)-\d*$/ || $id =~ /^SUSE.*-(202\d):(\d*)-\d*$/) {
		# use this hack to avoid a leading 0 .... the Announcer emits leading 0 
		# for the id, but the buildservice does not
		my $year = $1;
		my $yid = $2;
		if ($yid < 10000) {	# HACK: ids over 10000 are SLE11 ids currently
			my $sid = sprintf("SUSE-%d-%d",$year,$yid);
			$map{$sid} = 1;
			$CanDBReader::patch2susenotice{$sid} = $id;
		}
	}
	$CanDBReader::susenotice2patches{$id} = \%map;
}
close(INFILE);

print STDERR "Reading $cverepobase/data/bugzillas...\n" if (-t STDERR);
open(INFILE,"$cverepobase/data/bugzillas")||die "open:$!";
while (<INFILE>) {
	chomp;
	my $bug;
	my $day;
	my $change;

	undef $change;
	($bug,$day,$change) = split(/,/);
	next unless (defined($change));

	if ($change =~ /RESOLUTION:(.*)/) { $CanDBReader::bugzilla_resolution{$bug} = $1; }
	if ($change =~ /STATUS:(.*)/) { $CanDBReader::bugzilla_state{$bug} = $1; }
	if ($change =~ /PRIORITY:(.*)/) { $CanDBReader::bugzilla_priority{$bug} = $1; }
	if ($change =~ /SEVERITY:(.*)/) { $CanDBReader::bugzilla_severity{$bug} = $1; }
}
close(INFILE);
print STDERR "Reading $cverepobase/data/bugzillas...done\n" if (-t STDERR);

print STDERR "Reading $cverepobase/data/kernel/* ...\n" if (-t STDERR);
foreach my $file (<$cverepobase/data/kernel/*>) {
	my $sp = $file;

	$sp =~ s/^.*\///g;

	open(INFILE,"<$file")||die "open:$!";
	while (<INFILE>) {
		chomp;
		my $day;
		my $cve;

		($day,$cve) = split(/,/);

		$CanDBReader::kernelcvedates{$sp}->{$cve} = $day;
	}
	close(INFILE);
}
print STDERR "Reading $cverepobase/data/kernel/* ...done\n" if (-t STDERR);

1;
