1 # Copyright © 2007-2009 Raphaël Hertzog <hertzog@debian.org>
2 # Copyright © 2009, 2012-2015 Guillem Jover <guillem@debian.org>
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.
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.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <https://www.gnu.org/licenses/>.
17 package Dpkg::Control::HashCore;
22 our $VERSION = '1.01';
25 use Dpkg::ErrorHandling;
26 use Dpkg::Control::FieldsCore;
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.
32 use parent qw(Dpkg::Interface::Storable);
35 '%{}' => sub { ${$_[0]}->{fields} },
36 'eq' => sub { "$_[0]" eq "$_[1]" };
42 Dpkg::Control::HashCore - parse and manipulate a block of RFC822-like fields
46 The Dpkg::Control::Hash object 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
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.
61 During parsing, trailing spaces are stripped on all lines while leading
62 spaces are stripped only on the first line of each field.
68 =item $c = Dpkg::Control::Hash->new(%opts)
70 Creates a new object with the indicated options. Supported options
77 Configures the parser to accept OpenPGP signatures around the control
78 information. Value can be 0 (default) or 1.
82 Configures the parser to allow duplicate fields in the control
83 information. Value can be 0 (default) or 1.
87 Defines if empty fields are dropped during the output. Value can be 0
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.
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).
108 my ($this, %opts) = @_;
109 my $class = ref($this) || $this;
111 # Object is a scalar reference and not a hash ref to avoid
112 # infinite recursion due to overloading hash-dereferencing
118 allow_duplicate => 0,
123 $$self->{fields} = Dpkg::Control::HashCore::Tie->new($self);
125 # Options set by the user override default values
126 $$self->{$_} = $opts{$_} foreach keys %opts;
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.
138 delete $$self->{fields};
141 =item $c->set_options($option, %opts)
143 Changes the value of one or more options.
148 my ($self, %opts) = @_;
149 $$self->{$_} = $opts{$_} foreach keys %opts;
152 =item $value = $c->get_option($option)
154 Returns the value of the corresponding option.
163 =item $c->load($file)
165 Parse the content of $file. Exits in case of errors. Returns true if some
166 fields have been parsed.
168 =item $c->parse_error($file, $fmt, ...)
170 Prints an error message and dies on syntax parse errors.
175 my ($self, $file, $msg) = (shift, shift, shift);
177 $msg = sprintf($msg, @_) if (@_);
178 error(g_('syntax error in %s at line %d: %s'), $file, $., $msg);
181 =item $c->parse($fh, $description)
183 Parse a control file from the given filehandle. Exits in case of errors.
184 $description is used to describe the filehandle, ideally it's a filename
185 or a description of where the data comes from. It's used in error
186 messages. When called multiple times, the parsed fields are accumulated.
188 Returns true if some fields have been parsed.
193 my ($self, $fh, $desc) = @_;
197 my $cf; # Current field
198 my $expect_pgp_sig = 0;
203 next if m/^\s*$/ and $paraborder;
206 if (m/^(\S+?)\s*:\s*(.*)$/) {
208 my ($name, $value) = ($1, $2);
209 if ($name =~ m/^-/) {
210 $self->parse_error($desc, g_('field cannot start with a hyphen'));
212 if (exists $self->{$name}) {
213 unless ($$self->{allow_duplicate}) {
214 $self->parse_error($desc, g_('duplicate field %s found'), $name);
218 $self->{$name} = $value;
220 } elsif (m/^\s(\s*\S.*)$/) {
222 unless (defined($cf)) {
223 $self->parse_error($desc, g_('continued value line not in field'));
226 if ($line =~ /^\.+$/) {
227 $line = substr $line, 1;
229 $self->{$cf} .= "\n$line";
230 } elsif (m/^-----BEGIN PGP SIGNED MESSAGE-----[\r\t ]*$/) {
232 if ($$self->{allow_pgp} and not $parabody) {
233 # Skip OpenPGP headers
238 $self->parse_error($desc, g_('OpenPGP signature not allowed here'));
241 ($expect_pgp_sig && m/^-----BEGIN PGP SIGNATURE-----[\r\t ]*$/)) {
242 if ($expect_pgp_sig) {
244 $_ = <$fh> while defined && m/^\s*$/;
246 $self->parse_error($desc, g_('expected OpenPGP signature, ' .
247 'found end of file after blank line'));
250 unless (m/^-----BEGIN PGP SIGNATURE-----[\r\t ]*$/) {
251 $self->parse_error($desc, g_('expected OpenPGP signature, ' .
252 "found something else '%s'"), $_);
254 # Skip OpenPGP signature
257 last if m/^-----END PGP SIGNATURE-----[\r\t ]*$/;
260 $self->parse_error($desc, g_('unfinished OpenPGP signature'));
262 # This does not mean the signature is correct, that needs to
263 # be verified by gnupg.
264 $$self->{is_pgp_signed} = 1;
266 last; # Finished parsing one block
268 $self->parse_error($desc,
269 g_('line with unknown format (not field-colon-value)'));
273 if ($expect_pgp_sig and not $$self->{is_pgp_signed}) {
274 $self->parse_error($desc, g_('unfinished OpenPGP signature'));
280 =item $c->find_custom_field($name)
282 Scan the fields and look for a user specific field whose name matches the
283 following regex: /X[SBC]*-$name/i. Return the name of the field found or
284 undef if nothing has been found.
288 sub find_custom_field {
289 my ($self, $name) = @_;
290 foreach my $key (keys %$self) {
291 return $key if $key =~ /^X[SBC]*-\Q$name\E$/i;
296 =item $c->get_custom_field($name)
298 Identify a user field and retrieve its value.
302 sub get_custom_field {
303 my ($self, $name) = @_;
304 my $key = $self->find_custom_field($name);
305 return $self->{$key} if defined $key;
309 =item $c->save($filename)
311 Write the string representation of the control information to a
314 =item $str = $c->output()
318 Get a string representation of the control information. The fields
319 are sorted in the order in which they have been read or set except
320 if the order has been overridden with set_output_order().
322 =item $c->output($fh)
324 Print the string representation of the control information to a
330 my ($self, $fh) = @_;
333 if (@{$$self->{out_order}}) {
336 $imp->{$_} = $i++ foreach @{$$self->{out_order}};
338 if (defined $imp->{$a} && defined $imp->{$b}) {
339 $imp->{$a} <=> $imp->{$b};
340 } elsif (defined($imp->{$a})) {
342 } elsif (defined($imp->{$b})) {
349 @keys = @{$$self->{in_order}};
352 foreach my $key (@keys) {
353 if (exists $self->{$key}) {
354 my $value = $self->{$key};
355 # Skip whitespace-only fields
356 next if $$self->{drop_empty} and $value !~ m/\S/;
357 # Escape data to follow control file syntax
358 my ($first_line, @lines) = split /\n/, $value;
361 $kv .= ' ' . $first_line if length $first_line;
365 if (length == 0 or /^\.+$/) {
374 or syserr(g_('write error on control data'));
376 $str .= $kv if defined wantarray;
382 =item $c->set_output_order(@fields)
384 Define the order in which fields will be displayed in the output() method.
388 sub set_output_order {
389 my ($self, @fields) = @_;
391 $$self->{out_order} = [@fields];
394 =item $c->apply_substvars($substvars)
396 Update all fields by replacing the variables references with
397 the corresponding value stored in the Dpkg::Substvars object.
401 sub apply_substvars {
402 my ($self, $substvars, %opts) = @_;
404 # Add substvars to refer to other fields
405 $substvars->set_field_substvars($self, 'F');
407 foreach my $f (keys %$self) {
408 my $v = $substvars->substvars($self->{$f}, %opts);
409 if ($v ne $self->{$f}) {
412 $sep = field_get_sep_type($f);
414 # If we replaced stuff, ensure we're not breaking
415 # a dependency field by introducing empty lines, or multiple
418 if ($sep & (FIELD_SEP_COMMA | FIELD_SEP_LINE)) {
419 # Drop empty/whitespace-only lines
420 $v =~ s/\n[ \t]*(\n|$)/$1/;
423 if ($sep & FIELD_SEP_COMMA) {
424 $v =~ s/,[\s,]*,/,/g;
429 $v =~ s/\$\{\}/\$/g; # XXX: what for?
435 package Dpkg::Control::HashCore::Tie;
437 # This object is used to tie a hash. It implements hash-like functions by
438 # normalizing the name of fields received in keys (using
439 # Dpkg::Control::Fields::field_capitalize). It also stores the order in
440 # which fields have been added in order to be able to dump them in the
441 # same order. But the order information is stored in a parent object of
442 # type Dpkg::Control.
447 use Dpkg::Control::FieldsCore;
451 use parent -norequire, qw(Tie::ExtraHash);
453 # $self->[0] is the real hash
454 # $self->[1] is a reference to the hash contained by the parent object.
455 # This reference bypasses the top-level scalar reference of a
456 # Dpkg::Control::Hash, hence ensuring that reference gets DESTROYed
459 # Dpkg::Control::Hash->new($parent)
461 # Return a reference to a tied hash implementing storage of simple
462 # "field: value" mapping as used in many Debian-specific files.
467 tie %{$hash}, $class, @_;
472 my ($class, $parent) = @_;
473 croak 'parent object must be Dpkg::Control::Hash'
474 if not $parent->isa('Dpkg::Control::HashCore') and
475 not $parent->isa('Dpkg::Control::Hash');
476 return bless [ {}, $$parent ], $class;
480 my ($self, $key) = @_;
482 return $self->[0]->{$key} if exists $self->[0]->{$key};
487 my ($self, $key, $value) = @_;
488 my $parent = $self->[1];
490 if (not exists $self->[0]->{$key}) {
491 push @{$parent->{in_order}}, field_capitalize($key);
493 $self->[0]->{$key} = $value;
497 my ($self, $key) = @_;
499 return exists $self->[0]->{$key};
503 my ($self, $key) = @_;
504 my $parent = $self->[1];
505 my $in_order = $parent->{in_order};
507 if (exists $self->[0]->{$key}) {
508 delete $self->[0]->{$key};
509 @{$in_order} = grep { lc ne $key } @{$in_order};
518 my $parent = $self->[1];
519 foreach my $key (@{$parent->{in_order}}) {
520 return $key if exists $self->[0]->{lc $key};
525 my ($self, $last) = @_;
526 my $parent = $self->[1];
528 foreach my $key (@{$parent->{in_order}}) {
530 return $key if exists $self->[0]->{lc $key};
532 $found = 1 if $key eq $last;
544 =head2 Version 1.01 (dpkg 1.17.2)
546 New method: $c->parse_error().
548 =head2 Version 1.00 (dpkg 1.17.0)
550 Mark the module as public.