File Coverage

blib/lib/File/VirusScan.pm
Criterion Covered Total %
statement 49 57 85.9
branch 9 12 75.0
condition 3 6 50.0
subroutine 10 11 90.9
pod 3 3 100.0
total 74 89 83.1


line stmt bran cond sub pod time code
1             package File::VirusScan;
2 2     2   131626 use strict;
  2         9  
  2         47  
3 2     2   9 use warnings;
  2         3  
  2         36  
4 2     2   7 use Carp;
  2         3  
  2         76  
5 2     2   31 use 5.008;
  2         5  
6              
7 2     2   676 use File::VirusScan::Result;
  2         2  
  2         43  
8 2     2   675 use File::VirusScan::ResultSet;
  2         4  
  2         757  
9              
10             our $VERSION = '0.104';
11              
12             # We don't use Module::Pluggable. Most users of this module will have
13             # one or two virus scanners, with the other half-dozen or so plugins
14             # going unused, so there's no sense in finding/loading all plugins.
15             sub new
16             {
17 3     3 1 2332 my ($class, $conf) = @_;
18              
19 3 100 66     11 if(!exists $conf->{engines} || !scalar keys %{ $conf->{engines} }) {
  2         10  
20 1         11 croak q{Must supply an 'engines' value to constructor};
21             }
22              
23 2         3 my %backends;
24              
25             # Load and initialise our backend engines
26 2         4 while (my ($moniker, $backend_conf) = each %{ $conf->{engines} }) {
  3         13  
27              
28 2         6 $moniker =~ s/[^-A-Za-z0-9_:]//;
29 2         3 my $backclass = $moniker;
30              
31 2 100       7 substr($backclass, 0, 1, 'File::VirusScan::Engine::') if substr($backclass, 0, 1) eq '-';
32              
33 2     1   98 eval qq{use $backclass;}; ## no critic(StringyEval)
  1     1   308  
  0         0  
  0         0  
  1         6  
  1         2  
  1         11  
34 2 100       54 if($@) { ## no critic(PunctuationVars)
35 1         19 croak "Unable to find class $backclass for backend '$moniker'";
36             }
37              
38 1         4 $backends{$moniker} = $backclass->new($backend_conf);
39             }
40              
41 1         3 my $self = { always_scan => $conf->{always_scan}, };
42              
43 1 50       3 if(exists $conf->{order}) {
44 0         0 $self->{_backends} = [ @backends{ @{ $conf->{order} } } ];
  0         0  
45             } else {
46 1         3 $self->{_backends} = [ values %backends ];
47             }
48              
49 1         5 return bless $self, $class;
50             }
51              
52             sub scan
53             {
54 2     2 1 801 my ($self, $path) = @_;
55              
56 2         14 my $result = File::VirusScan::ResultSet->new();
57              
58 2         12 for my $back (@{ $self->{_backends} }) {
  2         6  
59              
60 2         3 my $scan_result = eval { $back->scan($path) };
  2         4  
61              
62 2 50       4 if($@) {
63 0         0 $result->add(File::VirusScan::Result->error("Error calling ->scan(): $@"));
64             } else {
65 2         7 $result->add($scan_result);
66             }
67              
68 2 50 33     20 if(!$self->{always_scan}
69             && $result->has_virus())
70             {
71 0         0 last;
72             }
73             }
74              
75 2         19 return $result;
76             }
77              
78             sub get_backends
79             {
80 0     0 1 0 my ($self) = @_;
81 0         0 return $self->{_backends};
82             }
83              
84             1;
85             __END__