File Coverage

blib/lib/Archive/Any.pm
Criterion Covered Total %
statement 57 59 96.6
branch 14 18 77.7
condition n/a
subroutine 12 13 92.3
pod 7 7 100.0
total 90 97 92.7


line stmt bran cond sub pod time code
1             package Archive::Any;
2             $Archive::Any::VERSION = '0.0945';
3 4     4   14111 use strict;
  4         6  
  4         92  
4 4     4   9 use warnings;
  4         4  
  4         85  
5              
6 4     4   1209 use Archive::Any::Plugin;
  4         6  
  4         88  
7 4     4   1535 use File::Spec::Functions qw( rel2abs splitdir );
  4         2065  
  4         213  
8 4     4   2347 use File::MMagic;
  4         47509  
  4         112  
9 4     4   1496 use MIME::Types qw(by_suffix);
  4         18193  
  4         1434  
10              
11             sub new {
12 13     13 1 7434 my ( $class, $file, $type ) = @_;
13              
14 13         46 $file = rel2abs( $file );
15 13 50       509 return unless -f $file;
16              
17 13         21 my %available;
18              
19 13         83 my @plugins = Archive::Any::Plugin->findsubmod;
20 13         16718 foreach my $plugin ( @plugins ) {
21 26         1211 eval "require $plugin";
22 26 50       92 next if $@;
23              
24 26         107 my @types = $plugin->can_handle();
25 26         50 foreach my $type ( @types ) {
26 91 50       136 next if exists( $available{$type} );
27 91         157 $available{$type} = $plugin;
28             }
29             }
30              
31 13         14 my $mime_type;
32              
33 13 100       27 if ( $type ) {
34              
35             # The user forced the type.
36 6         25 ( $mime_type ) = by_suffix( $type );
37 6 100       52403 unless ( $mime_type ) {
38 1         14 warn "No mime type found for type '$type'";
39 1         52 return;
40             }
41             }
42             else {
43             # Autodetect the type.
44 7         49 $mime_type = File::MMagic->new()->checktype_filename( $file );
45             }
46              
47 12         66071 my $handler = $available{$mime_type};
48 12 100       28 if ( !$handler ) {
49 2         101 warn "No handler available for type '$mime_type'";
50 2         56 return;
51             }
52              
53 10         83 return bless {
54             file => $file,
55             handler => $handler,
56             type => $mime_type,
57             }, $class;
58             }
59              
60             sub extract {
61 4     4 1 5 my $self = shift;
62 4         4 my $dir = shift;
63              
64             return defined( $dir )
65             ? $self->{handler}->_extract( $self->{file}, $dir )
66 4 50       40 : $self->{handler}->_extract( $self->{file} );
67             }
68              
69             sub files {
70 42     42 1 4898 my $self = shift;
71 42         211 return $self->{handler}->files( $self->{file} );
72             }
73              
74             sub is_impolite {
75 16     16 1 19 my $self = shift;
76              
77 16         30 my @files = $self->files;
78 16         1235 my $first_file = $files[0];
79 16         40 my ( $first_dir ) = splitdir( $first_file );
80              
81 16 100       298 return grep( !/^\Q$first_dir\E/, @files ) ? 1 : 0;
82             }
83              
84             sub is_naughty {
85 14     14 1 50 my ( $self ) = shift;
86 14 100       25 return ( grep {m{^(?:/|(?:\./)*\.\./)}} $self->files ) ? 1 : 0;
  104         1224  
87             }
88              
89             sub mime_type {
90 0     0 1 0 my $self = shift;
91 0         0 return $self->{type};
92             }
93              
94             #
95             # This is not really here. You are not seeing this.
96             #
97             sub type {
98 8     8 1 4510 my $self = shift;
99 8         57 return $self->{handler}->type();
100             }
101              
102             # End of what you are not seeing.
103              
104             1;
105              
106             # ABSTRACT: Single interface to deal with file archives.
107              
108             __END__