spam/ 0040775 0005671 0000012 00000000000 07752335027 011516 5 ustar jcameron wheel spam/module.info 0100664 0005671 0000012 00000000247 07752676232 013666 0 ustar jcameron wheel name=SpamAssassin
desc=SpamAssassin Mail Filter
category=mail
longdesc=Set up and configure SpamAssassin to filter email sent to your account.
usermin=1
version=1.052
spam/config.info 0100664 0005671 0000012 00000001627 07736402611 013637 0 ustar jcameron wheel local_cf=Users' SpamAssassin configuration file,0
avail_icons=Icons available to users,13,white-Allowed and Denied Addresses,score-Spam Classification,report-Message Modification,user-Miscellaneous User Options,header-Header and Body Tests,setup-Setup Procmail For SpamAssassin,mail-Read Spam mail
warn_procmail=Warn users if SpamAssassin is not set up?,1,1-Yes,0-No
index_spam=Build index for spam folder,1,1-Yes,0-No
global_cf=System-wide SpamAssassin configuration file,0
show_global=Display global allowed and denied addresses to users?,1,1-Yes,0-No
spamassassin=Full path to SpamAssassin command,0
procmail_cmd=SpamAssassin command for Procmail configuration,3,Just run spamassassin
procmailrc=Personal Procmail configuration file,3,From Procmail module
global_procmailrc=System-wide Procmail configuration file,0
call_spam=Add call to SpamAssassin to procmail configuration when setting up?,1,1-Yes,0-No
spam/edit_setup.cgi 0100775 0005671 0000012 00000002700 07705401056 014340 0 ustar jcameron wheel #!/usr/local/bin/perl
# edit_setup.cgi
# Display a form for setting up SpamAssassin, either locally or globally
require './spam-lib.pl';
&can_use_check("setup");
&header($text{'setup_title'}, "");
print "
\n";
&foreign_require("procmail", "procmail-lib.pl");
@pmrcs = &get_procmailrc();
$pmrc = $pmrcs[$#pmrcs];
if ($module_info{'usermin'}) {
print "",&text('setup_desc_usermin', "$pmrc "),"
\n";
}
else {
print "
",&text('setup_desc_webmin', "$pmrc "),"
\n";
}
print "
\n";
print " \n";
&footer("", $text{'index_return'});
spam/import.cgi 0100775 0005671 0000012 00000002406 07747562270 013524 0 ustar jcameron wheel #!/usr/local/bin/perl
# import.cgi
# Add email addresses to the allowed list
require './spam-lib.pl';
&ReadParseMime();
$in{'import'} || &error($text{'import_efile'});
# Parse the file
while($in{'import'} =~ s/((([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,})+)))//) {
push(@addrs, $1);
}
@addrs || &error($text{'import_enone'});
@addrs = &unique(@addrs);
&lock_spam_files();
$conf = &get_config();
@from = map { @{$_->{'words'}} } &find("whitelist_from", $conf);
%already = map { $_, 1 } @from;
@newaddrs = grep { !$already{$_} } @addrs;
&header($text{'import_title'}, "");
print " \n";
if (@newaddrs) {
print "",&text('import_ok1', scalar(@newaddrs),
scalar(@addrs)),"
\n";
push(@from, @newaddrs);
if ($in{'sort'}) {
@from = sort { ($ua, $da) = split(/\@/, $a);
($ub, $db) = split(/\@/, $b);
lc($da) cmp lc($db) || lc($ua) cmp lc($ub) }
@from;
}
&save_directives($conf, 'whitelist_from', \@from, 1);
&flush_file_lines();
}
else {
print "
",&text('import_ok2', scalar(@addrs)),"
\n";
}
&webmin_log("import", scalar(@newaddrs));
&unlock_spam_files();
print "
\n";
&footer("edit_white.cgi", $text{'white_return'});
spam/view_mail.cgi 0100755 0005671 0000012 00000020023 07730211552 014141 0 ustar jcameron wheel #!/usr/local/bin/perl
# view_mail.cgi
# View a single email message
require './spam-lib.pl';
&foreign_require("mailbox", "mailbox-lib.pl");
$folder = &spam_file_folder();
&disable_indexing($folder);
$force_charset = '';
&ReadParse();
&header($mailbox::text{'view_title'}, "");
@mail = &mailbox::mailbox_list_mails($in{'idx'}, $in{'idx'}, $folder);
$mail = $mail[$in{'idx'}];
&mailbox::parse_mail($mail);
@sub = split(/\0/, $in{'sub'});
$subs = join("", map { "&sub=$_" } @sub);
foreach $s (@sub) {
# We are looking at a mail within a mail ..
&mailbox::decrypt_attachments($mail);
local $amail = &mailbox::extract_mail($mail->{'attach'}->[$s]->{'data'});
&mailbox::parse_mail($amail);
$mail = $amail;
}
dbmopen(%read, "$user_config_directory/mailbox/read", 0600);
if ($mailbox::userconfig{'auto_mark'}) {
eval { $read{$mail->{'header'}->{'message-id'}} = 1 }
if (!$read{$mail->{'header'}->{'message-id'}});
}
print "\n";
if (!@sub) {
if ($in{'idx'}) {
print "",
" \n";
}
print "",&mailbox::text('view_desc', $in{'idx'}+1,
$folder->{'name'})," \n";
if ($in{'idx'} < @mail-1) {
print "",
" \n";
}
}
else {
print "$text{'view_sub'} \n";
}
print " \n";
print " \n";
# Check for encryption
($deccode, $decmessage) = &mailbox::decrypt_attachments($mail);
@attach = @{$mail->{'attach'}};
# Find body attachment and type
($textbody, $htmlbody, $body) = &mailbox::find_body($mail);
# XXX look for text/calendar body
# Check for signing
if (&has_command("gpg") && &foreign_check("gnupg")) {
# Check for GnuPG signatures
local $sig;
foreach $a (@attach) {
$sig = $a if ($a->{'type'} =~ /^application\/pgp-signature/);
}
if ($sig) {
# Verify the signature against the rest of the attachment
&foreign_require("gnupg", "gnupg-lib.pl");
local $rest = $sig->{'parent'}->{'attach'}->[0];
$rest->{'raw'} =~ s/\r//g;
$rest->{'raw'} =~ s/\n/\r\n/g;
($sigcode, $sigmessage) = &foreign_call("gnupg",
"verify_data", $rest->{'raw'}, $sig->{'data'});
@attach = grep { $_ ne $sig } @attach;
}
elsif ($body && $body eq $textbody && $body->{'data'} =~ /(-+BEGIN PGP SIGNED MESSAGE-+\n(Hash:\s+(\S+)\n\n)?([\000-\377]+\n)-+BEGIN PGP SIGNATURE-+\n([\000-\377]+)-+END PGP SIGNATURE-+\n)/i) {
# Signature is in body text!
local $sig = $1;
local $text = $4;
&foreign_require("gnupg", "gnupg-lib.pl");
($sigcode, $sigmessage) = &foreign_call("gnupg",
"verify_data", $sig);
if ($sigcode == 0 || $sigcode == 1) {
# XXX what about replying?
$body->{'data'} = $text;
}
}
}
# Strip out attachments not to display as icons
@attach = grep { $_ ne $body } @attach;
@attach = grep { !$_->{'attach'} } @attach;
print "\n";
print " \n";
print " \n";
if ($in{'headers'}) {
# Show all the headers
if ($mail->{'fromline'}) {
print " $text{'mail_rfc'} ",
"",&mailbox::eucconv(&html_escape($mail->{'fromline'})),
" \n";
}
foreach $h (@{$mail->{'headers'}}) {
print " $h->[0]: ",
"",&mailbox::eucconv(&html_escape(&mailbox::decode_mimewords($h->[1]))),
" \n";
}
}
else {
# Just show the most useful headers
print " $mailbox::text{'mail_from'} ",
"",&address_link($mail->{'header'}->{'from'})," \n";
print " $mailbox::text{'mail_to'} ",
"",&address_link($mail->{'header'}->{'to'})," \n";
print " $mailbox::text{'mail_cc'} ",
"",&address_link($mail->{'header'}->{'cc'})," \n"
if ($mail->{'header'}->{'cc'});
print " $mailbox::text{'mail_date'} ",
"",&mailbox::eucconv(&html_escape($mail->{'header'}->{'date'})),
" \n";
print " $mailbox::text{'mail_subject'} ",
"",&mailbox::eucconv(&html_escape(&mailbox::decode_mimewords(
$mail->{'header'}->{'subject'})))," \n";
if (!@sub) {
print " $text{'mail_level2'} ",
"",length($mail->{'header'}->{'x-spam-level'})," \n";
}
}
print "
\n";
# Show body attachment, with properly linked URLs
if ($body && $body->{'data'} =~ /\S/) {
if ($body eq $textbody) {
# Show plain text
print "
\n";
foreach $l (&mailbox::wrap_lines($body->{'data'},
$mailbox::userconfig{'wrap_width'})) {
print &mailbox::link_urls_and_escape($l),"\n";
}
print "
\n";
}
elsif ($body eq $htmlbody) {
# Attempt to show HTML
print "
\n";
print &mailbox::safe_html($body->{'data'});
print "
\n";
}
}
# Display other attachments
if (@attach) {
print "
\n";
print " $mailbox::text{'view_attach'} \n";
print " \n";
foreach $a (@attach) {
local $fn;
$size = (int(length($a->{'data'})/1000)+1)." Kb";
local $cb;
if ($a->{'type'} eq 'message/rfc822') {
push(@titles, "$mailbox::text{'view_sub'} $size");
}
elsif ($a->{'filename'}) {
push(@titles, &mailbox::decode_mimewords($a->{'filename'}).
" $size");
$fn = &mailbox::decode_mimewords($a->{'filename'});
push(@detach, [ $a->{'idx'}, $fn ]);
}
else {
push(@titles, "$a->{'type'} $size");
$a->{'type'} =~ /\/(\S+)$/;
$fn = "file.$1";
push(@detach, [ $a->{'idx'}, $fn ]);
}
$fn =~ s/ /_/g;
$fn =~ s/\#/_/g;
$fn = &html_escape($fn);
if ($a->{'type'} eq 'message/rfc822') {
push(@links, "view_mail.cgi?idx=$in{'idx'}$subs&sub=$a->{'idx'}");
}
else {
push(@links, "detach.cgi/$fn?idx=$in{'idx'}&attach=$a->{'idx'}$subs");
}
push(@icons, "/mailbox/images/boxes.gif");
}
&icons_table(\@links, \@titles, \@icons, 8);
print "
\n";
}
# Display GnuPG results
if (defined($sigcode)) {
print "
\n";
print " $text{'view_gnupg'} \n";
print " ";
$sigmessage = &html_escape($sigmessage);
$sigmessage = $sigmessage if ($sigcode == 4);
print &mailbox::text('view_gnupg_'.$sigcode, $sigmessage),"\n";
if ($sigcode == 3) {
local $url = "/$module_name/view_mail.cgi?idx=$in{'idx'}&folder=$in{'folder'}$subs";
print "",&mailbox::text('view_recv', $sigmessage, "/gnupg/recv.cgi?id=$sigmessage&return=".&urlize($url)."&returnmsg=".&urlize($text{'view_return'})),"\n";
}
print "
\n";
}
if ($deccode) {
print "
\n";
print " $text{'view_crypt'} \n";
print " ";
print &mailbox::text('view_crypt_'.$deccode, "$decmessage ");
print "
\n";
}
print "\n";
dbmclose(%read);
print "
\n";
local @sr = !@sub ? ( ) :
( "view_mail.cgi?idx=$in{'idx'}", $mailbox::text{'view_return'} ),
$s = int((@mail - $in{'idx'} - 1) / $mailbox::userconfig{'perpage'}) *
$mailbox::userconfig{'perpage'};
&footer(@sub ? ( "view_mail.cgi?idx=$in{'idx'}",
$mailbox::text{'view_return'} ) : ( ),
"mail.cgi", $text{'mail_return'});
# address_link(address)
sub address_link
{
local @addrs = &mailbox::split_addresses(&mailbox::decode_mimewords($_[0]));
local @rv;
foreach $a (@addrs) {
push(@rv, &html_escape($a->[2]));
}
return join(" , ", @rv);
}
spam/spam-lib.pl 0100664 0005671 0000012 00000022141 07747557012 013560 0 ustar jcameron wheel # spam-lib.pl
# Common functions for parsing and editing the spamassassin config file
# XXX online help
# XXX whitelist editing?
do '../web-lib.pl';
&init_config();
$local_cf = $config{'local_cf'};
if ($module_info{'usermin'}) {
&switch_to_remote_user();
&create_user_config_dirs();
if ($local_cf !~ /^\//) {
$local_cf = "$remote_user_info[7]/$local_cf";
if ($local_cf =~ /^(.*)\// && !-d $1) {
mkdir($1, 0700);
}
}
}
$add_cf = !-d $local_cf ? $local_cf :
$module_info{'usermin'} ? "$local_cf/user_prefs" :
"$local_cf/local.cf";
# get_config([file])
# Return a structure containing the contents of the spamassassin config file
sub get_config
{
local @rv;
local $lnum = 0;
local $file = $_[0] || $local_cf;
if (-d $file) {
# A directory of files - read them all
opendir(DIR, $file);
local @files = sort { $a cmp $b } readdir(DIR);
closedir(DIR);
local $f;
foreach $f (@files) {
if ($f =~ /\.cf$/) {
local $add = &get_config("$file/$f");
map { $_->{'index'} += scalar(@rv) } @$add;
push(@rv, @$add);
}
}
}
else {
# A single file that can be read right here
open(FILE, $file);
while() {
s/\r|\n//g;
s/^#.*$//;
if (/^(\S+)\s*(.*)$/) {
local $dir = { 'name' => $1,
'value' => $2,
'index' => scalar(@rv),
'file' => $file,
'line' => $lnum };
$dir->{'words'} = [ split(/\s+/, $dir->{'value'}) ];
push(@rv, $dir);
}
$lnum++;
}
close(FILE);
}
return \@rv;
}
# find(name, &config)
sub find
{
local @rv;
foreach $c (@{$_[1]}) {
push(@rv, $c) if (lc($c->{'name'}) eq lc($_[0]));
}
return wantarray ? @rv : $rv[0];
}
# find_value(name, &config)
sub find_value
{
local @rv = map { $_->{'value'} } &find(@_);
return wantarray ? @rv : $rv[0];
}
# save_directives(&config, name|&old, &new, valuesonly)
# Update the config file with some directives
sub save_directives
{
local @old = ref($_[1]) ? @{$_[1]} : &find($_[1], $_[0]);
local @new = $_[3] ? &make_directives($_[1], $_[2]) : @{$_[2]};
local $i;
for($i=0; $i<@old || $i<@new; $i++) {
local $line;
if ($new[$i]) {
$line = $new[$i]->{'name'};
$line .= " ".$new[$i]->{'value'} if ($new[$i]->{'value'} ne '');
}
if ($old[$i] && $new[$i]) {
# Replacing a directive
local $lref = &read_file_lines($old[$i]->{'file'});
$lref->[$old[$i]->{'line'}] = $line;
$_[0]->[$old[$i]->{'index'}] = $new[$i];
}
elsif ($old[$i]) {
# Deleting a directive
local $lref = &read_file_lines($old[$i]->{'file'});
splice(@$lref, $old[$i]->{'line'}, 1);
splice(@{$_[0]}, $old[$i]->{'index'}, 1);
foreach $c (@{$_[0]}) {
$c->{'line'}-- if ($c->{'line'} > $old[$i]->{'line'} &&
$c->{'file'} eq $old[$i]->{'file'});
$c->{'index'}-- if ($c->{'index'} > $old[$i]->{'index'});
}
}
elsif ($new[$i]) {
# Adding a directive
local $lref = &read_file_lines($add_cf);
$new[$i]->{'line'} = @$lref;
$new[$i]->{'index'} = @{$_[0]};
push(@$lref, $line);
push(@{$_[0]}, $new[$i]);
}
}
}
# make_directives(name, &values)
sub make_directives
{
return map { { 'name' => $_[0],
'value' => $_ } } @{$_[1]};
}
### UI functions ###
# edit_table(name, &headings, &&values, &sizes, [&convfunc], blankrows)
# Display a table of values for editing, with one blank row
sub edit_table
{
local ($h, $v);
print "\n";
print "\n";
foreach $h (@{$_[1]}) {
print "$h \n";
}
print " \n";
local $i = 0;
local $cfunc = $_[4] || \&default_convfunc;
local $blanks = $_[5] || 1;
foreach $v (@{$_[2]}, map { [ ] } (1 .. $blanks)) {
print "\n";
for($j=0; $j<@{$_[1]}; $j++) {
print "",&$cfunc($j, "$_[0]_${i}_${j}", $_[3]->[$j],
$v->[$j], $v)," ";
}
print " \n";
$i++;
}
print "
\n";
}
# default_convfunc(column, name, size, value)
sub default_convfunc
{
return " ";
}
# parse_table(name, &parser)
# Parse the inputs from a table and return an array of results
sub parse_table
{
local ($i, @rv);
local $pfunc = $_[1] || \&default_parsefunc;
for($i=0; defined($in{"$_[0]_${i}_0"}); $i++) {
local ($j, $v, @vals);
for($j=0; defined($v = $in{"$_[0]_${i}_${j}"}); $j++) {
push(@vals, $v);
}
local $p = &$pfunc("$_[0]_${i}", @vals);
push(@rv, $p) if (defined($p));
}
return @rv;
}
# default_parsefunc(rowname, value, ...)
# Returns a value or undef if empty, or calls &error if invalid
sub default_parsefunc
{
return $_[1] ? join(" ", @_[1..$#_]) : undef;
}
# start_form(cgi, header)
sub start_form
{
print "\n";
}
# yes_no_field(name, value, default)
sub yes_no_field
{
local $v = !$_[1] ? -1 : $_[1]->{'value'};
local $def = &find_default($_[0], $_[2]) ? $text{'yes'} : $text{'no'};
printf " %s\n",
$v == 1 ? "checked" : "", $text{'yes'};
printf " %s\n",
$v == 0 ? "checked" : "", $text{'no'};
printf " %s (%s)\n",
$v == -1 ? "checked" : "", $text{'default'}, $def;
}
# parse_yes_no(&config, name)
sub parse_yes_no
{
&save_directives($_[0], $_[1], $in{$_[1]} == 1 ? [ 1 ] :
$in{$_[1]} == 0 ? [ 0 ] : [ ], 1);
}
# opt_field(name, value, size, default)
sub opt_field
{
local $def = &find_default($_[0], $_[3]) if ($_[3]);
printf " %s %s\n",
$_[1] ? "" : "checked", $text{'default'}, $_[3] ? " ($def)" : "";
printf " \n",
$_[1] ? "checked" : "";
printf " \n",
$_[1] ? &html_escape($_[1]->{'value'}) : "";
}
# parse_opt(&config, name, [&checkfunc])
sub parse_opt
{
if (defined($in{"$_[1]_default"}) && $in{"$_[1]_default"} eq $in{$_[1]} ||
!defined($in{"$_[1]_default"}) && $in{"$_[1]_def"}) {
&save_directives($_[0], $_[1], [ ], 1);
}
else {
&{$_[2]}($in{$_[1]}) if ($_[2]);
&save_directives($_[0], $_[1], [ $in{$_[1]} ], 1);
}
}
# edit_textbox(name, &values, width, height)
sub edit_textbox
{
print "\n";
}
# parse_textbox(&config, name)
sub parse_textbox
{
$in{$_[1]} =~ s/^\s+//;
$in{$_[1]} =~ s/\s+$//;
local @v = split(/\s+/, $in{$_[1]});
&save_directives($_[0], $_[1], \@v, 1);
}
# get_procmailrc()
# Returns the full paths to the procmail config files in use, the last one
# being the user's config
sub get_procmailrc
{
if ($module_info{'usermin'}) {
local @rv;
push(@rv, $config{'global_procmailrc'}); # XXX needed
push(@rv, $config{'procmailrc'} || $procmail::procmailrc);
return @rv;
}
else {
return ( $config{'procmailrc'} || $procmail::procmailrc );
}
}
# find_default(name, compiled-in-default)
sub find_default
{
if ($config{'global_cf'}) {
local $gconf = &get_config($config{'global_cf'});
local $v = &find_value($_[0], $gconf);
return $v if (defined($v));
}
return $_[1];
}
# can_use_page(page)
# Returns 1 if some page can be used, 0 if not
sub can_use_page
{
if ($module_info{'usermin'}) {
local %avail_icons = map { $_, 1 } split(/,/, $config{'avail_icons'});
return $avail_icons{$_[0]};
}
else {
return 1;
}
}
# can_use_check(page)
# Calls error if some page cannot be used
sub can_use_check
{
&can_use_page($_[0]) || &error($text{'ecannot'});
}
# get_spamassassin_version(&out)
sub get_spamassassin_version
{
local $out = `$config{'spamassassin'} --version 2>&1`;
${$_[0]} = $out;
return $out =~ /version\s+(\S+)/ ? $1 : undef;
}
# spam_file_folder()
sub spam_file_folder
{
local $file = $userconfig{'spam_file'};
$file =~ s/\.$//;
$file =~ s/\/$//;
$file = "$remote_user_info[7]/$file" if ($file !~ /^\//);
$file =~ s/\~/$remote_user_info[7]/;
local @folders = &mailbox::list_folders();
local ($sf) = grep { $_->{'file'} eq $file } @folders;
if ($sf) {
return $sf;
}
else {
return { 'name' => 'Spam',
'type' => &mailbox::folder_type($file),
'file' => $file,
'mode' => 0 };
}
}
# disable_indexing(&folder)
sub disable_indexing
{
if (!$config{'index_spam'}) {
$mailbox::config{'index_min'} = 1000000000;
unlink(&mailbox::user_index_file($_[0]->{'file'}));
}
}
# get_process_pids()
# Returns the PIDs and names of SpamAssassin daemon processes like spamd
sub get_process_pids
{
local ($pn, @pids);
foreach $pn (split(/\s+/, $config{'processes'})) {
push(@pids, map { [ $_, $pn ] } &find_byname($pn));
}
return @pids;
}
sub lock_spam_files
{
local $conf = &get_config();
@spam_files = &unique(map { $_->{'file'} } @$conf);
local $f;
foreach $f (@spam_files) {
&lock_file($f);
}
}
sub unlock_spam_files
{
local $f;
foreach $f (@spam_files) {
&unlock_file($f);
}
}
1;
spam/setup.cgi 0100775 0005671 0000012 00000003745 07747562426 013364 0 ustar jcameron wheel #!/usr/local/bin/perl
# setup.cgi
# Actually setup SpamAssassin for the user or globally
require './spam-lib.pl';
&error_setup($text{'setup_err'});
&can_use_check("setup");
&ReadParse();
# Validate inputs
if ($in{'to'} == 0) {
$file = "/dev/null";
}
elsif ($in{'to'} == 1) {
$in{'file'} =~ /^\S+$/ || &error($text{'setup_efile'});
$file = $in{'file'};
}
elsif ($in{'to'} == 2) {
$in{'maildir'} =~ /^\S+$/ || &error($text{'setup_emaildir'});
$file = "$in{'maildir'}/";
}
elsif ($in{'to'} == 3) {
$in{'mhdir'} =~ /^\S+$/ || &error($text{'setup_emhdir'});
$file = "$in{'mhdir'}/.";
}
if ($module_info{'usermin'} && $file !~ /^\//) {
# Create parent directory if needed
if ($file =~ /^(\S+)\/([^\/]+)(\/(\.)?)?$/ &&
!-d "$remote_user_info[7]/$1") {
&system_logged("mkdir -p '$remote_user_info[7]/$1'");
}
}
# Add new Procmail directives at the top of config file
&foreign_require("procmail", "procmail-lib.pl");
@pmrc = &get_procmailrc();
$pmrc = $pmrc[$#pmrc];
@recipes = &procmail::parse_procmail_file($pmrc);
if ($config{'call_spam'}) {
$recipe1 = { 'flags' => [ 'f', 'w' ],
'conds' => [ ],
'type' => '|',
'action' => $config{'procmail_cmd'} ||
&has_command($config{'spamassassin'}) };
}
if ($file) {
$recipe2 = { 'flags' => [ ],
'conds' => [ [ '', '^X-Spam-Status: Yes' ] ],
'action' => $file };
}
&lock_file($pmrc);
if (@recipes) {
# Insert at start of file
&procmail::create_recipe_before($recipe1, $recipes[0], $pmrc)
if ($recipe1);
&procmail::create_recipe_before($recipe2, $recipes[0], $pmrc)
if ($recipe2);
}
else {
# Just add to file
&procmail::create_recipe($recipe1, $pmrc) if ($recipe1);
&procmail::create_recipe($recipe2, $pmrc) if ($recipe2);
}
chmod(0644, $pmrc);
&unlock_file($pmrc);
if ($module_info{'usermin'} && $file ne "/dev/null") {
# Remember spam mail file
$userconfig{'spam_file'} = $file;
&write_file("$user_module_config_directory/config", \%userconfig);
}
# All done!
&webmin_log("setup");
&redirect("");
spam/save_white.cgi 0100775 0005671 0000012 00000002540 07747562421 014345 0 ustar jcameron wheel #!/usr/local/bin/perl
# save_white.cgi
# Save white and black lists of to and from addresses
require './spam-lib.pl';
&error_setup($text{'white_err'});
&can_use_check("white");
&ReadParse();
&lock_spam_files();
$conf = &get_config();
&parse_textbox($conf, "whitelist_from");
&parse_textbox($conf, 'unwhitelist_from');
if (!$config{'show_global'}) {
@rcvd = &parse_table("whitelist_from_rcvd", \&rcvd_parser);
&save_directives($conf, 'whitelist_from_rcvd', \@rcvd, 1);
}
&parse_textbox($conf, 'blacklist_from');
&parse_textbox($conf, 'unblacklist_from');
if (!$config{'show_global'}) {
@to = &parse_table("whitelist_to", \&to_parser);
@oldto = ( &find("whitelist_to", $conf),
&find("more_spam_to", $conf),
&find("all_spam_to", $conf) );
&save_directives($conf, \@oldto, \@to, 0);
}
&flush_file_lines();
&unlock_spam_files();
&webmin_log("white");
&redirect("");
sub from_parser
{
return undef if (!$_[1]);
$_[1] =~ /^\S+$/ || &error(&text('white_efrom', $_[1]));
return $_[1];
}
sub rcvd_parser
{
local $a = &from_parser($_[0], $_[1]);
return undef if (!$a);
$_[2] =~ /^[A-Za-z0-9\.\-]+$/ || &error(&text('white_ercvd', $_[2]));
return "$a $_[2]";
}
sub to_parser
{
local $a = &from_parser($_[0], $_[1]);
return undef if (!$a);
return { 'name' => $_[2] == 0 ? 'whitelist_to' :
$_[2] == 1 ? 'more_spam_to' : 'all_spam_to',
'value' => $a };
}
spam/save_user.cgi 0100775 0005671 0000012 00000003026 07747562407 014207 0 ustar jcameron wheel #!/usr/local/bin/perl
# save_user.cgi
# Save other user options
require './spam-lib.pl';
&error_setup($text{'user_err'});
&can_use_check("user");
&ReadParse();
&lock_spam_files();
$conf = &get_config();
if ($in{'dns'} == 1) {
&save_directives($conf, 'dns_available', [ 'yes' ], 1);
}
elsif ($in{'dns'} == 0) {
&save_directives($conf, 'dns_available', [ 'no' ], 1);
}
elsif ($in{'dns'} == -1) {
&save_directives($conf, 'dns_available', [ ], 1);
}
else {
local $test = "test";
if ($in{'dnslist'}) {
$test .= ": $in{'dnslist'}";
}
if ($config{'defaults'} && !$in{'dnslist'}) {
&save_directives($conf, 'dns_available', [ ]);
}
else {
&save_directives($conf, 'dns_available', [ $test ], 1);
}
}
&parse_opt($conf, "razor_timeout", \&check_timeout);
&parse_opt($conf, "dcc_path", \&check_path);
&parse_opt($conf, "dcc_body_max", \&check_max);
&parse_opt($conf, "dcc_timeout", \&check_timeout);
&parse_opt($conf, "dcc_fuz1_max", \&check_max);
&parse_opt($conf, "dcc_fuz2_max", \&check_max);
&parse_yes_no($conf, "dcc_header");
&parse_opt($conf, "pyzor_path", \&check_path);
&parse_opt($conf, "pyzor_body_max", \&check_max);
&parse_opt($conf, "pyzor_timeout", \&check_timeout);
&parse_yes_no($conf, "pyzor_header");
&flush_file_lines();
&unlock_spam_files();
&webmin_log("user");
&redirect("");
sub check_timeout
{
$_[0] =~ /^\d+$/ || &error(&text('user_etimeout', $_[0]));
}
sub check_path
{
$_[0] =~ /^\// && -r $_[0] || &error(&text('user_epath', $_[0]));
}
sub check_max
{
$_[0] =~ /^\d+$/ || &error(&text('user_emax', $_[0]));
}
spam/save_report.cgi 0100775 0005671 0000012 00000002215 07747562327 014544 0 ustar jcameron wheel #!/usr/local/bin/perl
# save_report.cgi
# Save report generation options
require './spam-lib.pl';
&error_setup($text{'report_err'});
&can_use_check("report");
&ReadParse();
&lock_spam_files();
$conf = &get_config();
&save_directives($conf, 'clear_report_template',
$in{'clear_report'} ? [ "" ] : [ ], 1);
$in{'report'} =~ s/\r//g;
@report = split(/\n/, $in{'report'});
&save_directives($conf, 'report', \@report, 1);
&save_directives($conf, 'clear_terse_report_template',
$in{'clear_terse'} ? [ "" ] : [ ], 1);
$in{'terse'} =~ s/\r//g;
@terse = split(/\n/, $in{'terse'});
&save_directives($conf, 'terse_report', \@terse, 1);
&parse_yes_no($conf, "rewrite_subject");
&parse_opt($conf, "subject_tag", undef);
&parse_yes_no($conf, "report_header");
&parse_yes_no($conf, "use_terse_report");
&parse_yes_no($conf, "fold_headers");
&parse_yes_no($conf, "detailed_phrase_score");
&parse_yes_no($conf, "spam_level_stars");
&parse_opt($conf, "spam_level_char", \&char_check);
&parse_yes_no($conf, "defang_mime");
&flush_file_lines();
&unlock_spam_files();
&webmin_log("report");
&redirect("");
sub char_check
{
$_[0] =~ /^\S$/ || &error($text{'report_echar'});
}
spam/images/ 0040775 0005671 0000012 00000000000 07723371656 012771 5 ustar jcameron wheel spam/images/icon.gif 0100664 0005671 0000012 00000003301 07675211717 014377 0 ustar jcameron wheel GIF87a0 0 ۽ʪƞʶsh¢AAV44U|t{vwºɛ`¶_`faf|fKIoZVucjdp~z{~`YT?AgVfb^abbige:Fqf^j>Fonr^`^ba`ƹfNXvCFqbrjVNZ^Ҿblro^ab^ڎZrj`PQkfRNV22FV^lljJJBJu')J6>kvVJF6r<8Q;nJҰfDnL~T`BY>N8C5e>2@Ov4:J<4J7ZBbD`?}jGsL|S>5C7zB25>`V=fFtQuOB5j:.75,5:YdliQI6zPY^:0H6,.2*:HZN:fJV0.*9:.DL8UszFVzZh>.ZbF^~Nj6.V;U[>A2JfB6VjJ:NZ>r^BVB6JPBr¾Rn8>XQ9V@^Bº8BlZJVFxRHj^ZNƲ¦rrzW_~F:RﮒpަBJj~rvv , 0 0 H*\X0@ @\pAVH#dž?
(RF$KRJ--:9G8qZIp Y@ 9@(P@sjG$ptM
>P*hک3HfPAA{:@7
3(41t@D@G(a*,T
yQa+Xp2fpX8rȑCK
~$B)bI.=&Mb8B(KDAS-H1D1$1U`@}V\qBEZC