File Coverage

blib/lib/Dpkg/Control/HashCore.pm
Criterion Covered Total %
statement 172 218 78.9
branch 61 88 69.3
condition 26 36 72.2
subroutine 28 34 82.3
pod 10 10 100.0
total 297 386 76.9


line stmt bran cond sub pod time code
1             # Copyright © 2007-2009 Raphaël Hertzog
2             # Copyright © 2009, 2012-2015 Guillem Jover
3             #
4             # This program is free software; you can redistribute it and/or modify
5             # it under the terms of the GNU General Public License as published by
6             # the Free Software Foundation; either version 2 of the License, or
7             # (at your option) any later version.
8             #
9             # This program is distributed in the hope that it will be useful,
10             # but WITHOUT ANY WARRANTY; without even the implied warranty of
11             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12             # GNU General Public License for more details.
13             #
14             # You should have received a copy of the GNU General Public License
15             # along with this program. If not, see .
16              
17             package Dpkg::Control::HashCore;
18              
19 13     13   85 use strict;
  13         34  
  13         385  
20 13     13   65 use warnings;
  13         25  
  13         517  
21              
22             our $VERSION = '1.01';
23              
24 13     13   73 use Dpkg::Gettext;
  13         26  
  13         794  
25 13     13   92 use Dpkg::ErrorHandling;
  13         25  
  13         1050  
26 13     13   2738 use Dpkg::Control::FieldsCore;
  13         40  
  13         1406  
27              
28             # This module cannot use Dpkg::Control::Fields, because that one makes use
29             # of Dpkg::Vendor which at the same time uses this module, which would turn
30             # into a compilation error. We can use Dpkg::Control::FieldsCore instead.
31              
32 13     13   4613 use parent qw(Dpkg::Interface::Storable);
  13         2850  
  13         113  
33              
34             use overload
35 13708     13708   23694 '%{}' => sub { ${$_[0]}->{fields} },
  13708         48610  
36 13     13   1295 'eq' => sub { "$_[0]" eq "$_[1]" };
  13     4   39  
  13         94  
  4         894  
