File Coverage

blib/lib/CPAN/Access/AdHoc/Archive/Zip.pm
Criterion Covered Total %
statement 80 90 88.8
branch 20 42 47.6
condition 5 15 33.3
subroutine 16 17 94.1
pod 8 8 100.0
total 129 172 75.0


line stmt bran cond sub pod time code
1             package CPAN::Access::AdHoc::Archive::Zip;
2              
3 6     6   7538 use 5.008;
  6         19  
  6         194  
4              
5 6     6   24 use strict;
  6         162  
  6         166  
6 6     6   24 use warnings;
  6         8  
  6         160  
7              
8 6     6   28 use base qw{ CPAN::Access::AdHoc::Archive };
  6         6  
  6         633  
9              
10 6     6   3630 use Archive::Zip;
  6         322626  
  6         261  
11 6     6   49 use CPAN::Access::AdHoc::Util qw{ :carp __guess_media_type };
  6         10  
  6         665  
12 6     6   54 use File::Spec::Unix ();
  6         10  
  6         77  
13 6     6   26 use IO::File ();
  6         7  
  6         5025  
14              
15             our $VERSION = '0.000_194';
16              
17             {
18              
19             my %decode;
20              
21             sub new {
22 4     4 1 407 my ( $class, %arg ) = @_;
23              
24 4   33     27 my $self = bless {}, ref $class || $class;
25              
26 4         28 my $archive = Archive::Zip->new();
27              
28 4         151 $self->archive( $archive );
29              
30 4 50       16 if ( defined( my $content = delete $arg{content} ) ) {
31              
32 4 50       33 if ( my $encoding = delete $arg{encoding} ) {
    50          
33 0 0       0 $decode{$encoding}
34             or __wail( "Unsupported encoding '$encoding'" );
35 0         0 $content = $decode{$encoding}->( $content );
36             } elsif ( ref $content ) {
37 4 50       27 $content = IO::File->new( $content, '<' )
38             or __wail( "Unable to open string reference: $!" );
39             }
40              
41 4         2165 my $status = $archive->read( $content );
42 4 50       9596 $status == Archive::Zip::AZ_OK()
43             or __wail( "Zip read error" );
44              
45 4 50 33     22 ref $content
46             or defined $arg{path}
47             or $arg{path} = $content;
48              
49             }
50              
51 4         31 $self->mtime( delete $arg{mtime} );
52 4         24 $self->path( delete $arg{path} );
53              
54 4         35 return $self;
55             }
56             }
57              
58             sub base_directory {
59 26     26 1 43 my ( $self ) = @_;
60              
61 78 50       341 my @rslt = sort { length $a <=> length $b || $a cmp $b }
  78         578  
62 234         1332 map { $_->fileName() }
63 26         94 grep { $_->isDirectory() }
64             $self->archive()->members();
65              
66 26 50       59 if ( ! @rslt ) {
67 0 0       0 @rslt = sort { length $a <=> length $b || $a cmp $b }
  0         0  
68 0         0 map { ( File::Spec::Unix->splitpath( $_->fileName() ) )[1] }
69             $self->archive->members();
70             }
71              
72 26         26 my $base = $rslt[0];
73 26 50 33     217 defined $base
      33        
74             and '' ne $base
75             and $base !~ m{ / \z }smx
76             and $base .= '/';
77              
78 26         61 return $base;
79             }
80              
81             sub extract {
82 1     1 1 1140 my ( $self ) = @_;
83              
84 1         11 $self->archive()->extractTree();
85              
86 1         4 return $self;
87             }
88              
89             sub get_item_content {
90 16     16 1 6285 my ( $self, $file ) = @_;
91 16         31 $file = $self->base_directory() . $file;
92 16 50       43 my $member = $self->archive()->memberNamed( $file )
93             or return;
94 16         598 return scalar $member->contents();
95             }
96              
97             sub get_item_mtime {
98 0     0 1 0 my ( $self, $file ) = @_;
99 0         0 $file = $self->base_directory() . $file;
100 0 0       0 my $member = $self->archive()->memberNamed( $file )
101             or return;
102 0         0 return scalar $member->lastModTime();
103             }
104              
105             {
106              
107             my %handled = map { $_ => 1 } qw{ application/zip };
108              
109             sub __handle_http_response {
110 5     5   10 my ( $class, $rslt ) = @_;
111              
112 5 100       18 $handled{ $rslt->header( 'Content-Type' ) }
113             or return;
114              
115 4         111 return $class->new(
116             content => \( scalar $rslt->content() ),
117             encoding => scalar $rslt->header( 'Content-Encoding' ),
118             mtime => HTTP::Date::str2time(
119             scalar $rslt->header( 'Last-Modified' ) ),
120             path => scalar $rslt->header( 'Content-Location' ),
121             );
122             }
123             }
124              
125             sub item_present {
126 2     2 1 5 my ( $self, $name ) = @_;
127 2         5 $name = $self->base_directory() . $name;
128 2 50       9 return $self->archive()->memberNamed( $name ) ? 1 : 0;
129             }
130              
131             sub list_contents {
132 4     4 1 26 my ( $self ) = @_;
133              
134 4         9 my $base = $self->base_directory();
135 4         75 $base = qr{ \A \Q$base\E }smx;
136              
137 4         6 my @rslt;
138 4         14 foreach my $file ( $self->archive()->members() ) {
139 36 100       92 $file->isDirectory()
140             and next;
141 24         174 my $name = $file->fileName();
142 24 50       165 $name =~ s/ $base //smx
143             or next;
144 24         43 push @rslt, $name;
145             }
146              
147 4         30 return @rslt;
148             }
149              
150             sub write : method { ## no critic (ProhibitBuiltInHomonyms)
151 1     1 1 6 my ( $self, $fn ) = @_;
152 1 50       4 if ( ! defined $fn ) {
153 1         4 $fn = ( File::Spec->splitpath( $self->path() ) )[2];
154             }
155 1         8 my $resp = HTTP::Response->new();
156 1         39 __guess_media_type( $resp, $fn );
157 1         3 my $encoding = $resp->header( 'Content-Encoding' );
158 1 50       25 defined $encoding
159             or $encoding = '';
160 1 50 33     7 if ( defined $encoding && '' ne $encoding ) {
161 0         0 __wail( "Encoding $encoding not supported" );
162             }
163 1         4 my $status = $self->archive()->writeToFileNamed( $fn );
164 1 50       4884 $status == Archive::Zip::AZ_OK()
165             or __wail( 'Zip write error' );
166 1         7 return $self;
167             }
168              
169             1;
170              
171             __END__