package fs::remote::davfs; # $Id: smb.pm 231184 2007-10-24 14:36:29Z pixel $

use strict;
use diagnostics;

use common;
use fs::mount_options;

sub secrets_file() { "$::prefix/etc/davfs2/secrets" }

sub fstab_entry_to_credentials {
    my ($part) = @_;    

    my ($options, $unknown) = fs::mount_options::unpack($part);
    my %h = map { $_ => delete $options->{"$_="} } qw(username password);
    foreach (qw(username password)) {
        $h{$_} ||= 'nobody';
    }
    $h{mntpoint} = $part->{mntpoint} or return;
    fs::mount_options::pack_($part, $options, $unknown), \%h;
}

sub save_credentials {
    my ($credentials) = @_;
    @$credentials or return;

    output_with_perm(secrets_file(), 0600, 
		     map { to_double_quoted($_->{mntpoint}, $_->{username}, $_->{password}, $_->{comment}) . "\n" } @$credentials);
}

sub mountpoint_credentials_save {
    my ($mntpoint, $mount_opt) = @_;
    my @entries = read_credentials_raw();
    my $entry = find { $mntpoint eq $_->{mntpoint} } @entries;
    die "mountpoint not found" if !$entry;
    my %h;
    foreach (@$mount_opt) {
        my @var = split(/=/);
        $h{$var[0]} = $var[1];
    }
    foreach my $key (qw(username password)) {
        $entry->{$key} = $h{$key};
    }
    save_credentials(\@entries);
}


sub read_credentials_raw() {
    from_double_quoted(cat_(secrets_file()));
}

sub read_credentials {
    my ($mntpoint) = @_;
    find { $mntpoint eq $_->{mntpoint} } read_credentials_raw();
}

# Comments are indicated by a '#' character and the rest of the line
# is ignored. Empty lines are ignored too.
#
# Each line consists of two or three items separated by spaces or tabs.
# If an item contains one of the characters space, tab, #, \ or ", this
# character must be escaped by a preceding \. Alternatively, the item
# may be enclosed in double quotes.

sub from_double_quoted {
    my ($file) = @_;
    my @l;
    my @lines = split("\n",$file);
    foreach (@lines) {
	my ($mnt, $user, $pass, $comment); 
	if (/^\s*(#.*)?$/) {
	    $comment = $1;
	} else {
            if (/^(?:"((?:\\.|[^"])*)"|((?:\\.|[^"\s#])+))\s+(?:"((?:\\.|[^"])*)"|((?:\\.|[^"\s#])+))(?:\s+(?:"((?:\\.|[^"])*)"|((?:\\.|[^"\s#])+)))?(?:\s*|\s*(#.*))?$/) {
	            $mnt = "$1$2";
		    $mnt =~ s/\\(.)/$1/g;
		    $user = "$3$4";
	            $user =~ s/\\(.)/$1/g;
		    $pass = "$5$6";
	            $pass =~ s/\\(.)/$1/g;
		    $comment=$7;
	    } else {
		    die "bad entry $_";
	    }
        }
        push @l, { 'mntpoint' => $mnt, 'username' => $user, 'password' => $pass, 'comment' => $comment };
    }
    @l;
}

sub to_double_quoted {
    my (@l) = @_;
    join(' ', map {
	s/(["\\])/\\$1/g;
	/\s/ ? qq("$_") : $_;
    } @l);
}

1;