1 package IO::Compress::Zlib::Extra;
9 our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS);
13 use IO::Compress::Gzip::Constants 2.003 ;
18 return "Error with ExtraField Parameter: $_[0]" ;
21 sub validateExtraFieldPair
25 my $gzipMode = shift ;
27 return ExtraFieldError("Not an array ref")
28 unless ref $pair && ref $pair eq 'ARRAY';
30 return ExtraFieldError("SubField must have two parts")
33 return ExtraFieldError("SubField ID is a reference")
36 return ExtraFieldError("SubField Data is a reference")
39 # ID is exactly two chars
40 return ExtraFieldError("SubField ID not two chars long")
41 unless length $pair->[0] == GZIP_FEXTRA_SUBFIELD_ID_SIZE ;
43 # Check that the 2nd byte of the ID isn't 0
44 return ExtraFieldError("SubField ID 2nd byte is 0x00")
45 if $strict && $gzipMode && substr($pair->[0], 1, 1) eq "\x00" ;
47 return ExtraFieldError("SubField Data too long")
48 if length $pair->[1] > GZIP_FEXTRA_SUBFIELD_MAX_SIZE ;
59 my $gzipMode = shift ;
66 my $XLEN = length $data ;
68 return ExtraFieldError("Too Large")
69 if $XLEN > GZIP_FEXTRA_MAX_SIZE;
72 while ($offset < $XLEN) {
74 return ExtraFieldError("Truncated in FEXTRA Body Section")
75 if $offset + GZIP_FEXTRA_SUBFIELD_HEADER_SIZE > $XLEN ;
77 my $id = substr($data, $offset, GZIP_FEXTRA_SUBFIELD_ID_SIZE);
78 $offset += GZIP_FEXTRA_SUBFIELD_ID_SIZE;
80 my $subLen = unpack("v", substr($data, $offset,
81 GZIP_FEXTRA_SUBFIELD_LEN_SIZE));
82 $offset += GZIP_FEXTRA_SUBFIELD_LEN_SIZE ;
84 return ExtraFieldError("Truncated in FEXTRA Body Section")
85 if $offset + $subLen > $XLEN ;
87 my $bad = validateExtraFieldPair( [$id,
88 substr($data, $offset, $subLen)],
91 push @$extraRef, [$id => substr($data, $offset, $subLen)]
92 if defined $extraRef;;
107 return $id . pack("v", length $data) . $data ;
114 my $gzipMode = $_[2];
115 #my $lax = @_ == 2 ? $_[1] : 1;
118 # ExtraField can be any of
120 # -ExtraField => $data
122 # -ExtraField => [$id1, $data1,
127 # -ExtraField => [ [$id1 => $data1],
132 # -ExtraField => { $id1 => $data1,
137 if ( ! ref $dataRef ) {
142 return parseRawExtra($dataRef, undef, 1, $gzipMode);
145 #my $data = $$dataRef;
149 if (ref $data eq 'ARRAY') {
150 if (ref $data->[0]) {
152 foreach my $pair (@$data) {
153 return ExtraFieldError("Not list of lists")
154 unless ref $pair eq 'ARRAY' ;
156 my $bad = validateExtraFieldPair($pair, $strict, $gzipMode) ;
157 return $bad if $bad ;
159 $out .= mkSubField(@$pair);
163 return ExtraFieldError("Not even number of elements")
164 unless @$data % 2 == 0;
166 for (my $ix = 0; $ix <= length(@$data) -1 ; $ix += 2) {
167 my $bad = validateExtraFieldPair([$data->[$ix],
169 $strict, $gzipMode) ;
170 return $bad if $bad ;
172 $out .= mkSubField($data->[$ix], $data->[$ix+1]);
176 elsif (ref $data eq 'HASH') {
177 while (my ($id, $info) = each %$data) {
178 my $bad = validateExtraFieldPair([$id, $info], $strict, $gzipMode);
179 return $bad if $bad ;
181 $out .= mkSubField($id, $info);
185 return ExtraFieldError("Not a scalar, array ref or hash ref") ;
188 return ExtraFieldError("Too Large")
189 if length $out > GZIP_FEXTRA_MAX_SIZE;