File Coverage

blib/lib/NIST/NVD/Store/DB_File.pm
Criterion Covered Total %
statement 25 27 92.5
branch n/a
condition n/a
subroutine 9 9 100.0
pod n/a
total 34 36 94.4


line stmt bran cond sub pod time code
1             package NIST::NVD::Store::DB_File;
2              
3 2     2   4310 use NIST::NVD::Store::Base;
  2         4  
  2         65  
4 2     2   15 use base qw{NIST::NVD::Store::Base};
  2         5  
  2         183  
5              
6 2     2   11 use warnings;
  2         23  
  2         50  
7 2     2   11 use strict;
  2         4  
  2         94  
8              
9             our $VERSION = '1.00.00';
10              
11 2     2   10 use Carp;
  2         3  
  2         128  
12              
13 2     2   1093 use Storable qw(nfreeze thaw);
  2         4233  
  2         193  
14 2     2   3022 use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error);
  2         106845  
  2         355  
15 2     2   3023 use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error);
  2         22815  
  2         268  
16              
17 2     2   911 use DB_File;
  0            
  0            
18              
19             =head2 new
20              
21             my $NVD_Storage_ORACLE = NIST::NVD::Store::DB_File->new(
22             store => 'DB_File',
23             database => '/path/to/nvd.db',
24             cwe => '/path/to/cwe.db',
25             'idx_cpe' => '/path/to/idx_cpe.db'
26             'idx_cwe' => '/path/to/idx_cwe.db'
27             mode => $mode, # perldoc DB_File
28             );
29              
30             =cut
31              
32             sub new {
33             my ( $class, %args ) = @_;
34             $class = ref $class || $class;
35              
36             my $args = {
37             filename => [qw{ database idx_cpe idx_cwe cwe }],
38             database => [qw{ database idx_cpe idx_cwe cwe }],
39             required => [qw{ database }],
40             };
41              
42             unless( exists $args{idx_cpe} ){
43             ($args{idx_cpe} = $args{database}) =~ s/(\.db)$/.idx_cpe$1/;
44             }
45              
46             unless( exists $args{idx_cwe} ){
47             ($args{idx_cwe} = $args{database}) =~ s/(\.db)$/.idx_cwe$1/;
48             }
49              
50             unless( exists $args{cwe} ){
51             ($args{cwe} = $args{database}) =~ s:/(nvd\.db)$:cwec_v2.2.db:;
52             }
53              
54             $args{mode} //= O_RDONLY;
55              
56             my $fail = 0;
57             foreach my $req_arg ( @{ $args->{required} } ) {
58             unless ( $args{$req_arg} ) {
59             carp "'$req_arg' is a required argument to __PACKAGE__::new\n";
60             $fail++;
61             }
62             }
63             return if $fail;
64              
65             my $self = { vuln_software => {} };
66             foreach my $arg ( keys %args ) {
67             if ( grep { $_ eq $arg } @{ $args->{filename} } ) {
68              
69             unless ( ( $args{mode} & O_CREAT ) == O_CREAT || -f $args{$arg} ) {
70             carp "$arg file '$args{$arg}' does not exist\n";
71             $fail++;
72             }
73             }
74             if ( grep { $_ eq $arg } @{ $args->{database} } ) {
75             my %tied_hash;
76             $self->{$arg} = \%tied_hash;
77             $self->{"$arg.db"} = tie %tied_hash, 'DB_File', $args{$arg},
78             $args{mode};
79              
80             unless ( $self->{"$arg.db"} ) {
81             carp "failed to open database '$args{$arg}': $!";
82             $fail++;
83             }
84             }
85             }
86             return if $fail;
87              
88             bless $self, $class;
89              
90             }
91              
92             =head2 get_cve_for_cpe
93              
94             =cut
95              
96             sub get_cve_for_cpe {
97             my ( $self, %args ) = @_;
98              
99             my $frozen;
100              
101             my $result = $self->{'idx_cpe.db'}->get( $args{cpe}, $frozen );
102              
103             my $cve_ids = [];
104              
105             unless ( $result == 0 ) {
106             return $cve_ids;
107             }
108              
109             $cve_ids = eval { thaw $frozen };
110             if (@$) {
111             carp "Storable::thaw had a major malfunction: $@";
112             return;
113             }
114              
115             return $cve_ids;
116             }
117              
118             =head2 get_cve
119              
120              
121             =cut
122              
123             sub get_cve {
124             my ( $self, %args ) = @_;
125              
126             my $compressed;
127              
128             my $result = $self->{'database.db'}->get( $args{cve_id}, $compressed );
129              
130             unless ( $result == 0 ) {
131             carp "failed to retrieve CVE '$args{cve_id}': $!\n";
132             return;
133             }
134              
135             my $frozen;
136              
137             my $status = bunzip2( \$compressed, \$frozen );
138             unless ($status) {
139             carp "bunzip2 failed: $Bunzip2Error\n";
140             return;
141             }
142              
143             my $entry = eval { thaw $frozen };
144             if (@$) {
145             carp "Storable::thaw had a major malfunction.";
146             return;
147             }
148              
149             return $entry;
150             }
151              
152             =head2 put_cve_idx_cpe
153              
154             $NVD_Storage_ORACLE->put_cve_idx_cpe( $cpe_urn, $value )
155              
156             =cut
157              
158             sub put_cve_idx_cpe {
159             my ( $self, $vuln_software ) = @_;
160              
161             foreach my $cpe_urn ( keys %$vuln_software ) {
162             my $frozen;
163              
164             $self->{'idx_cpe.db'}->get( $cpe_urn, $frozen );
165              
166             if ($frozen) {
167             my $thawed = thaw($frozen);
168             next unless ref $thawed eq 'ARRAY';
169              
170             my @vuln_list = ();
171              
172             @vuln_list = @{ $self->{vuln_software}->{$cpe_urn} }
173             if ref $self->{vuln_software}->{$cpe_urn} eq 'ARRAY';
174              
175             # Combine previous results with these results
176             $vuln_software->{$cpe_urn} = [ @vuln_list, @{$thawed} ];
177             }
178              
179             $frozen = nfreeze( $vuln_software->{$cpe_urn} );
180              
181             $self->{'idx_cpe.db'}->put( $cpe_urn, $frozen );
182             }
183             }
184              
185             =head2 put_nvd_entries
186              
187             $NVD_Storage_ORACLE->put_nvd_entries( $entries )
188              
189             =cut
190              
191             sub put_nvd_entries {
192             my ( $self, $entries ) = @_;
193              
194             while ( my ( $cve_id, $entry ) = ( each %$entries ) ) {
195              
196             my $frozen = nfreeze($entry);
197              
198             my $compressed;
199              
200             bzip2 \$frozen => \$compressed
201             or die "bzip2 failed: $Bzip2Error\n";
202              
203             $self->{'database.db'}->put( $cve_id, $compressed );
204             }
205             }
206              
207             sub _get_default_args {
208             return ( mode => O_CREAT | O_RDWR );
209              
210             }
211              
212             1;