# Copyright © 2007-2009 Raphaël Hertzog <hertzog@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

package Dpkg::Control::Hash;

use strict;
use warnings;

our $VERSION = "1.00";

use Dpkg::Gettext;
use Dpkg::ErrorHandling;

# This module must absolutely not use Dpkg::Control::Fields
# it's used by other modules that are required to compile
# Dpkg::Control::Fields itself (Dpkg::Vendor)
# That's why field_capitalize is duplicated

use base qw(Dpkg::Interface::Storable);

use overload
    '%{}' => sub { ${$_[0]}->{'fields'} },
    'eq' => sub { "$_[0]" eq "$_[1]" };

=encoding utf8

=head1 NAME

Dpkg::Control::Hash - parse and manipulate a block of RFC822-like fields

=head1 DESCRIPTION

The Dpkg::Control::Hash object is a hash-like representation of a set of
RFC822-like fields. The fields names are case insensitive and are always
capitalized the same when output (see field_capitalize function in
Dpkg::Control::Fields).
The order in which fields have been set is remembered and is used
to be able to dump back the same content. The output order can also be
overridden if needed.

You can store arbitrary values in the hash, they will always be properly
escaped in the output to conform to the syntax of control files. This is
relevant mainly for multilines values: while the first line is always output
unchanged directly after the field name, supplementary lines are
modified. Empty lines and lines containing only dots are prefixed with
" ." (space + dot) while other lines are prefixed with a single space.

During parsing, trailing spaces are stripped on all lines while leading
spaces are stripped only on the first line of each field.

=head1 FUNCTIONS

=over 4

=item my $c = Dpkg::Control::Hash->new(%opts)

Creates a new object with the indicated options. Supported options
are:

=over 8

=item allow_pgp

Configures the parser to accept PGP signatures around the control
information. Value can be 0 (default) or 1.

=item allow_duplicate

Configures the parser to allow duplicate fields in the control
information. Value can be 0 (default) or 1.

=item drop_empty

Defines if empty fields are dropped during the output. Value can be 0
(default) or 1.

=item name

The user friendly name of the information stored in the object. It might
be used in some error messages or warnings. A default name might be set
depending on the type.

=back

=cut

sub new {
    my ($this, %opts) = @_;
    my $class = ref($this) || $this;

    # Object is a scalar reference and not a hash ref to avoid
    # infinite recursion due to overloading hash-derefencing
    my $self = \{
        'in_order' => [],
        'out_order' => [],
        'allow_pgp' => 0,
        'allow_duplicate' => 0,
        'drop_empty' => 0,
    };
    bless $self, $class;

    $$self->{'fields'} = Dpkg::Control::Hash::Tie->new($self);

    # Options set by the user override default values
    $$self->{$_} = $opts{$_} foreach keys %opts;

    return $self;
}

=item $c->set_options($option, %opts)

Changes the value of one or more options.

=cut

sub set_options {
    my ($self, $k, $v) = @_;
    $$self->{$k} = $v;
}

=item my $value = $c->get_option($option)

Returns the value of the corresponding option.

=cut

sub get_option {
    my ($self, $k) = @_;
    return $$self->{$k};
}

=item $c->load($file)

Parse the content of $file. Exits in case of errors. Returns true if some
fields have been parsed.

=item $c->parse($fh, $description)

Parse a control file from the given filehandle. Exits in case of errors.
$description is used to describe the filehandle, ideally it's a filename
or a description of where the data comes from. It's used in error
messages. Returns true if some fields have been parsed.

=cut

