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   94 use strict;
  13         27  
  13         389  
20 13     13   77 use warnings;
  13         25  
  13         503  
21              
22             our $VERSION = '1.01';
23              
24 13     13   72 use Dpkg::Gettext;
  13         26  
  13         773  
25 13     13   80 use Dpkg::ErrorHandling;
  13         23  
  13         1015  
26 13     13   3102 use Dpkg::Control::FieldsCore;
  13         43  
  13         1403  
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   4660 use parent qw(Dpkg::Interface::Storable);
  13         2817  
  13         120  
33              
34             use overload
35 13708     13708   22104 '%{}' => sub { ${$_[0]}->{fields} },
  13708         48209  
36 13     13   1314 'eq' => sub { "$_[0]" eq "$_[1]" };
  13     4   30  
  13         93  
  4         913  
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 1508 my ($this, %opts) = @_;
109 789   33     2070 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         4024 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         1742 bless $self, $class;
122              
123 789         1818 $$self->{fields} = Dpkg::Control::HashCore::Tie->new($self);
124              
125             # Options set by the user override default values
126 789         1986 $$self->{$_} = $opts{$_} foreach keys %opts;
127              
128 789         1855 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   17593 my $self = shift;
138 761         6116 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 22 my ($self, $file, $msg) = (shift, shift, shift);
171              
172 7 100       26 $msg = sprintf($msg, @_) if (@_);
173 7         15 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 106 my ($self, $fh, $desc) = @_;
189              
190 39         74 my $paraborder = 1;
191 39         69 my $parabody = 0;
192 39         83 my $cf; # Current field
193 39         72 my $expect_pgp_sig = 0;
194 39         71 local $_;
195              
196 39         430 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         2169 chomp;
201 116         202 my $armor = $_;
202 116         411 s/\s+$//;
203              
204 116 50 66     382 next if length == 0 and $paraborder;
205              
206 116         239 my $lead = substr $_, 0, 1;
207 116 100       251 next if $lead eq '#';
208 113         162 $paraborder = 0;
209              
210 113         571 my ($name, $value) = split /\s*:\s*/, $_, 2;
211 113 100 100     803 if (defined $name and $name =~ m/^\S+?$/) {
    100 33        
    100 66        
    100          
212 81         140 $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       307 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         226 $self->{$name} = $value;
222 81         447 $cf = $name;
223             } elsif (m/^\s(\s*\S.*)$/) {
224 8         19 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       21 if ($line =~ /^\.+$/) {
229 3         7 $line = substr $line, 1;
230             }
231 8         20 $self->{$cf} .= "\n$line";
232             } elsif (length == 0 ||
233             ($expect_pgp_sig && $armor =~ m/^-----BEGIN PGP SIGNATURE-----[\r\t ]*$/)) {
234 15 100       35 if ($expect_pgp_sig) {
235             # Skip empty lines
236 3   66     22 $_ = <$fh> while defined && m/^\s*$/;
237 3 50       80 unless (length) {
238 0         0 $self->parse_error($desc, g_('expected OpenPGP signature, ' .
239             'found end of file after blank line'));
240             }
241 3         7 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         7 while (<$fh>) {
248 16         372 chomp;
249 16 100       50 last if m/^-----END PGP SIGNATURE-----[\r\t ]*$/;
250             }
251 3 50       7 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         30 last; # Finished parsing one block
259             } elsif ($armor =~ m/^-----BEGIN PGP SIGNED MESSAGE-----[\r\t ]*$/) {
260 5         11 $expect_pgp_sig = 1;
261 5 100 66     25 if ($$self->{allow_pgp} and not $parabody) {
262             # Skip OpenPGP headers
263 4         68 while (<$fh>) {
264 8 100       212 last if m/^\s*$/;
265             }
266             } else {
267 1         5 $self->parse_error($desc, g_('OpenPGP signature not allowed here'));
268             }
269             } else {
270 4         18 $self->parse_error($desc,
271             g_('line with unknown format (not field-colon-value)'));
272             }
273             }
274              
275 34 100 100     682 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         160 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 66 my ($self, $fh) = @_;
333 26         44 my $str = '';
334 26         37 my @keys;
335 26 100       39 if (@{$$self->{out_order}}) {
  26         97  
336 10         16 my $i = 1;
337 10         19 my $imp = {};
338 10         17 $imp->{$_} = $i++ foreach @{$$self->{out_order}};
  10         99  
339             @keys = sort {
340 10 100 100     28 if (defined $imp->{$a} && defined $imp->{$b}) {
  185 100       512  
    100          
341 163         306 $imp->{$a} <=> $imp->{$b};
342             } elsif (defined($imp->{$a})) {
343 12         25 -1;
344             } elsif (defined($imp->{$b})) {
345 8         17 1;
346             } else {
347 2         9 $a cmp $b;
348             }
349             } keys %$self;
350             } else {
351 16         25 @keys = @{$$self->{in_order}};
  16         41  
352             }
353              
354 26         68 foreach my $key (@keys) {
355 137 50       249 if (exists $self->{$key}) {
356 137         233 my $value = $self->{$key};
357             # Skip whitespace-only fields
358 137 100 100     708 next if $$self->{drop_empty} and $value !~ m/\S/;
359             # Escape data to follow control file syntax
360 136         386 my ($first_line, @lines) = split /\n/, $value;
361              
362 136         256 my $kv = "$key:";
363 136 100       283 $kv .= ' ' . $first_line if length $first_line;
364 136         188 $kv .= "\n";
365 136         235 foreach (@lines) {
366 110         242 s/\s+$//;
367 110 100 100     291 if (length == 0 or /^\.+$/) {
368 37         61 $kv .= " .$_\n";
369             } else {
370 73         144 $kv .= " $_\n";
371             }
372             }
373             # Print it out
374 136 100       216 if ($fh) {
375 19 50       26 print { $fh } $kv
  19         53  
376             or syserr(g_('write error on control data'));
377             }
378 136 100       408 $str .= $kv if defined wantarray;
379             }
380             }
381 26         193 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 3067 my ($self, @fields) = @_;
396              
397 775         4782 $$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   26177 use strict;
  13         30  
  13         396  
