#!/usr/bin/perl # Copyright (c) 2023 Solar Designer # Redistribution and use in source and binary forms, with or without # modification, are permitted. (This is a heavily cut-down "BSD license".) use List::Util qw(first); use Time::Local qw(timegm); sub timestr2unix { my @DoW = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); my @MoY = ('Jan','Feb','Mar','Apr','May','Jun', 'Jul','Aug','Sep','Oct','Nov','Dec'); my $in = shift; my ($wday, $mon, $mday, $hour, $min, $sec, $year) = $in =~ /^(\w{3}) (\w{3}) (\d{2}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/; if (defined($year)) { $wday = first { $DoW[$_] eq $wday } 0..$#DoW; $mon = first { $MoY[$_] eq $mon } 0..$#MoY; if (defined($wday) && defined($mon)) { $out = timegm($sec, $min, $hour, $mday, $mon, $year - 1900); ($sec2, $min2, $hour2, $mday2, $mon2, $year2, $wday2, $yday, $isdst) = gmtime($out); die "Wrong day of week in $in\n" if $wday ne $wday2; return $out; } } die "Parse error of date/time $in\n"; } $i = $line = 0; while (<>) { $line++; chomp; if (/^$/ || (defined($file) && $file ne $ARGV)) { $i++ if defined($a[$i]); next if /^$/; } $file = $ARGV; my ($key, $value) = /^([^:]*): (.*)$/; die "Parse error at line $line in $file: $_\n" unless defined($key) && defined($value); die "Duplicate key at line $line in $file: $_\n" if defined($a[$i]{$key}); $a[$i]{$key} = $value; } print "^ Project ^ Subjects/titles/links ^ Time at distros (UTC) \\\\ ... oss-security (UTC) \\\\ Elsewhere (UTC) ^ Embargo days ^ Planned CRD(s) \\\\ (exact wording) ^ CVE(s) ^\n"; $nemb = $npub = $eoss_total = 0; for ($i = 0; $i <= $#a; $i++) { next unless defined($a[$i]{"toss"}); $eoss = (timestr2unix($a[$i]{"toss"}) - timestr2unix($a[$i]{"trep"})) / 86400; $lpub = ""; if (defined($a[$i]{"lpub"})) { $lpub = $a[$i]{"lpub"}; if (defined($a[$i]{"spub"})) { $lpub = " \\\\ [[$lpub|$spub]]"; } else { $lpub = " \\\\ [[$lpub]]"; } } $tpub = $epub = ""; if (defined($a[$i]{"tpub"})) { $tpub = $a[$i]{"tpub"}; $epub_vs_rep = (timestr2unix($tpub) - timestr2unix($a[$i]{"trep"})) / 86400; $epub = sprintf(" \\\\ %.2f", $epub_vs_rep); $tpub = " \\\\ $tpub"; } $cves = $a[$i]{"cves"}; $cves =~ s/, / \\\\ /g; printf("| %s | %s \\\\ [[%s|%s]]%s | %s \\\\ %s%s | %.2f%s | %s | %s |\n", $a[$i]{"proj"}, $a[$i]{"subj"}, $a[$i]{"loss"}, $a[$i]{"soss"}, $lpub, $a[$i]{"trep"}, $a[$i]{"toss"}, $tpub, $eoss, $epub, $a[$i]{"tcrd"}, $cves); $npub++; next unless $eoss > 0; $eoss_all[$nemb++] = $eoss; $eoss_total += $eoss; } print "\nTotal $i, public $npub, were embargoed $nemb\n\n"; exit unless $nemb; @eoss_all = sort {$a <=> $b} @eoss_all; if ($nemb & 1) { $eoss_med = $eoss_all[($nemb - 1) / 2]; } else { $eoss_med = ($eoss_all[$nemb / 2 - 1] + $eoss_all[$nemb / 2]) / 2; } print "^ All reports ^ Embargoed ^ Average ^ Median ^ Min ^ Max embargo days ^\n"; printf("| %u | %u | %.2f | %.2f | %.2f | %.2f |\n", $npub, $nemb, $eoss_total / $nemb, $eoss_med, $eoss_all[0], $eoss_all[$#eoss_all]);