#!/usr/bin/perl -w
use warnings;
use strict;
use Data::Dumper;
use JSON::XS;
use Storable qw(nfreeze thaw);
use IO::Compress::Gzip qw(gzip $GzipError);
use IO::Uncompress::Gunzip qw(gunzip $GunzipError);

use NIST::NVD::Update;

# https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-recent.json.gz
my $filename = $ARGV[0] || 'nvdcve-1.1-recent.json.gz';

my $store    = $ARGV[1] || 'DB_File';

my $db_file = 'nvdcve-1.1.db';

my $NVD_Updater = NIST::NVD::Update->new(
    store    => $store,
    database => $db_file,
);

my %vuln_software;

my $coder = JSON::XS->new->ascii->pretty->allow_nonref;

my $decompressed = '';
gunzip $filename => \$decompressed or die "gunzip failed: $GunzipError\n";

my $cve_recent = $coder->decode ($decompressed);

print("CVE_data_numberOfCVEs: $cve_recent->{CVE_data_numberOfCVEs}",$/);
if( scalar @{$cve_recent->{CVE_Items}} == $cve_recent->{CVE_data_numberOfCVEs} ){
  print("received the advertised number of CVE items$/");
}else{
  print('$cve_recent->{CVE_data_numberOfCVEs} != scalar keys %{$cve_recent->{CVE_Items}}',$/);
}

my $NVD_Entry_HASH = {};
foreach my $item (@{$cve_recent->{CVE_Items}}){
  my $cve_id = $item->{cve}->{CVE_data_meta}->{ID};
  $NVD_Entry_HASH->{$cve_id} = $item;

  if( exists( $item->{configurations}->{nodes} ) ){
    foreach my $node ( @{$item->{configurations}->{nodes}} ){
      if( exists $node->{cpe_match} ){
	foreach my $cpe_match ( @{$node->{cpe_match}} ){
	  my $cpe23Uri = $cpe_match->{cpe23Uri};
	  push( @{ $vuln_software{$cpe23Uri} }, $cve_id )
	    if $cpe_match->{vulnerable};
	}
      }
    }
  }
}

print "Writing CPE URNs to disk...";

$NVD_Updater->put_cpe([ keys %vuln_software ]);

print "Done.\n";

print "Writing NVD entries to disk...";

$NVD_Updater->put_nvd_entries($NVD_Entry_HASH);

print " Done.\n";

print "Writing CPE index to disk...";
print( Data::Dumper::Dumper( \%vuln_software ) );


$NVD_Updater->put_cve_idx_cpe( \%vuln_software );

print "Done.\n";