37              
38             =encoding utf8
39              
40             =head1 NAME
41              
42             Dpkg::Control::HashCore - parse and manipulate a block of RFC822-like fields
43              
44             =head1 DESCRIPTION
45              
46             The Dpkg::Control::Hash class is a hash-like representation of a set of
47             RFC822-like fields. The fields names are case insensitive and are always
48             capitalized the same when output (see field_capitalize function in
49             Dpkg::Control::Fields).
50             The order in which fields have been set is remembered and is used
51             to be able to dump back the same content. The output order can also be
52             overridden if needed.
53              
54             You can store arbitrary values in the hash, they will always be properly
55             escaped in the output to conform to the syntax of control files. This is
56             relevant mainly for multilines values: while the first line is always output
57             unchanged directly after the field name, supplementary lines are
58             modified. Empty lines and lines containing only dots are prefixed with
59             " ." (space + dot) while other lines are prefixed with a single space.
60              
61             During parsing, trailing spaces are stripped on all lines while leading
62             spaces are stripped only on the first line of each field.
63              
64             =head1 METHODS
65              
66             =over 4
67              
68             =item $c = Dpkg::Control::Hash->new(%opts)
69              
70             Creates a new object with the indicated options. Supported options
71             are:
72              
73             =over 8
74              
75             =item allow_pgp
76              
77             Configures the parser to accept OpenPGP signatures around the control
78             information. Value can be 0 (default) or 1.
79              
80             =item allow_duplicate
81              
82             Configures the parser to allow duplicate fields in the control
83             information. Value can be 0 (default) or 1.
84              
85             =item drop_empty
86              
87             Defines if empty fields are dropped during the output. Value can be 0
88             (default) or 1.
89              
90             =item name
91              
92             The user friendly name of the information stored in the object. It might
93             be used in some error messages or warnings. A default name might be set
94             depending on the type.
95              
96             =item is_pgp_signed
97              
98             Set by the parser (starting in dpkg 1.17.0) if it finds an OpenPGP
99             signature around the control information. Value can be 0 (default)
100             or 1, and undef when the option is not supported by the code (in
101             versions older than dpkg 1.17.0).
102              
103             =back
104              
105             =cut
106              
107             sub new {
108 789     789 1 1430 my ($this, %opts) = @_;
109 789   33     2119 my $class = ref($this) || $this;
110              
111             # Object is a scalar reference and not a hash ref to avoid
112             # infinite recursion due to overloading hash-dereferencing
113 789         3975 my $self = \{
114             in_order => [],
115             out_order => [],
116             is_pgp_signed => 0,
117             allow_pgp => 0,
118             allow_duplicate => 0,
119             drop_empty => 0,
120             };
121 789         1604 bless $self, $class;
122              
123 789         1866 $$self->{fields} = Dpkg::Control::HashCore::Tie->new($self);
124              
125             # Options set by the user override default values
126 789         1993 $$self->{$_} = $opts{$_} foreach keys %opts;
127              
128 789         1879 return $self;
129             }
130              
131             # There is naturally a circular reference between the tied hash and its
132             # containing object. Happily, the extra layer of scalar reference can
133             # be used to detect the destruction of the object and break the loop so
134             # that everything gets garbage-collected.
135              
136             sub DESTROY {
137 761     761   16248 my $self = shift;
138 761         6364 delete $$self->{fields};
139             }
140              
141             =item $c->set_options($option, %opts)
142              
143             Changes the value of one or more options.
144              
145             =cut
146              
147             sub set_options {
148 0     0 1 0 my ($self, %opts) = @_;
149 0         0 $$self->{$_} = $opts{$_} foreach keys %opts;
150             }
151              
152             =item $value = $c->get_option($option)
153              
154             Returns the value of the corresponding option.
155              
156             =cut
157              
158             sub get_option {
159 0     0 1 0 my ($self, $k) = @_;
160 0         0 return $$self->{$k};
161             }
162              
163             =item $c->parse_error($file, $fmt, ...)
164              
165             Prints an error message and dies on syntax parse errors.
166              
167             =cut
168              
169             sub parse_error {
170 7     7 1 19 my ($self, $file, $msg) = (shift, shift, shift);
171              
172 7 100       23 $msg = sprintf($msg, @_) if (@_);
173 7         18 error(g_('syntax error in %s at line %d: %s'), $file, $., $msg);
174             }
175              
176             =item $c->parse($fh, $description)
177              
178             Parse a control file from the given filehandle. Exits in case of errors.
179             $description is used to describe the filehandle, ideally it's a filename
180             or a description of where the data comes from. It's used in error
181             messages. When called multiple times, the parsed fields are accumulated.
182              
183             Returns true if some fields have been parsed.
184              
185             =cut
186              
187             sub parse {
188 39     39 1 98 my ($self, $fh, $desc) = @_;
189              
190 39         67 my $paraborder = 1;
191 39         73 my $parabody = 0;
192 39         73 my $cf; # Current field
193 39         75 my $expect_pgp_sig = 0;
194 39         63 local $_;
195              
196 39         429 while (<$fh>) {
197             # In the common case there will be just a trailing \n character,
198             # so using chomp here which is very fast will avoid the latter
199             # s/// doing anything, which gives usa significant speed up.
200 116         2043 chomp;
201 116         201 my $armor = $_;
202 116         406 s/\s+$//;
203              
204 116 50 66     358 next if length == 0 and $paraborder;
205              
206 116         230 my $lead = substr $_, 0, 1;
207 116 100       243 next if $lead eq '#';
208 113         157 $paraborder = 0;
209              
210 113         530 my ($name, $value) = split /\s*:\s*/, $_, 2;
211 113 100 100     775 if (defined $name and $name =~ m/^\S+?$/) {
    100 33        
    100 66        
    100          
212 81         142 $parabody = 1;
213 81 50       187 if ($lead eq '-') {
214 0         0 $self->parse_error($desc, g_('field cannot start with a hyphen'));
215             }
216 81 50       266 if (exists $self->{$name}) {
217 0 0       0 unless ($$self->{allow_duplicate}) {
218 0         0 $self->parse_error($desc, g_('duplicate field %s found'), $name);
219             }
220             }
221 81         211 $self->{$name} = $value;
222 81         442 $cf = $name;
223             } elsif (m/^\s(\s*\S.*)$/) {
224 8         18 my $line = $1;
225 8 50       18 unless (defined($cf)) {
226 0         0 $self->parse_error($desc, g_('continued value line not in field'));
227             }
228 8 100       18 if ($line =~ /^\.+$/) {
229 3         7 $line = substr $line, 1;
230             }
231 8         18 $self->{$cf} .= "\n$line";
232             } elsif (length == 0 ||
233             ($expect_pgp_sig && $armor =~ m/^-----BEGIN PGP SIGNATURE-----[\r\t ]*$/)) {
234 15 100       31 if ($expect_pgp_sig) {
235             # Skip empty lines
236 3   66     33 $_ = <$fh> while defined && m/^\s*$/;
237 3 50       81 unless (length) {
238 0         0 $self->parse_error($desc, g_('expected OpenPGP signature, ' .
239             'found end of file after blank line'));
240             }
241 3         5 chomp;
242 3 50       11 unless (m/^-----BEGIN PGP SIGNATURE-----[\r\t ]*$/) {
243 0         0 $self->parse_error($desc, g_('expected OpenPGP signature, ' .
244             "found something else '%s'"), $_);
245             }
246             # Skip OpenPGP signature
247 3         9 while (<$fh>) {
248 16         359 chomp;
249 16 100       61 last if m/^-----END PGP SIGNATURE-----[\r\t ]*$/;
250             }
251 3 50       8 unless (defined) {
252 0         0 $self->parse_error($desc, g_('unfinished OpenPGP signature'));
253             }
254             # This does not mean the signature is correct, that needs to
255             # be verified by gnupg.
256 3         9 $$self->{is_pgp_signed} = 1;
257             }
258 15         29 last; # Finished parsing one block
259             } elsif ($armor =~ m/^-----BEGIN PGP SIGNED MESSAGE-----[\r\t ]*$/) {
260 5         12 $expect_pgp_sig = 1;
261 5 100 66     27 if ($$self->{allow_pgp} and not $parabody) {
262             # Skip OpenPGP headers
263 4         13 while (<$fh>) {
264 8 100       206 last if m/^\s*$/;
265             }
266             } else {
267 1         4 $self->parse_error($desc, g_('OpenPGP signature not allowed here'));
268             }
269             } else {
270 4         20 $self->parse_error($desc,
271             g_('line with unknown format (not field-colon-value)'));
272             }
273             }
274              
275 34 100 100     342 if ($expect_pgp_sig and not $$self->{is_pgp_signed}) {
276 1         5 $self->parse_error($desc, g_('unfinished OpenPGP signature'));
277             }
278              
279 33         168 return defined($cf);
280             }
281              
282             =item $c->load($file)
283              
284             Parse the content of $file. Exits in case of errors. Returns true if some
285             fields have been parsed.
286              
287             =item $c->find_custom_field($name)
288              
289             Scan the fields and look for a user specific field whose name matches the
290             following regex: /X[SBC]*-$name/i. Return the name of the field found or
291             undef if nothing has been found.
292              
293             =cut
294              
295             sub find_custom_field {
296 0     0 1 0 my ($self, $name) = @_;
297 0         0 foreach my $key (keys %$self) {
298 0 0       0 return $key if $key =~ /^X[SBC]*-\Q$name\E$/i;
299             }
300 0         0 return;
301             }
302              
303             =item $c->get_custom_field($name)
304              
305             Identify a user field and retrieve its value.
306              
307             =cut
308              
309             sub get_custom_field {
310 0     0 1 0 my ($self, $name) = @_;
311 0         0 my $key = $self->find_custom_field($name);
312 0 0       0 return $self->{$key} if defined $key;
313 0         0 return;
314             }
315              
316             =item $str = $c->output()
317              
318             =item "$c"
319              
320             Get a string representation of the control information. The fields
321             are sorted in the order in which they have been read or set except
322             if the order has been overridden with set_output_order().
323              
324             =item $c->output($fh)
325              
326             Print the string representation of the control information to a
327             filehandle.
328              
329             =cut
330              
331             sub output {
332 26     26 1 59 my ($self, $fh) = @_;
333 26         47 my $str = '';
334 26         37 my @keys;
335 26 100       35 if (@{$$self->{out_order}}) {
  26         89  
336 10         19 my $i = 1;
337 10         19 my $imp = {};
338 10         16 $imp->{$_} = $i++ foreach @{$$self->{out_order}};
  10         99  
339             @keys = sort {
340 10 100 100     25 if (defined $imp->{$a} && defined $imp->{$b}) {
  185 100       504  
    100          
341 163         289 $imp->{$a} <=> $imp->{$b};
342             } elsif (defined($imp->{$a})) {
343 12         27 -1;
344             } elsif (defined($imp->{$b})) {
345 8         16 1;
346             } else {
347 2         6 $a cmp $b;
348             }
349             } keys %$self;
350             } else {
351 16         38 @keys = @{$$self->{in_order}};
  16         39  
352             }
353              
354 26         71 foreach my $key (@keys) {
355 137 50       250 if (exists $self->{$key}) {
356 137         231 my $value = $self->{$key};
357             # Skip whitespace-only fields
358 137 100 100     596 next if $$self->{drop_empty} and $value !~ m/\S/;
359             # Escape data to follow control file syntax
360 136         374 my ($first_line, @lines) = split /\n/, $value;
361              
362 136         283 my $kv = "$key:";
363 136 100       289 $kv .= ' ' . $first_line if length $first_line;
364 136         183 $kv .= "\n";
365 136         224 foreach (@lines) {
366 110         236 s/\s+$//;
367 110 100 100     297 if (length == 0 or /^\.+$/) {
368 37         65 $kv .= " .$_\n";
369             } else {
370 73         147 $kv .= " $_\n";
371             }
372             }
373             # Print it out
374 136 100       230 if ($fh) {
375 19 50       24 print { $fh } $kv
  19         51  
376             or syserr(g_('write error on control data'));
377             }
378 136 100       401 $str .= $kv if defined wantarray;
379             }
380             }
381 26         183 return $str;
382             }
383              
384             =item $c->save($filename)
385              
386             Write the string representation of the control information to a file.
387              
388             =item $c->set_output_order(@fields)
389              
390             Define the order in which fields will be displayed in the output() method.
391              
392             =cut
393              
394             sub set_output_order {
395 775     775 1 3088 my ($self, @fields) = @_;
396              
397 775         4804 $$self->{out_order} = [@fields];
398             }
399              
400             =item $c->apply_substvars($substvars)
401              
402             Update all fields by replacing the variables references with
403             the corresponding value stored in the Dpkg::Substvars object.
404              
405             =cut
406              
407             sub apply_substvars {
408 0     0 1 0 my ($self, $substvars, %opts) = @_;
409              
410             # Add substvars to refer to other fields
411 0         0 $substvars->set_field_substvars($self, 'F');
412              
413 0         0 foreach my $f (keys %$self) {
414 0         0 my $v = $substvars->substvars($self->{$f}, %opts);
415 0 0       0 if ($v ne $self->{$f}) {
416 0         0 my $sep;
417              
418 0         0 $sep = field_get_sep_type($f);
419              
420             # If we replaced stuff, ensure we're not breaking
421             # a dependency field by introducing empty lines, or multiple
422             # commas
423              
424 0 0       0 if ($sep & (FIELD_SEP_COMMA | FIELD_SEP_LINE)) {
425             # Drop empty/whitespace-only lines
426 0         0 $v =~ s/\n[ \t]*(\n|$)/$1/;
427             }
428              
429 0 0       0 if ($sep & FIELD_SEP_COMMA) {
430 0         0 $v =~ s/,[\s,]*,/,/g;
431 0         0 $v =~ s/^\s*,\s*//;
432 0         0 $v =~ s/\s*,\s*$//;
433             }
434             }
435 0         0 $v =~ s/\$\{\}/\$/g; # XXX: what for?
436              
437 0         0 $self->{$f} = $v;
438             }
439             }
440              
441             package Dpkg::Control::HashCore::Tie;
442              
443             # This class is used to tie a hash. It implements hash-like functions by
444             # normalizing the name of fields received in keys (using
445             # Dpkg::Control::Fields::field_capitalize). It also stores the order in
446             # which fields have been added in order to be able to dump them in the
447             # same order. But the order information is stored in a parent object of
448             # type Dpkg::Control.
449              
450 13     13   26001 use strict;
  13         36  
  13         386  
