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              
3 4     4   66926 use strict;
  4         21  
  4         115  
4 4     4   19 use warnings;
  4         7  
  4         158  
5              
6             our $VERSION = '0.0946';
7              
8 4     4   1591 use Archive::Any::Plugin;
  4         10  
  4         249  
9 4     4   1773 use File::Spec::Functions qw( rel2abs splitdir );
  4         3171  
  4         247  
10 4     4   2684 use File::MMagic;
  4         65195  
  4         153  
11 4     4   1905 use MIME::Types qw(by_suffix);
  4         22664  
  4         2375  
12              
13             sub new {
14 13     13 1 4577 my ( $class, $file, $type ) = @_;
15              
16 13         73 $file = rel2abs($file);
17 13 50       788 return unless -f $file;
18              
19 13         81 my %available;
20              
21 13         128 my @plugins = Archive::Any::Plugin->findsubmod;
22 13         23217 foreach my $plugin (@plugins) {
23 26         1776 eval "require $plugin";
24 26 50       144 next if $@;
25              
26 26         162 my @types = $plugin->can_handle();
27 26         66 foreach my $type (@types) {
28 91 50       182 next if exists( $available{$type} );
29 91         255 $available{$type} = $plugin;
30             }
31             }
32              
33 13         28 my $mime_type;
34              
35 13 100       50 if ($type) {
36              
37             # The user forced the type.
38 6         44 ($mime_type) = by_suffix($type);
39 6 100       99525 unless ($mime_type) {
40 1         15 warn "No mime type found for type '$type'";
41 1         77 return;
42             }
43             }
44             else {
45             # Autodetect the type.
46 7         79 $mime_type = File::MMagic->new()->checktype_filename($file);
47             }
48              
49 12         136400 my $handler = $available{$mime_type};
50 12 100       46 if ( !$handler ) {
51 2         101 warn "No handler available for type '$mime_type'";
52 2         91 return;
53             }
54              
55 10         133 return bless {
56             file => $file,
57             handler => $handler,
58             type => $mime_type,
59             }, $class;
60             }
61              
62             sub extract {
63 4     4 1 8 my $self = shift;
64 4         10 my $dir = shift;
65              
66             return defined($dir)
67             ? $self->{handler}->_extract( $self->{file}, $dir )
68 4 50       61 : $self->{handler}->_extract( $self->{file} );
69             }
70              
71             sub files {
72 42     42 1 5564 my $self = shift;
73 42         299 return $self->{handler}->files( $self->{file} );
74             }
75              
76             sub is_impolite {
77 16     16 1 39 my $self = shift;
78              
79 16         45 my @files = $self->files;
80 16         2529 my $first_file = $files[0];
81 16         71 my ($first_dir) = splitdir($first_file);
82              
83 16 100       433 return grep( !/^\Q$first_dir\E/, @files ) ? 1 : 0;
84             }
85              
86             sub is_naughty {
87 14     14 1 72 my ($self) = shift;
88 14 100       34 return ( grep { m{^(?:/|(?:\./)*\.\./)} } $self->files ) ? 1 : 0;
  104         2572  
89             }
90              
91             sub mime_type {
92 0     0 1 0 my $self = shift;
93 0         0 return $self->{type};
94             }
95              
96             #
97             # This is not really here. You are not seeing this.
98             #
99             sub type {
100 8     8 1 6433 my $self = shift;
101 8         61 return $self->{handler}->type();
102             }
103              
104             # End of what you are not seeing.
105              
106             1;
107              
108             =pod
109              
110             =encoding UTF-8
111              
112             =head1 NAME
113              
114             Archive::Any - Single interface to deal with file archives.
115              
116             =head1 VERSION
117              
118             version 0.0946
119              
120             =head1 SYNOPSIS
121              
122             use Archive::Any;
123              
124             my $archive = Archive::Any->new( 'archive_file.zip' );
125              
126             my @files = $archive->files;
127              
128             $archive->extract;
129              
130             my $type = $archive->type;
131              
132             $archive->is_impolite;
133             $archive->is_naughty;
134              
135             =head1 DESCRIPTION
136              
137             This module is a single interface for manipulating different archive formats.
138             Tarballs, zip files, etc.
139              
140             =over 4
141              
142             =item B
143              
144             my $archive = Archive::Any->new( $archive_file );
145             my $archive_with_type = Archive::Any->new( $archive_file, $type );
146              
147             $type is optional. It lets you force the file type in case Archive::Any can't
148             figure it out.
149              
150             =item B
151              
152             $archive->extract;
153             $archive->extract( $directory );
154              
155             Extracts the files in the archive to the given $directory. If no $directory is
156             given, it will go into the current working directory.
157              
158             =item B
159              
160             my @file = $archive->files;
161              
162             A list of files in the archive.
163              
164             =item B
165              
166             my $mime_type = $archive->mime_type();
167              
168             Returns the mime type of the archive.
169              
170             =item B
171              
172             my $is_impolite = $archive->is_impolite;
173              
174             Checks to see if this archive is going to unpack into the current directory
175             rather than create its own.
176              
177             =item B
178              
179             my $is_naughty = $archive->is_naughty;
180              
181             Checks to see if this archive is going to unpack B the current
182             directory.
183              
184             =back
185              
186             =head1 DEPRECATED
187              
188             =over 4
189              
190             =item B
191              
192             my $type = $archive->type;
193              
194             Returns the type of archive. This method is provided for backwards
195             compatibility in the Tar and Zip plugins and will be going away B in
196             favor of C.
197              
198             =back
199              
200             =head1 PLUGINS
201              
202             For detailed information on writing plugins to work with Archive::Any, please
203             see the pod documentation for L.
204              
205             =head1 SEE ALSO
206              
207             Archive::Any::Plugin
208              
209             =head1 SUPPORT
210              
211             You can find documentation for this module with the perldoc command.
212              
213             perldoc Archive::Any
214              
215             You can also look for information at:
216              
217             =over 4
218              
219             =item * MetaCPAN
220              
221             L
222              
223             =item * Issue tracker
224              
225             L
226              
227             =back
228              
229             =head1 AUTHORS
230              
231             =over 4
232              
233             =item *
234              
235             Clint Moore
236              
237             =item *
238              
239             Michael G Schwern (author emeritus)
240              
241             =item *
242              
243             Olaf Alders (current maintainer)
244              
245             =back
246              
247             =head1 COPYRIGHT AND LICENSE
248              
249             This software is copyright (c) 2016 by Michael G Schwern, Clint Moore, Olaf Alders.
250              
251             This is free software; you can redistribute it and/or modify it under
252             the same terms as the Perl 5 programming language system itself.
253              
254             =cut
255              
256             __END__