File Coverage

blib/lib/CPAN/Access/AdHoc/Archive/Zip.pm
Criterion Covered Total %
statement 81 91 89.0
branch 19 40 47.5
condition 5 15 33.3
subroutine 16 17 94.1
pod 8 8 100.0
total 129 171 75.4


line stmt bran cond sub pod time code
1             package CPAN::Access::AdHoc::Archive::Zip;
2              
3 6     6   10519 use 5.008;
  6         22  
  6         240  
4              
5 6     6   33 use strict;
  6         11  
  6         188  
6 6     6   29 use warnings;
  6         11  
  6         198  
7              
8 6     6   33 use base qw{ CPAN::Access::AdHoc::Archive };
  6         13  
  6         688  
9              
10 6     6   6511 use Archive::Zip;
  6         521543  
  6         312  
11 6     6   65 use CPAN::Access::AdHoc::Util qw{ :carp __guess_media_type };
  6         17  
  6         2219  
12 6     6   68 use File::Spec::Unix ();
  6         15  
  6         111  
13 6     6   34 use IO::File ();
  6         13  
  6         8667  
14              
15             our $VERSION = '0.000_18';
16              
17             {
18              
19             my %decode;
20              
21             sub new {
22 4     4 1 564 my ( $class, %arg ) = @_;
23              
24 4   33     37 my $self = bless {}, ref $class || $class;
25              
26 4         35 my $archive = Archive::Zip->new();
27              
28 4         205 $self->archive( $archive );
29              
30 4 50       22 if ( defined( my $content = delete $arg{content} ) ) {
31              
32 4 50       29 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       40 $content = IO::File->new( $content, '<' )
38             or __wail( "Unable to open string reference: $!" );
39             }
40              
41 4         3208 my $status = $archive->read( $content );
42 4 50       13169 $status == Archive::Zip::AZ_OK()
43             or __wail( "Zip read error" );
44              
45 4 50 33     27 ref $content
46             or defined $arg{path}
47             or $arg{path} = $content;
48              
49             }
50              
51 4         55 $self->mtime( delete $arg{mtime} );
52 4         39 $self->path( delete $arg{path} );
53              
54 4         60 return $self;
55             }
56             }
57              
58             sub base_directory {
59 26     26 1 69 my ( $self ) = @_;
60              
61 78 50       861 my @rslt = sort { length $a <=> length $b || $a cmp $b }
  78         1069  
62 234         3880 map { $_->fileName() }
63 26         98 grep { $_->isDirectory() }
64             $self->archive()->members();
65              
66 26 50       846 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         50 my $base = $rslt[0];
73 26 50 33     252 defined $base
      33        
74             and '' ne $base
75             and $base !~ m{ / \z }smx
76             and $base .= '/';
77              
78 26         305 return $base;
79             }
80              
81             sub extract {
82 1     1 1 2053 my ( $self ) = @_;
83              
84 1         13 $self->archive()->extractTree();
85              
86 1         6 return $self;
87             }
88              
89             sub get_item_content {
90 16     16 1 8896 my ( $self, $file ) = @_;
91 16         39 $file = $self->base_directory() . $file;
92 16 50       58 my $member = $self->archive()->memberNamed( $file )
93             or return;
94 16         893 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   15 my ( $class, $rslt ) = @_;
111              
112 5 100       23 $handled{ $rslt->header( 'Content-Type' ) }
113             or return;
114              
115 4         162 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 7 my ( $self, $name ) = @_;
127 2         13 $name = $self->base_directory() . $name;
128 2         60 my $re = qr{ \A \Q$name\E \z }smx;
129 2         12 return scalar $self->archive()->membersMatching( $re );
130             }
131              
132             sub list_contents {
133 4     4 1 74 my ( $self ) = @_;
134              
135 4         16 my $base = $self->base_directory();
136 4         456 $base = qr{ \A \Q$base\E }smx;
137              
138 4         11 my @rslt;
139 4         217 foreach my $file ( $self->archive()->members() ) {
140 36 100       145 $file->isDirectory()
141             and next;
142 24         281 my $name = $file->fileName();
143 24 50       263 $name =~ s/ $base //smx
144             or next;
145 24         65 push @rslt, $name;
146             }
147              
148 4         39 return @rslt;
149             }
150              
151             sub write : method { ## no critic (ProhibitBuiltInHomonyms)
152 1     1 1 9 my ( $self, $fn ) = @_;
153 1 50       6 if ( ! defined $fn ) {
154 1         7 $fn = ( File::Spec->splitpath( $self->path() ) )[2];
155             }
156 1         13 my $resp = HTTP::Response->new();
157 1         64 __guess_media_type( $resp, $fn );
158 1         4 my $encoding = $resp->header( 'Content-Encoding' );
159 1 50       39 defined $encoding
160             or $encoding = '';
161 1 50 33     11 if ( defined $encoding && '' ne $encoding ) {
162 0         0 __wail( "Encoding $encoding not supported" );
163             }
164 1         7 my $status = $self->archive()->writeToFileNamed( $fn );
165 1 50       7002 $status == Archive::Zip::AZ_OK()
166             or __wail( 'Zip write error' );
167 1         11 return $self;
168             }
169              
170             1;
171              
172             __END__