File Coverage

blib/lib/Archive/Zip/MemberRead.pm
Criterion Covered Total %
statement 72 78 92.3
branch 15 22 68.2
condition 11 21 52.4
subroutine 15 15 100.0
pod 7 9 77.8
total 120 145 82.8


line stmt bran cond sub pod time code
1             package Archive::Zip::MemberRead;
2              
3             # Copyright (c) 2002 Sreeji K. Das. All rights reserved. This program is free
4             # software; you can redistribute it and/or modify it under the same terms
5             # as Perl itself.
6              
7             =head1 NAME
8            
9             Archive::Zip::MemberRead - A wrapper that lets you read Zip archive members as if they were files.
10            
11             =cut
12              
13             =head1 SYNOPSIS
14            
15             use Archive::Zip;
16             use Archive::Zip::MemberRead;
17             $zip = new Archive::Zip("file.zip");
18             $fh = new Archive::Zip::MemberRead($zip, "subdir/abc.txt");
19             while (defined($line = $fh->getline()))
20             {
21             print $fh->input_line_number . "#: $line\n";
22             }
23            
24             $read = $fh->read($buffer, 32*1024);
25             print "Read $read bytes as :$buffer:\n";
26            
27             =head1 DESCRIPTION
28            
29             The Archive::Zip::MemberRead module lets you read Zip archive member data
30             just like you read data from files.
31            
32             =head1 METHODS
33            
34             =over 4
35            
36             =cut
37              
38 2     2   27 use strict;
  2         18  
  2         82  
39 2     2   36 use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
  2         19  
  2         37  
40              
41 2     2   34 use vars qw{$VERSION};
  2         20  
  2         30  