451 13     13   181 use warnings;
  13         29  
  13         509  
452              
453 13     13   82 use Dpkg::Control::FieldsCore;
  13         43  
  13         1467  
454              
455 13     13   100 use Carp;
  13         27  
  13         752  
456 13     13   87 use Tie::Hash;
  13         31  
  13         683  
457 13     13   89 use parent -norequire, qw(Tie::ExtraHash);
  13         27  
  13         96  
458              
459             # $self->[0] is the real hash
460             # $self->[1] is a reference to the hash contained by the parent object.
461             # This reference bypasses the top-level scalar reference of a
462             # Dpkg::Control::Hash, hence ensuring that reference gets DESTROYed
463             # properly.
464              
465             # Dpkg::Control::Hash->new($parent)
466             #
467             # Return a reference to a tied hash implementing storage of simple
468             # "field: value" mapping as used in many Debian-specific files.
469              
470             sub new {
471 789     789   1258 my $class = shift;
472 789         1186 my $hash = {};
473 789         1167 tie %{$hash}, $class, @_; ## no critic (Miscellanea::ProhibitTies)
  789         2701  
474 789         2063 return $hash;
475             }
476              
477             sub TIEHASH {
478 789     789   1657 my ($class, $parent) = @_;
479 789 0 33     3007 croak 'parent object must be Dpkg::Control::Hash'
480             if not $parent->isa('Dpkg::Control::HashCore') and
481             not $parent->isa('Dpkg::Control::Hash');
482 789         3894 return bless [ {}, $$parent ], $class;
483             }
484              
485             sub FETCH {
486 4664     4664   8251 my ($self, $key) = @_;
487 4664         6707 $key = lc($key);
488 4664 100       23904 return $self->[0]->{$key} if exists $self->[0]->{$key};
489 2         8 return;
490             }
491              
492             sub STORE {
493 6230     6230   14821 my ($self, $key, $value) = @_;
494 6230         9398 $key = lc($key);
495 6230 100       12754 if (not exists $self->[0]->{$key}) {
496 4882         6003 push @{$self->[1]->{in_order}}, field_capitalize($key);
  4882         11888  
497             }
498 6230         19226 $self->[0]->{$key} = $value;
499             }
500              
501             sub EXISTS {
502 2312     2312   4377 my ($self, $key) = @_;
503 2312         3431 $key = lc($key);
504 2312         8412 return exists $self->[0]->{$key};
505             }
506              
507             sub DELETE {
508 0     0   0 my ($self, $key) = @_;
509 0         0 my $parent = $self->[1];
510 0         0 my $in_order = $parent->{in_order};
511 0         0 $key = lc($key);
512 0 0       0 if (exists $self->[0]->{$key}) {
513 0         0 delete $self->[0]->{$key};
514 0         0 @{$in_order} = grep { lc ne $key } @{$in_order};
  0         0  
  0         0  
  0         0  
515 0         0 return 1;
516             } else {
517 0         0 return 0;
518             }
519             }
520              
521             sub FIRSTKEY {
522 748     748   1303 my $self = shift;
523 748         1191 my $parent = $self->[1];
524 748         1342 foreach my $key (@{$parent->{in_order}}) {
  748         1605  
525 748 50       3388 return $key if exists $self->[0]->{lc $key};
526             }
527             }
528              
529             sub NEXTKEY {
530 1364     1364   2427 my ($self, $last) = @_;
531 1364         1924 my $parent = $self->[1];
532 1364         1790 my $found = 0;
533 1364         1688 foreach my $key (@{$parent->{in_order}}) {
  1364         2320  
534 2917 100       4430 if ($found) {
535 616 50       2375 return $key if exists $self->[0]->{lc $key};
536             } else {
537 2301 100       4435 $found = 1 if $key eq $last;
538             }
539             }
540 748         2140 return;
541             }
542              
543             1;
544              
545             =back
546              
547             =head1 CHANGES
548              
549             =head2 Version 1.01 (dpkg 1.17.2)
550              
551             New method: $c->parse_error().
552              
553             =head2 Version 1.00 (dpkg 1.17.0)
554              
555             Mark the module as public.
556              
557             =cut
558              
559             1;