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   88 use strict;
  13         23  
  13         379  
20 13     13   67 use warnings;
  13         24  
  13         499  
21              
22             our $VERSION = '1.01';
23              
24 13     13   71 use Dpkg::Gettext;
  13         25  
  13         757  
25 13     13   104 use Dpkg::ErrorHandling;
  13         43  
  13         954  
26 13     13   2788 use Dpkg::Control::FieldsCore;
  13         47  
  13         1313  
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   4681 use parent qw(Dpkg::Interface::Storable);
  13         2653  
  13         107  
33              
34             use overload
35 13708     13708   21443 '%{}' => sub { ${$_[0]}->{fields} },
  13708         47706  
36 13     13   1326 'eq' => sub { "$_[0]" eq "$_[1]" };
  13     4   27  
  13         92  
  4         801  
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 1480 my ($this, %opts) = @_;
109 789   33     2081 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         4054 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         1619 bless $self, $class;
122              
123 789         1885 $$self->{fields} = Dpkg::Control::HashCore::Tie->new($self);
124              
125             # Options set by the user override default values
126 789         2044 $$self->{$_} = $opts{$_} foreach keys %opts;
127              
128 789         1901 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   50684 my $self = shift;
138 761         6654 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 17 my ($self, $file, $msg) = (shift, shift, shift);
171              
172 7 100       19 $msg = sprintf($msg, @_) if (@_);
173 7         14 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 89 my ($self, $fh, $desc) = @_;
189              
190 39         70 my $paraborder = 1;
191 39         69 my $parabody = 0;
192 39         48 my $cf; # Current field
193 39         65 my $expect_pgp_sig = 0;
194 39         59 local $_;
195              
196 39         386 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         1707 chomp;
201 116         189 my $armor = $_;
202 116         360 s/\s+$//;
203              
204 116 50 66     314 next if length == 0 and $paraborder;
205              
206 116         221 my $lead = substr $_, 0, 1;
207 116 100       223 next if $lead eq '#';
208 113         131 $paraborder = 0;
209              
210 113         493 my ($name, $value) = split /\s*:\s*/, $_, 2;
211 113 100 100     696 if (defined $name and $name =~ m/^\S+?$/) {
    100 33        
    100 66        
    100          
212 81         125 $parabody = 1;
213 81 50       182 if ($lead eq '-') {
214 0         0 $self->parse_error($desc, g_('field cannot start with a hyphen'));
215             }
216 81 50       254 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         197 $self->{$name} = $value;
222 81         429 $cf = $name;
223             } elsif (m/^\s(\s*\S.*)$/) {
224 8         15 my $line = $1;
225 8 50       13 unless (defined($cf)) {
226 0         0 $self->parse_error($desc, g_('continued value line not in field'));
227             }
228 8 100       16 if ($line =~ /^\.+$/) {
229 3         6 $line = substr $line, 1;
230             }
231 8         14 $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     17 $_ = <$fh> while defined && m/^\s*$/;
237 3 50       64 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       10 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         17 while (<$fh>) {
248 16         311 chomp;
249 16 100       41 last if m/^-----END PGP SIGNATURE-----[\r\t ]*$/;
250             }
251 3 50       14 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         10 $$self->{is_pgp_signed} = 1;
257             }
258 15         20 last; # Finished parsing one block
259             } elsif ($armor =~ m/^-----BEGIN PGP SIGNED MESSAGE-----[\r\t ]*$/) {
260 5         8 $expect_pgp_sig = 1;
261 5 100 66     23 if ($$self->{allow_pgp} and not $parabody) {
262             # Skip OpenPGP headers
263 4         12 while (<$fh>) {
264 8 100       165 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         14 $self->parse_error($desc,
271             g_('line with unknown format (not field-colon-value)'));
272             }
273             }
274              
275 34 100 100     286 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         155 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 60 my ($self, $fh) = @_;
333 26         37 my $str = '';
334 26         33 my @keys;
335 26 100       33 if (@{$$self->{out_order}}) {
  26         67  
336 10         14 my $i = 1;
337 10         55 my $imp = {};
338 10         15 $imp->{$_} = $i++ foreach @{$$self->{out_order}};
  10         96  
339             @keys = sort {
340 10 100 100     26 if (defined $imp->{$a} && defined $imp->{$b}) {
  185 100       470  
    100          
341 163         268 $imp->{$a} <=> $imp->{$b};
342             } elsif (defined($imp->{$a})) {
343 12         27 -1;
344             } elsif (defined($imp->{$b})) {
345 8         12 1;
346             } else {
347 2         5 $a cmp $b;
348             }
349             } keys %$self;
350             } else {
351 16         24 @keys = @{$$self->{in_order}};
  16         36  
352             }
353              
354 26         56 foreach my $key (@keys) {
355 137 50       214 if (exists $self->{$key}) {
356 137         222 my $value = $self->{$key};
357             # Skip whitespace-only fields
358 137 100 100     541 next if $$self->{drop_empty} and $value !~ m/\S/;
359             # Escape data to follow control file syntax
360 136         343 my ($first_line, @lines) = split /\n/, $value;
361              
362 136         217 my $kv = "$key:";
363 136 100       249 $kv .= ' ' . $first_line if length $first_line;
364 136         153 $kv .= "\n";
365 136         194 foreach (@lines) {
366 110         212 s/\s+$//;
367 110 100 100     259 if (length == 0 or /^\.+$/) {
368 37         54 $kv .= " .$_\n";
369             } else {
370 73         135 $kv .= " $_\n";
371             }
372             }
373             # Print it out
374 136 100       205 if ($fh) {
375 19 50       19 print { $fh } $kv
  19         43  
376             or syserr(g_('write error on control data'));
377             }
378 136 100       358 $str .= $kv if defined wantarray;
379             }
380             }
381 26         174 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 3222 my ($self, @fields) = @_;
396              
397 775         4564 $$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   24953 use strict;
  13         34  
  13         363  
451 13     13   161 use warnings;
  13         33  
  13         510  
452              
453 13     13   75 use Dpkg::Control::FieldsCore;
  13         28  
  13         1376  
454              
455 13     13   90 use Carp;
  13         26  
  13         788  
456 13     13   85 use Tie::Hash;
  13         43  
  13         657  
457 13     13   81 use parent -norequire, qw(Tie::ExtraHash);
  13         25  
  13         90  
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   1111 my $class = shift;
472 789         1179 my $hash = {};
473 789         1105 tie %{$hash}, $class, @_; ## no critic (Miscellanea::ProhibitTies)
  789         2574  
474 789         2052 return $hash;
475             }
476              
477             sub TIEHASH {
478 789     789   1467 my ($class, $parent) = @_;
479 789 0 33     2907 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         3940 return bless [ {}, $$parent ], $class;
483             }
484              
485             sub FETCH {
486 4664     4664   8329 my ($self, $key) = @_;
487 4664         6521 $key = lc($key);
488 4664 100       23047 return $self->[0]->{$key} if exists $self->[0]->{$key};
489 2         7 return;
490             }
491              
492             sub STORE {
493 6230     6230   15425 my ($self, $key, $value) = @_;
494 6230         9120 $key = lc($key);
495 6230 100       12566 if (not exists $self->[0]->{$key}) {
496 4882         6075 push @{$self->[1]->{in_order}}, field_capitalize($key);
  4882         11351  
497             }
498 6230         18634 $self->[0]->{$key} = $value;
499             }
500              
501             sub EXISTS {
502 2312     2312   4345 my ($self, $key) = @_;
503 2312         3488 $key = lc($key);
504 2312         8515 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   1302 my $self = shift;
523 748         1112 my $parent = $self->[1];
524 748         956 foreach my $key (@{$parent->{in_order}}) {
  748         1590  
525 748 50       3406 return $key if exists $self->[0]->{lc $key};
526             }
527             }
528              
529             sub NEXTKEY {
530 1364     1364   2507 my ($self, $last) = @_;
531 1364         1833 my $parent = $self->[1];
532 1364         1795 my $found = 0;
533 1364         1571 foreach my $key (@{$parent->{in_order}}) {
  1364         2206  
534 2917 100       4222 if ($found) {
535 616 50       2385 return $key if exists $self->[0]->{lc $key};
536             } else {
537 2301 100       4439 $found = 1 if $key eq $last;
538             }
539             }
540 748         2043 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;