sub parse {
    my ($self, $fh, $desc) = @_;

    my $paraborder = 1;
    my $cf; # Current field
    my $expect_pgp_sig = 0;
    while (<$fh>) {
	s/\s*\n$//;
	next if (m/^$/ and $paraborder);
	next if (m/^#/);
	$paraborder = 0;
	if (m/^(\S+?)\s*:\s*(.*)$/) {
	    if (exists $self->{$1}) {
		unless ($$self->{'allow_duplicate'}) {
		    syntaxerr($desc, sprintf(_g("duplicate field %s found"), $1));
		}
	    }
	    $self->{$1} = $2;
	    $cf = $1;
	} elsif (m/^\s(\s*\S.*)$/) {
	    my $line = $1;
	    unless (defined($cf)) {
                syntaxerr($desc, _g("continued value line not in field"));
            }
	    if ($line =~ /^\.+$/) {
		$line = substr $line, 1;
	    }
	    $self->{$cf} .= "\n$line";
	} elsif (m/^-----BEGIN PGP SIGNED MESSAGE/) {
	    $expect_pgp_sig = 1;
	    if ($$self->{'allow_pgp'}) {
		# Skip PGP headers
		while (<$fh>) {
		    last if m/^$/;
		}
	    } else {
		syntaxerr($desc, _g("PGP signature not allowed here"));
	    }
	} elsif (m/^$/ || ($expect_pgp_sig && m/^-----BEGIN PGP SIGNATURE/)) {
	    if ($expect_pgp_sig) {
		# Skip empty lines
		$_ = <$fh> while defined($_) && $_ =~ /^\s*$/;
		length($_) ||
                    syntaxerr($desc, _g("expected PGP signature, found EOF " .
                                        "after blank line"));
		s/\n$//;
		unless (m/^-----BEGIN PGP SIGNATURE/) {
		    syntaxerr($desc, sprintf(_g("expected PGP signature, " .
                                                "found something else \`%s'"), $_));
                }
		# Skip PGP signature
		while (<$fh>) {
		    last if m/^-----END PGP SIGNATURE/;
		}
		unless (defined($_)) {
                    syntaxerr($desc, _g("unfinished PGP signature"));
                }
	    }
	    last; # Finished parsing one block
	} else {
	    syntaxerr($desc,
                      _g("line with unknown format (not field-colon-value)"));
	}
    }
    return defined($cf);
}

=item $c->find_custom_field($name)

Scan the fields and look for a user specific field whose name matches the
following regex: /X[SBC]*-$name/i. Return the name of the field found or
undef if nothing has been found.

=cut

sub find_custom_field {
    my ($self, $name) = @_;
    foreach my $key (keys %$self) {
        return $key if $key =~ /^X[SBC]*-\Q$name\E$/i;
    }
    return undef;
}

=item $c->get_custom_field($name)

Identify a user field and retrieve its value.

=cut

sub get_custom_field {
    my ($self, $name) = @_;
    my $key = $self->find_custom_field($name);
    return $self->{$key} if defined $key;
    return undef;
}

=item $c->save($filename)

Write the string representation of the control information to a
file.

=item my $str = $c->output()

=item "$c"

Get a string representation of the control information. The fields
are sorted in the order in which they have been read or set except
if the order has been overridden with set_output_order().

=item $c->output($fh)

Print the string representation of the control information to a
filehandle.

=cut

sub output {
    my ($self, $fh) = @_;
    my $str = "";
    my @keys;
    if (@{$$self->{'out_order'}}) {
        my $i = 1;
        my $imp = {};
        $imp->{$_} = $i++ foreach @{$$self->{'out_order'}};
        @keys = sort {
            if (defined $imp->{$a} && defined $imp->{$b}) {
                $imp->{$a} <=> $imp->{$b};
            } elsif (defined($imp->{$a})) {
                -1;
            } elsif (defined($imp->{$b})) {
                1;
            } else {
                $a cmp $b;
            }
        } keys %$self;
    } else {
        @keys = @{$$self->{'in_order'}};
    }

    foreach my $key (@keys) {
	if (exists $self->{$key}) {
	    my $value = $self->{$key};
            # Skip whitespace-only fields
            next if $$self->{'drop_empty'} and $value !~ m/\S/;
	    # Escape data to follow control file syntax
	    my @lines = split(/\n/, $value);
	    $value = (scalar @lines) ? shift @lines : "";
	    foreach (@lines) {
		s/\s+$//;
		if (/^$/ or /^\.+$/) {
		    $value .= "\n .$_";
		} else {
		    $value .= "\n $_";
		}
	    }
	    # Print it out
            if ($fh) {
	        print $fh "$key: $value\n" ||
                    syserr(_g("write error on control data"));
            }
	    $str .= "$key: $value\n" if defined wantarray;
	}
    }
    return $str;
}

=item $c->set_output_order(@fields)

Define the order in which fields will be displayed in the output() method.

=cut

sub set_output_order {
    my ($self, @fields) = @_;

    $$self->{'out_order'} = [@fields];
}

=item $c->apply_substvars($substvars)

Update all fields by replacing the variables references with
the corresponding value stored in the Dpkg::Substvars object.

=cut

sub apply_substvars {
    my ($self, $substvars, %opts) = @_;

    # Add substvars to refer to other fields
    foreach my $f (keys %$self) {
        $substvars->set("F:$f", $self->{$f});
        $substvars->no_warn("F:$f");
    }

    foreach my $f (keys %$self) {
        my $v = $substvars->substvars($self->{$f}, %opts);
	if ($v ne $self->{$f}) {
	    # If we replaced stuff, ensure we're not breaking
	    # a dependency field by introducing empty lines, or multiple
	    # commas
	    $v =~ s/\n[ \t]*(\n|$)/$1/; # Drop empty/whitespace-only lines
	    # TODO: do this only for dependency fields
	    $v =~ s/,[\s,]*,/,/g;
	    $v =~ s/^\s*,\s*//;
	    $v =~ s/\s*,\s*$//;
	}
        $v =~ s/\$\{\}/\$/g; # XXX: what for?

        $self->{$f} = $v;
    }
}

package Dpkg::Control::Hash::Tie;

# This object is used to tie a hash. It implements hash-like functions by
# normalizing the name of fields received in keys (using
# Dpkg::Control::Fields::field_capitalize). It also stores the order in
# which fields have been added in order to be able to dump them in the
# same order. But the order information is stored in a parent object of
# type Dpkg::Control.

use Dpkg::ErrorHandling;
use Dpkg::Checksums;

use Tie::Hash;
use base qw(Tie::ExtraHash);

sub field_capitalize($) {
    my $field = lc(shift);
    # Some special cases due to history
    return "MD5sum" if $field eq "md5sum";
    return uc($field) if checksums_is_supported($field);
    # Generic case
    return join '-', map { ucfirst } split /-/, $field;
}

# $self->[0] is the real hash
# $self->[1] is an array containing the ordered list of keys
# $self->[2] is an hash describing the relative importance of each field
# (used to sort the output).

# Dpkg::Control::Hash->new($parent)
#
# Return a reference to a tied hash implementing storage of simple
# "field: value" mapping as used in many Debian-specific files.

sub new {
    my $class = shift;
    my $hash = {};
    tie %{$hash}, $class, @_;
    return $hash;
}

sub TIEHASH  {
    my ($class, $parent) = @_;
    die "Parent object must be Dpkg::Control::Hash"
        if not $parent->isa("Dpkg::Control::Hash");
    return bless [ {}, $parent ], $class;
}

sub FETCH {
    my ($self, $key) = @_;
    $key = lc($key);
    return $self->[0]->{$key} if exists $self->[0]->{$key};
    return undef;
}

sub STORE {
    my ($self, $key, $value) = @_;
    my $parent = $self->[1];
    $key = lc($key);
    if (not exists $self->[0]->{$key}) {
	push @{$$parent->{'in_order'}}, field_capitalize($key);
    }
    $self->[0]->{$key} = $value;
}

sub EXISTS {
    my ($self, $key) = @_;
    $key = lc($key);
    return exists $self->[0]->{$key};
}

sub DELETE {
    my ($self, $key) = @_;
    my $parent = $self->[1];
    my $in_order = $$parent->{'in_order'};
    $key = lc($key);
    if (exists $self->[0]->{$key}) {
	delete $self->[0]->{$key};
	@$in_order = grep { lc($_) ne $key } @$in_order;
	return 1;
    } else {
	return 0;
    }
}

sub FIRSTKEY {
    my $self = shift;
    my $parent = $self->[1];
    foreach (@{$$parent->{'in_order'}}) {
	return $_ if exists $self->[0]->{lc($_)};
    }
}

sub NEXTKEY {
    my ($self, $last) = @_;
    my $parent = $self->[1];
    my $found = 0;
    foreach (@{$$parent->{'in_order'}}) {
	if ($found) {
	    return $_ if exists $self->[0]->{lc($_)};
	} else {
	    $found = 1 if $_ eq $last;
	}
    }
    return undef;
}

1;

=back

=head1 AUTHOR

Raphaël Hertzog <hertzog@debian.org>.

=cut

1;
