File Coverage

lib/Archive/Lha/Header/Level1.pm
Criterion Covered Total %
statement 57 64 89.0
branch 6 12 50.0
condition n/a
subroutine 7 7 100.0
pod 1 1 100.0
total 71 84 84.5


line stmt bran cond sub pod time code
1             package Archive::Lha::Header::Level1;
2              
3 17     17   123 use strict;
  17         34  
  17         628  
4 17     17   96 use warnings;
  17         29  
  17         1068  
5 17     17   123 use Carp;
  17         32  
  17         1203  
6 17     17   95 use Archive::Lha::Constants;
  17         27  
  17         113  
7 17     17   103 use Archive::Lha::Header::Base;
  17         29  
  17         121  
8 17     17   88 use Archive::Lha::Header::Utils;
  17         32  
  17         149  
9              
10             sub new {
11 239     239 1 415 my ($class, $stream) = @_;
12              
13 239         487 my $start = $stream->tell;
14 239         454 my $size = ord($stream->read(1)) + 2;
15              
16 239 50       546 croak "Header is broken: size is too small: $size" if $size < 27;
17              
18 239         574 $stream->seek($start);
19 239         460 my $buf = $stream->read($size);
20              
21 239         544 my $checksum = ord(substr($buf, 1, 1));
22             my $checksum1 = defined &Archive::Lha::Header::Utils::checksum
23             ? Archive::Lha::Header::Utils::checksum($buf, 2)
24 239 50       868 : do { my $s = 0; $s += $_ for unpack 'C*', substr($buf, 2); $s & CHAR_MAX };
  0         0  
  0         0  
  0         0  
25 239 50       467 croak "Header is broken: checksum $checksum/$checksum1"
26             unless $checksum == $checksum1;
27              
28 239         352 my %header;
29 239         458 $header{header_top} = $start;
30 239         340 $header{header_size} = $size;
31 239         324 $header{header_checksum} = $checksum;
32 239         458 $header{method} = substr($buf, 3, 3);
33 239         609 $header{skip_size} = unpack 'V', substr($buf, 7, 4);
34 239         431 $header{original_size} = unpack 'V', substr($buf, 11, 4);
35 239         531 $header{timestamp} = unpack 'V', substr($buf, 15, 4);
36              
37 239         344 my $filename_length = ord(substr($buf, 21, 1));
38 239         463 $header{filename} = substr($buf, 22, $filename_length);
39 239         462 $header{filename} =~ s/\0.*//s;
40 239         437 $header{crc16} = unpack 'v', substr($buf, 22 + $filename_length, 2);
41 239         815 $header{os} = _os_id( substr($buf, 24 + $filename_length, 1) );
42              
43 239         455 my $ext_from = 25 + $filename_length;
44 239         338 my $ext_to = $size - 3;
45 239 50       371 if ($ext_from < $ext_to) {
46 0         0 my (undef, $ext) = _extended_header_buf($buf, $ext_from, $ext_to - $ext_from + 2);
47 0 0       0 %header = (%header, %{ $ext }) if %{ $ext };
  0         0  
  0         0  
48             }
49              
50 239         317 my $extended_size_total = 0;
51 239         456 my $extended_size = unpack 'v', substr($buf, -2, 2);
52 239         443 while ($extended_size) {
53 466         890 my $chunk = $stream->read($extended_size);
54 466         594 $extended_size_total += $extended_size;
55 466         886 my ($next, $hash) = _extended_header_buf($chunk, 0, $extended_size);
56 466 100       636 %header = (%header, %{ $hash }) if %{ $hash };
  462         2588  
  466         1404  
57 466         1342 $extended_size = $next;
58             }
59 239         473 $header{encoded_size} = $header{skip_size} - $extended_size_total;
60              
61 239         368 $header{data_top} = $start + $size + $extended_size_total;
62 239         405 $header{next_header} = $header{data_top} + $header{encoded_size};
63              
64 239         905 bless \%header, $class;
65             }
66              
67             1;
68              
69             __END__