451 13     13   159 use warnings;
  13         27  
  13         499  
452              
453 13     13   83 use Dpkg::Control::FieldsCore;
  13         24  
  13         1452  
454              
455 13     13   95 use Carp;
  13         28  
  13         796  
456 13     13   90 use Tie::Hash;
  13         46  
  13         673  
457 13     13   87 use parent -norequire, qw(Tie::ExtraHash);
  13         25  
  13         101  
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   1181 my $class = shift;
472 789         1290 my $hash = {};
473 789         1100 tie %{$hash}, $class, @_; ## no critic (Miscellanea::ProhibitTies)
  789         2614  
474 789         2085 return $hash;
475             }
476              
477             sub TIEHASH {
478 789     789   1566 my ($class, $parent) = @_;
479 789 0 33     2972 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         4012 return bless [ {}, $$parent ], $class;
483             }
484              
485             sub FETCH {
486 4664     4664   8408 my ($self, $key) = @_;
487 4664         6700 $key = lc($key);
488 4664 100       23610 return $self->[0]->{$key} if exists $self->[0]->{$key};
489 2         9 return;
490             }
491              
492             sub STORE {
493 6230     6230   15504 my ($self, $key, $value) = @_;
494 6230         9350 $key = lc($key);
495 6230 100       12986 if (not exists $self->[0]->{$key}) {
496 4882         6045 push @{$self->[1]->{in_order}}, field_capitalize($key);
  4882         11870  
497             }
498 6230         19348 $self->[0]->{$key} = $value;
499             }
500              
501             sub EXISTS {
502 2312     2312   4245 my ($self, $key) = @_;
503 2312         3531 $key = lc($key);
504 2312         8755 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   1249 my $self = shift;
523 748         1092 my $parent = $self->[1];
524 748         973 foreach my $key (@{$parent->{in_order}}) {
  748         1701  
525 748 50       7616 return $key if exists $self->[0]->{lc $key};
526             }
527             }
528              
529             sub NEXTKEY {
530 1364     1364   2500 my ($self, $last) = @_;
531 1364         1952 my $parent = $self->[1];
532 1364         1705 my $found = 0;
533 1364         1694 foreach my $key (@{$parent->{in_order}}) {
  1364         2211  
534 2917 100       4502 if ($found) {
535 616 50       2413 return $key if exists $self->[0]->{lc $key};
536             } else {
537 2301 100       4635 $found = 1 if $key eq $last;
538             }
539             }
540 748         2092 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;