# aliases-lib.pl
# Alias file functions

# aliases_file(&config)
# Returns the alias filenames
sub aliases_file
{
if ($config{'alias_file'}) { return [ $config{'alias_file'} ]; }
else {
	local(@afiles, $o);
	foreach $o (&find_type("O", $_[0])) {
		if ($o->{'value'} =~ /^\s*AliasFile=(.*)$/) {
			push(@afiles, split(/,/, $1));
			}
		}
	map { s/dbm:// } @afiles;
	return \@afiles;
	}
}

# list_aliases(files)
# Returns an array of data structures, each containing information about
# one sendmail alias
sub list_aliases
{
local($lnum, @rv, $file, $lalias);
local @skip = split(/\s+/, $config{'alias_skip'});
foreach $file (@{$_[0]}) {
	$lnum = 0;
	open(AFILE, $file);
	while(<AFILE>) {
		s/\r|\n//g;	# remove newlines
		if (/^(#*)\s*([^:$ \t]+)\s*:\s*(.*)$/) {
			local(%alias, @values, $v);
			$alias{'eline'} = $alias{'line'} = $lnum;
			$alias{'file'} = $file;
			$alias{'enabled'} = $1 ? 0 : 1;
			$alias{'name'} = $2;
			$v = $alias{'value'} = $3;
			while($v =~ /^\s*,?\s*()"([^"]+)"(.*)$/ ||
			      $v =~ /^\s*,?\s*(\|)"([^"]+)"(.*)$/ ||
			      $v =~ /^\s*,?\s*()([^,\s]+)(.*)$/) {
				push(@values, $1.$2); $v = $3;
				}
			$alias{'values'} = \@values;
			$alias{'num'} = scalar(@rv);
			if (&indexof($alias{'name'}, @skip) < 0) {
				push(@rv, \%alias);
				$lalias = \%alias;
				}
			}
		elsif (/^(#*)\s+(\S.*)$/ && $lalias &&
		       ($1 && !$lalias->{'enabled'} ||
			!$1 && $lalias->{'enabled'})) {
			# continuation of last alias
			$lalias->{'eline'} = $lnum;
			local $v = $2;
			$lalias->{'value'} .= $v;
			while($v =~ /^\s*,?\s*()"([^"]+)"(.*)$/ ||
			      $v =~ /^\s*,?\s*(\|)"([^"]+)"(.*)$/ ||
			      $v =~ /^\s*,?\s*()([^,\s]+)(.*)$/) {
				push(@{$lalias->{'values'}}, $1.$2); $v = $3;
				}
			}
		else { $lalias = undef; }
		$lnum++;
		}
	close(AFILE);
	}
return @rv;
}

