1# aliases-lib.pl 2# Alias file functions 3 4# aliases_file(&config) 5# Returns the alias filenames 6sub aliases_file 7{ 8if ($config{'alias_file'}) { return [ $config{'alias_file'} ]; } 9else { 10 local(@afiles, $o); 11 foreach $o (&find_type("O", $_[0])) { 12 if ($o->{'value'} =~ /^\s*AliasFile=(.*)$/) { 13 push(@afiles, split(/,/, $1)); 14 } 15 } 16 map { s/dbm:// } @afiles; 17 return \@afiles; 18 } 19} 20 21# list_aliases(files) 22# Returns an array of data structures, each containing information about 23# one sendmail alias 24sub list_aliases 25{ 26local $jfiles = join(",", @{$_[0]}); 27local $c = $list_aliases_cache{$jfiles}; 28if (!defined($c)) { 29 $c = $list_aliases_cache{$jfiles} = [ ]; 30 local $file; 31 local @skip = split(/\s+/, $config{'alias_skip'}); 32 foreach $file (@{$_[0]}) { 33 local $lalias; 34 local $lnum = 0; 35 local $cmt; 36 &open_readfile(AFILE, $file); 37 while(<AFILE>) { 38 s/\r|\n//g; # remove newlines 39 if (/^\s*#+\s*(.*)/ && &is_table_comment($_, 1)) { 40 # A comment line 41 $cmt = &is_table_comment($_, 1); 42 } 43 elsif (/^(#*)\s*([^:$ \t]+)\s*:\s*(.*)$/) { 44 local(%alias, @values, $v); 45 $alias{'line'} = $cmt ? $lnum-1 : $lnum; 46 $alias{'eline'} = $lnum; 47 $alias{'file'} = $file; 48 $alias{'files'} = $_[0]; 49 $alias{'enabled'} = $1 ? 0 : 1; 50 $alias{'name'} = $2; 51 $alias{'cmt'} = $cmt; 52 $v = $3; 53 $alias{'value'} = $v; 54 while($v =~ /^\s*,?\s*()"([^"]+)"(.*)$/ || 55 $v =~ /^\s*,?\s*(\|)"([^"]+)"(.*)$/ || 56 $v =~ /^\s*,?\s*()([^,\s]+)(.*)$/) { 57 push(@values, $1.$2); $v = $3; 58 } 59 $alias{'values'} = \@values; 60 $alias{'num'} = scalar(@$c); 61 if (&indexof($alias{'name'}, @skip) < 0) { 62 push(@$c, \%alias); 63 $lalias = \%alias; 64 } 65 $cmt = undef; 66 } 67 elsif (/^(#*)\s+(\S.*)$/ && $lalias && 68 ($1 && !$lalias->{'enabled'} || 69 !$1 && $lalias->{'enabled'})) { 70 # continuation of last alias 71 $lalias->{'eline'} = $lnum; 72 local $v = $2; 73 $lalias->{'value'} .= $v; 74 while($v =~ /^\s*,?\s*()"([^"]+)"(.*)$/ || 75 $v =~ /^\s*,?\s*(\|)"([^"]+)"(.*)$/ || 76 $v =~ /^\s*,?\s*()([^,\s]+)(.*)$/) { 77 push(@{$lalias->{'values'}}, $1.$2); $v = $3; 78 } 79 $cmt = undef; 80 } 81 else { 82 # Some other line 83 $lalias = undef; 84 $cmt = undef; 85 } 86 $lnum++; 87 } 88 close(AFILE); 89 } 90 } 91return @$c; 92} 93 94# alias_form([alias], [no-comment]) 95# Display a form for editing or creating an alias. Each alias can map to 96# 1 or more programs, files, lists or users 97sub alias_form 98{ 99local ($a, $nocmt, $afile) = @_; 100local (@values, $v, $type, $val, @typenames); 101if ($a) { @values = @{$a->{'values'}}; } 102@typenames = map { $text{"aform_type$_"} } (0 .. 6); 103$typenames[0] = "<$typenames[0]>"; 104 105# Start of form and table 106print &ui_form_start("save_alias.cgi", "post"); 107if ($a) { 108 print &ui_hidden("num", $a->{'num'}),"\n"; 109 } 110else { 111 print &ui_hidden("new", 1),"\n"; 112 } 113print &ui_table_start($a ? $text{'aform_edit'} 114 : $text{'aform_create'}, undef, 2); 115 116# Description 117if (!$nocmt) { 118 print &ui_table_row(&hlink($text{'aform_cmt'},"alias_cmt"), 119 &ui_textbox("cmt", $a ? $a->{'cmt'} : undef, 50)); 120 } 121 122 123# Alias name 124print &ui_table_row(&hlink($text{'aform_name'},"alias_name"), 125 &ui_textbox("name", $a ? $a->{'name'} : "", 20)); 126 127# Enabled flag 128print &ui_table_row(&hlink($text{'aform_enabled'}, "alias_enabled"), 129 &ui_yesno_radio("enabled", !$a || $a->{'enabled'} ? 1 : 0)); 130 131# Alias file, if more than one possible 132if ($afile && @$afile > 1) { 133 print &ui_table_row(&hlink($text{'aform_file'}, "alias_file"), 134 &ui_select("afile", undef, $afile)); 135 } 136 137# Destinations 138local @typeopts; 139for($j=0; $j<@typenames; $j++) { 140 if (!$j || $access{"aedit_$j"}) { 141 push(@typeopts, [ $j, $typenames[$j] ]); 142 } 143 } 144for($i=0; $i<=@values; $i++) { 145 ($type, $val) = $values[$i] ? &alias_type($values[$i]) : (0, ""); 146 147 local $typesel = &ui_select("type_$i", $type, \@typeopts); 148 local $valtxt = &ui_textbox("val_$i", $val, 30); 149 local $edlnk; 150 if ($type == 2 && $a) { 151 $edlnk = &ui_link("edit_afile.cgi?file=$val&num=$a->{'num'}",$text{'aform_afile'}); 152 } 153 elsif ($type == 5 && $a) { 154 $edlnk = &ui_link("edit_rfile.cgi?file=$val&num=$a->{'num'}",$text{'aform_afile'}); 155 } 156 elsif ($type == 6 && $a) { 157 $edlnk = &ui_link("edit_ffile.cgi?file=$val&num=$a->{'num'}",$text{'aform_afile'}); 158 } 159 print &ui_table_row(&hlink($text{'aform_val'},"alias_to"), 160 $typesel."\n".$valtxt."\n".$edlnk); 161 } 162 163# Table and form end 164print &ui_table_end(); 165if ($a) { 166 print &ui_form_end([ [ "save", $text{'save'} ], 167 [ "delete", $text{'delete'} ] ]); 168 } 169else { 170 print &ui_form_end([ [ "create", $text{'create'} ] ]); 171 } 172} 173 174# create_alias(&details, &files, [norebuild]) 175# Create a new alias 176sub create_alias 177{ 178&list_aliases($_[1]); # force cache init 179 180# Update the config file 181local(%aliases); 182$_[0]->{'file'} ||= $_[1]->[0]; 183local $lref = &read_file_lines($_[0]->{'file'}); 184$_[0]->{'line'} = scalar(@$lref); 185push(@$lref, &make_table_comment($_[0]->{'cmt'}, 1)); 186local $str = ($_[0]->{'enabled'} ? "" : "# ") . $_[0]->{'name'} . ": " . 187 join(',', map { /\s/ ? "\"$_\"" : $_ } @{$_[0]->{'values'}}); 188push(@$lref, $str); 189$_[0]->{'eline'} = scalar(@$lref)-1; 190&flush_file_lines($_[0]->{'file'}); 191if (!$_[2]) { 192 if (!&rebuild_map_cmd($_[0]->{'file'})) { 193 &system_logged("newaliases >/dev/null 2>&1"); 194 } 195 } 196 197# Add to the cache 198local $jfiles = join(",", @{$_[1]}); 199local $c = $list_aliases_cache{$jfiles}; 200$_[0]->{'num'} = scalar(@$c); 201push(@$c, $_[0]); 202} 203 204# delete_alias(&details, [norebuild]) 205# Deletes one mail alias 206sub delete_alias 207{ 208# Remove from the file 209local $lref = &read_file_lines($_[0]->{'file'}); 210local $len = $_[0]->{'eline'} - $_[0]->{'line'} + 1; 211splice(@$lref, $_[0]->{'line'}, $len); 212&flush_file_lines($_[0]->{'file'}); 213if (!$_[1]) { 214 if (!&rebuild_map_cmd($_[0]->{'file'})) { 215 &system_logged("newaliases >/dev/null 2>&1"); 216 } 217 } 218 219# Remove from the cache 220local $jfiles = join(",", @{$_[0]->{'files'}}); 221local $c = $list_aliases_cache{$jfiles}; 222local $idx = &indexof($_[0], @$c); 223splice(@$c, $idx, 1) if ($idx != -1); 224&renumber_list($c, $_[0], -$len); 225} 226 227# modify_alias(&old, &details, [norebuild]) 228# Update some existing alias 229sub modify_alias 230{ 231# Add to the file 232local @newlines; 233push(@newlines, &make_table_comment($_[1]->{'cmt'}, 1)); 234local $str = ($_[1]->{'enabled'} ? "" : "# ") . $_[1]->{'name'} . ": " . 235 join(',', map { /\s/ ? "\"$_\"" : $_ } @{$_[1]->{'values'}}); 236push(@newlines, $str); 237local $lref = &read_file_lines($_[0]->{'file'}); 238local $len = $_[0]->{'eline'} - $_[0]->{'line'} + 1; 239splice(@$lref, $_[0]->{'line'}, $len, @newlines); 240&flush_file_lines($_[0]->{'file'}); 241if (!$_[2]) { 242 if (!&rebuild_map_cmd($_[0]->{'file'})) { 243 &system_logged("newaliases >/dev/null 2>&1"); 244 } 245 } 246 247local $jfiles = join(",", @{$_[0]->{'files'}}); 248local $c = $list_aliases_cache{$jfiles}; 249local $idx = &indexof($_[0], @$c); 250$_[1]->{'file'} = $_[0]->{'file'}; 251$_[1]->{'line'} = $_[0]->{'line'}; 252$_[1]->{'eline'} = $_[1]->{'line'}+scalar(@newlines)-1; 253$c->[$idx] = $_[1] if ($idx != -1); 254&renumber_list($c, $_[0], scalar(@newlines) - $len); 255} 256 257# alias_type(string) 258# Return the type and destination of some alias string 259sub alias_type 260{ 261local @rv; 262if ($_[0] =~ /^\|$module_config_directory\/autoreply.pl\s+(\S+)/) { 263 @rv = (5, $1); 264 } 265elsif ($_[0] =~ /^\|$module_config_directory\/filter.pl\s+(\S+)/) { 266 @rv = (6, $1); 267 } 268elsif ($_[0] =~ /^\|(.*)$/) { 269 @rv = (4, $1); 270 } 271elsif ($_[0] =~ /^(\/.*)$/) { 272 @rv = (3, $1); 273 } 274elsif ($_[0] =~ /^:include:"(.*)"$/ || $_[0] =~ /^:include:(.*)$/) { 275 @rv = (2, $1); 276 } 277else { 278 @rv = (1, $_[0]); 279 } 280return wantarray ? @rv : $rv[0]; 281} 282 283# lock_alias_files(&files) 284sub lock_alias_files 285{ 286foreach $f (@{$_[0]}) { 287 &lock_file($f); 288 } 289} 290 291# unlock_alias_files(&files) 292sub unlock_alias_files 293{ 294foreach $f (@{$_[0]}) { 295 &unlock_file($f); 296 } 297} 298 299# can_edit_alias(&alias) 300sub can_edit_alias 301{ 302local ($a) = @_; 303foreach my $v (@{$a->{'values'}}) { 304 $access{"aedit_".&alias_type($v)} || return 0; 305 } 306if ($access{'amode'} == 2) { 307 $a->{'name'} =~ /$access{'aliases'}/ || return 0; 308 } 309elsif ($access{'amode'} == 3) { 310 $a->{'name'} eq $remote_user || return 0; 311 } 312return 1; 313} 314 3151; 316 317