42              
43             BEGIN {
44 2     2   39     $VERSION = '1.18';
45 2         164     $VERSION = eval $VERSION;
46             }
47              
48             =item Archive::Zip::Member::readFileHandle()
49            
50             You can get a C<Archive::Zip::MemberRead> from an archive member by
51             calling C<readFileHandle()>:
52            
53             my $member = $zip->memberNamed('abc/def.c');
54             my $fh = $member->readFileHandle();
55             while (defined($line = $fh->getline()))
56             {
57             # ...
58             }
59             $fh->close();
60            
61             =cut
62              
63             sub Archive::Zip::Member::readFileHandle {
64 1     1   17     return Archive::Zip::MemberRead->new( shift() );
65             }
66              
67             =item Archive::Zip::MemberRead->new($zip, $fileName)
68            
69             =item Archive::Zip::MemberRead->new($zip, $member)
70            
71             =item Archive::Zip::MemberRead->new($member)
72            
73             Construct a new Archive::Zip::MemberRead on the specified member.
74            
75             my $fh = Archive::Zip::MemberRead->new($zip, 'fred.c')
76            
77             =cut
78              
79             sub new {
80 4     4 1 42     my ( $class, $zip, $file ) = @_;
81 4         34     my ( $self, $member );
82              
83 4 100 66     71     if ( $zip && $file ) # zip and filename, or zip and member
    50 33        
      33        
84                 {
85 2 100       31         $member = ref($file) ? $file : $zip->memberNamed($file);
86                 }
87                 elsif ( $zip && !$file && ref($zip) ) # just member
88                 {
89 2         19         $member = $zip;
90                 }
91                 else {
92 0         0         die(
93             'Archive::Zip::MemberRead::new needs a zip and filename, zip and member, or member'
94                     );
95                 }
96              
97 4         104     $self = {};
98 4         77     bless( $self, $class );
99 4         46     $self->set_member($member);
100 4         49     return $self;
101             }
102              
103             sub set_member {
104 4     4 0 37     my ( $self, $member ) = @_;
105              
106 4         41     $self->{member} = $member;
107 4         42     $self->set_compression(COMPRESSION_STORED);
108 4         42     $self->rewind();
109             }
110              
111             sub set_compression {
112 4     4 0 36     my ( $self, $compression ) = @_;
113 4 50       183     $self->{member}->desiredCompressionMethod($compression) if $self->{member};
114             }
115              
116             =item rewind()
117            
118             Rewinds an C<Archive::Zip::MemberRead> so that you can read from it again
119             starting at the beginning.
120            
121             =cut
122              
123             sub rewind {
124 5     5 1 45     my $self = shift;
125              
126 5         51     $self->_reset_vars();
127 5 50       78     $self->{member}->rewindData() if $self->{member};
128             }
129              
130             sub _reset_vars {
131 6     6   53     my $self = shift;
132 6         369     $self->{lines} = [];
133 6         61     $self->{partial} = 0;
134 6         62     $self->{line_no} = 0;
135             }
136              
137             =item input_line_number()
138            
139             Returns the current line number, but only if you're using C<getline()>.
140             Using C<read()> will not update the line number.
141            
142             =cut
143              
144             sub input_line_number {
145 5     5 1 45     my $self = shift;
146 5         69     return $self->{line_no};
147             }
148              
149             =item close()
150            
151             Closes the given file handle.
152            
153             =cut
154              
155             sub close {
156 1     1 1 10     my $self = shift;
157              
158 1         12     $self->_reset_vars();
159 1         16     $self->{member}->endRead();
160             }
161              
162             =item buffer_size([ $size ])
163            
164             Gets or sets the buffer size used for reads.
165             Default is the chunk size used by Archive::Zip.
166            
167             =cut
168              
169             sub buffer_size {
170 6     6 1 52     my ( $self, $size ) = @_;
171              
172 6 50       57     if ( !$size ) {
173 6   33     81         return $self->{chunkSize} || Archive::Zip::chunkSize();
174                 }
175                 else {
176 0         0         $self->{chunkSize} = $size;
177                 }
178             }
179              
180             =item getline()
181            
182             Returns the next line from the currently open member.
183             Makes sense only for text files.
184             A read error is considered fatal enough to die.
185             Returns undef on eof. All subsequent calls would return undef,
186             unless a rewind() is called.
187             Note: The line returned has the newline removed.
188            
189             =cut
190              
191             # $self->{partial} flags whether the last line in the buffer is partial or not.
192             # A line is treated as partial if it does not ends with \n
193             sub getline {
194 6     6 1 52     my $self = shift;
195 6         50     my ( $temp, $status, $size, $buffer, @lines );
196              
197 6         50     $status = AZ_OK;
198 6         61     $size = $self->buffer_size();
199 6         61     $temp = \$status;
200 6   100     123     while ( $$temp !~ /\n/ && $status != AZ_STREAM_END ) {
201 6         85         ( $temp, $status ) = $self->{member}->readChunk($size);
202 6 50 66     80         if ( $status != AZ_OK && $status != AZ_STREAM_END ) {
203 0         0             die "ERROR: Error reading chunk from archive - $status\n";
204                     }
205              
206 6         85         $buffer .= $$temp;
207                 }
208              
209 6         61     @lines = split( /\n/, $buffer );
210 6         54     $self->{line_no}++;
211 6 100       69     if ( $#lines == -1 ) {
212 5         63         return ( $#{ $self->{lines} } == -1 )
  4         52  
213                       ? undef
214 5 100       43           : shift( @{ $self->{lines} } );
215                 }
216              
217 1 50       12     $self->{lines}->[ $#{ $self->{lines} } ] .= shift(@lines)
  0         0  
218                   if $self->{partial};
219              
220 1         69     splice( @{ $self->{lines} }, @{ $self->{lines} }, 0, @lines );
  1         12  
  1         14  
221 1         12     $self->{partial} = !( $buffer =~ /\n$/ );
222 1         9     return shift( @{ $self->{lines} } );
  1         18  
223             }
224              
225             =item read($buffer, $num_bytes_to_read)
226            
227             Simulates a normal C<read()> system call.
228             Returns the no. of bytes read. C<undef> on error, 0 on eof, I<e.g.>:
229            
230             $fh = new Archive::Zip::MemberRead($zip, "sreeji/secrets.bin");
231             while (1)
232             {
233             $read = $fh->read($buffer, 1024);
234             die "FATAL ERROR reading my secrets !\n" if (!defined($read));
235             last if (!$read);
236             # Do processing.
237             ....
238             }
239            
240             =cut
241              
242             #
243             # All these $_ are required to emulate read().
244             #
245             sub read {
246 1     1 1 12     my $self = $_[0];
247 1         10     my $size = $_[2];
248 1         9     my ( $temp, $status, $ret );
249              
250 1         13     ( $temp, $status ) = $self->{member}->readChunk($size);
251 1 50 33     15     if ( $status != AZ_OK && $status != AZ_STREAM_END ) {
252 0         0         $_[1] = undef;
253 0         0         $ret = undef;
254                 }
255                 else {
256 1         11         $_[1] = $$temp;
257 1         9         $ret = length($$temp);
258                 }
259 1         12     return $ret;
260             }
261              
262             1;
263              
264             =back
265            
266             =head1 AUTHOR
267            
268             Sreeji K. Das, <sreeji_k@yahoo.com>
269             See L<Archive::Zip> by Ned Konz without which this module does not make
270             any sense!
271            
272             Minor mods by Ned Konz.
273            
274             =head1 COPYRIGHT
275            
276             Copyright (c) 2002 Sreeji K. Das. All rights reserved. This program is free
277             software; you can redistribute it and/or modify it under the same terms
278             as Perl itself.
279            
280             =cut
281