# alias_form([alias])
# Display a form for editing or creating an alias. Each alias can map to
# 1 or more programs, files, lists or users
sub alias_form
{
local($a, @values, $v, $type, $val, @typenames);
$a = $_[0];
if ($a) { @values = @{$a->{'values'}}; }
@typenames = map { $text{"aform_type$_"} } (0 .. 6);
$typenames[0] = "&lt;$typenames[0]&gt;";

print "<form method=post action=save_alias.cgi>\n";
if ($a) { print "<input type=hidden name=num value=$a->{'num'}>\n"; }
else { print "<input type=hidden name=new value=1>\n"; }
print "<table border>\n";
print "<tr $tb> <td><b>",$a ? $text{'aform_edit'}
			    : $text{'aform_create'},"</b></td> </tr>\n";
print "<tr $cb> <td><table>\n";
print "<tr> <td>",&hlink("<b>$text{'aform_name'}</b>","alias_name"),"</td>\n";
printf "<td><input name=name size=20 value=\"%s\"></td> </tr>\n",
	$a ? $a->{'name'} : "";
print "<tr> <td>",&hlink("<b>$text{'aform_enabled'}</b>",
			 "alias_enabled"),"</td>\n";
printf "<td><input type=radio name=enabled value=1 %s> $text{'yes'}\n",
	!$a || $a->{'enabled'} ? "checked" : "";
printf "<input type=radio name=enabled value=0 %s> $text{'no'}</td> </tr>\n",
	!$a || $a->{'enabled'} ? "" : "checked";
for($i=0; $i<=@values; $i++) {
	($type, $val) = $values[$i] ? &alias_type($values[$i]) : (0, "");
	print "<tr> <td valign=top>",
	      &hlink("<b>$text{'aform_val'}</b>","alias_to"),"</td>\n";
	print "<td><select name=type_$i>\n";
	for($j=0; $j<@typenames; $j++) {
		if (!$j || $access{"aedit_$j"}) {
			printf "<option value=$j %s>$typenames[$j]\n",
				$type == $j ? "selected" : "";
			}
		}
	print "</select>\n";
	print "<input name=val_$i size=30 value=\"$val\">\n";
	if ($type == 2 && $a) {
		print "<a href='edit_afile.cgi?file=$val&num=$a->{'num'}'>",
		      "$text{'aform_afile'}</a>\n";
		}
	elsif ($type == 5 && $a) {
		print "<a href='edit_rfile.cgi?file=$val&num=$a->{'num'}'>",
		      "$text{'aform_afile'}</a>\n";
		}
	elsif ($type == 6 && $a) {
		print "<a href='edit_ffile.cgi?file=$val&num=$a->{'num'}'>",
		      "$text{'aform_afile'}</a>\n";
		}
	print "</td> </tr>\n";
	}
print "<tr> <td colspan=2 align=right>\n";
if ($a) {
	print "<input type=submit value=$text{'save'}>\n";
	print "<input type=submit name=delete value=$text{'delete'}>\n";
	}
else { print "<input type=submit value=$text{'create'}>\n"; }
print "</td> </tr>\n";
print "</table></td></tr></table></form>\n";
}

# create_alias(&details, files, [norebuild])
# Create a new alias
sub create_alias
{
local(%aliases);
open(AFILE, ">>".$_[1]->[0]);
print AFILE $_[0]->{'enabled'} ? "" : "# ", $_[0]->{'name'}, ": ",
	    join(',', map { /\s/ ? "\"$_\"" : $_ } @{$_[0]->{'values'}}),"\n";
close(AFILE);
&system_logged("newaliases >/dev/null 2>&1") if (!$_[2]);
}

# delete_alias(&details)
sub delete_alias
{
local $lref = &read_file_lines($_[0]->{'file'});
local $len = $_[0]->{'eline'} - $_[0]->{'line'} + 1;
splice(@$lref, $_[0]->{'line'}, $len);
&flush_file_lines();
&system_logged("newaliases >/dev/null 2>&1");
}

# modify_alias(&old, &details)
# Update some existing alias
sub modify_alias
{
local $str = ($_[1]->{'enabled'} ? "" : "# ") . $_[1]->{'name'} . ": " .
	     join(',', map { /\s/ ? "\"$_\"" : $_ } @{$_[1]->{'values'}});
local $lref = &read_file_lines($_[0]->{'file'});
local $len = $_[0]->{'eline'} - $_[0]->{'line'} + 1;
splice(@$lref, $_[0]->{'line'}, $len, $str);
&flush_file_lines();
&system_logged("newaliases >/dev/null 2>&1");
}

# alias_type(string)
# Return the type and destination of some alias string
sub alias_type
{
local @rv;
if ($_[0] =~ /^\|$module_config_directory\/autoreply.pl\s+(\S+)/) {
	@rv = (5, $1);
	}
elsif ($_[0] =~ /^\|$module_config_directory\/filter.pl\s+(\S+)/) {
	@rv = (6, $1);
	}
elsif ($_[0] =~ /^\|(.*)$/) {
	@rv = (4, $1);
	}
elsif ($_[0] =~ /^(\/.*)$/) {
	@rv = (3, $1);
	}
elsif ($_[0] =~ /^:include:(.*)$/) {
	@rv = (2, $1);
	}
else {
	@rv = (1, $_[0]);
	}
return wantarray ? @rv : $rv[0];
}

# lock_alias_files(&files)
sub lock_alias_files
{
foreach $f (@{$_[0]}) {
	&lock_file($f);
	}
}

# unlock_alias_files(&files)
sub unlock_alias_files
{
foreach $f (@{$_[0]}) {
	&unlock_file($f);
	}
}

1;

