spam/0040775000567100000120000000000007752335027011516 5ustar jcameronwheelspam/module.info0100664000567100000120000000024707752676232013666 0ustar jcameronwheelname=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.info0100664000567100000120000000162707736402611013637 0ustar jcameronwheellocal_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.cgi0100775000567100000120000000270007705401056014340 0ustar jcameronwheel#!/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"; print "\n"; print "\n"; print "\n"; print "\n"; printf "\n", $module_info{'usermin'} ? "mail/spam" : "spam"; print "\n"; print "\n"; print "\n"; print "\n"; print "
$text{'setup_to'} $text{'setup_null'}
$text{'setup_default'}
$text{'setup_file'}
$text{'setup_maildir'}
$text{'setup_mhdir'}

\n"; print "$text{'setup_rel'}

\n"; print "$text{'setup_head'}

\n"; print "

\n"; print "
\n"; &footer("", $text{'index_return'}); spam/import.cgi0100775000567100000120000000240607747562270013524 0ustar jcameronwheel#!/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.cgi0100755000567100000120000002002307730211552014141 0ustar jcameronwheel#!/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'}) { print "\n"; } else { print "\n"; } print "
$mailbox::text{'view_headers'}$mailbox::text{'view_noheaders'}$mailbox::text{'view_allheaders'}
\n"; if ($in{'headers'}) { # Show all the headers if ($mail->{'fromline'}) { print "", "\n"; } foreach $h (@{$mail->{'headers'}}) { print " ", "\n"; } } else { # Just show the most useful headers print " ", "\n"; print " ", "\n"; print " ", "\n" if ($mail->{'header'}->{'cc'}); print " ", "\n"; print " ", "\n"; if (!@sub) { print " ", "\n"; } } print "
$text{'mail_rfc'}",&mailbox::eucconv(&html_escape($mail->{'fromline'})), "
$h->[0]:",&mailbox::eucconv(&html_escape(&mailbox::decode_mimewords($h->[1]))), "
$mailbox::text{'mail_from'}",&address_link($mail->{'header'}->{'from'}),"
$mailbox::text{'mail_to'}",&address_link($mail->{'header'}->{'to'}),"
$mailbox::text{'mail_cc'}",&address_link($mail->{'header'}->{'cc'}),"
$mailbox::text{'mail_date'}",&mailbox::eucconv(&html_escape($mail->{'header'}->{'date'})), "
$mailbox::text{'mail_subject'}",&mailbox::eucconv(&html_escape(&mailbox::decode_mimewords( $mail->{'header'}->{'subject'}))),"
$text{'mail_level2'}",length($mail->{'header'}->{'x-spam-level'}),"

\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 "\n"; print "
$mailbox::text{'view_attach'}
\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 "\n"; print "
$text{'view_gnupg'}
"; $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 "\n"; print "
$text{'view_crypt'}
"; 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.pl0100664000567100000120000002214107747557012013560 0ustar jcameronwheel# 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 "\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 ""; } print "\n"; $i++; } print "
$h
",&$cfunc($j, "$_[0]_${i}_${j}", $_[3]->[$j], $v->[$j], $v),"
\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"; print "\n"; print "\n"; print "
$_[1]
\n"; } # end_form(buttonname, buttonvalue, ...) sub end_form { print "
\n"; if (@_) { local $p = int(200 / scalar(@_)); print "\n"; local $i; for($i=0; $i<@_; $i+=2 ) { local $al = $i == 0 ? "align=left" : $i == @_-2 ? "align=right" : "align=center"; local $n = $_[$i] ? "name='$_[$i]'" : ""; local $v = &html_escape($_[$i+1]); print "\n"; } print "
\n"; } 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.cgi0100775000567100000120000000374507747562426013364 0ustar jcameronwheel#!/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.cgi0100775000567100000120000000254007747562421014345 0ustar jcameronwheel#!/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.cgi0100775000567100000120000000302607747562407014207 0ustar jcameronwheel#!/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.cgi0100775000567100000120000000221507747562327014544 0ustar jcameronwheel#!/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/0040775000567100000120000000000007723371656012771 5ustar jcameronwheelspam/images/icon.gif0100664000567100000120000000330107675211717014377 0ustar jcameronwheelGIF87a00۽ʪƞʶ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Ʋ¦rŽrzW_~F:RﮒpަBJj~rvv,00H*\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\qBEZCCCB34X_R ;spam/images/spam.gif0100644000567100000120000010017207675210530014401 0ustar jcameronwheelGIF89a@@@@@@??̿̀̀???˿˿˿?????֪@@@@@??wff@fff?ff?feeee?e@e?e??UkkTDUUD33333@3@@22?2?2>22>2"++"@??jU?+, H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿F(48„!Ƹ.Ƈ n(9Ə'?X2gf,phC5 LXCϤMUf}pmK-8㾓Wn9ЛG.:γOw^wlDg OHtAo_o]qH~~O6@0 8 @O,`pP~P@$"h VH<(g[hxf8A?zh@|Lbh(hÁWfږi kӀ*HHd@&馒$TI!#xMzH"iJ",vZm*H'FY h(e&>OJ牢F*gc^q))8 *#?r`q NjFyz-R ˁ|~k, b 디= ?r8gnH.< @Šv0ٺ 2k9|:/[чjH /cHe6nkN!2!rKʹofMn ej8|s\֨p&˃*ga'iv:2 LfPf؉6;Gk7P6>Jo+|zrKe-ʝ읗( 9bY hlb!"hmC }j3֫ gm#bl) z,]҆2߾ce {/c *?Z:܅84 rY"8{bRUUw=baQK)Hӧ=Mw!npQdə`͓XN.)-gPtqgb@8p:UT[7cyXB GtU3!`/;thLAnk)[ߚ]V1*Ȩ7v@ TY c3@ .*w W!Fasܫo鴮 }[!|U[ݼ^x\]+Re:%0 eaߔLe-z"@K:-}G^EWj5hE(` H@qklI,Wx0zCYy<*sxCR }hM6Zw(Z晛sPj1cI`_*_2$DHҨ@P͘m.us s}'=9gsAS$>U5Bt_)*1/Kkȡ oӑT<5tٻS!L–Y3 { 6"O@<#d@@>$y sc AE\f34+5dAlѴO %хekZe 7B`^p#L fSLDs;Mluԃ $܆pQ{-)7 &6hmbNju:u@T"+N]eMz@F:5uNlN\M[=pw+7;7^73F[+M/X*@;\X@, e:) jކ@;IkB[?a- HͿ_є.E<6=|ү & &m-r ux6.sZ;;csv,@u:4<0e- "gxܤwY*]h}Po460~~~}Cjb-W{͆&\K,R'r G/U{FY7!(.*lR0(`i1f?$m <#n}U"[5Sȸw7< Sg&kw֌:nYKAc*f1#ULId]$@4S1dMsWnD lf%1, Q0^Ggꥀ SmtnxxQ !ߒ$9~HCMn$`+ Uh0:ɓq,_,twOLO2|cG!u67oiI I)Md۷YyHAy}#X?67SA&G0z7aQQGp / * oz{&z yF4MC!99&";`Bc< 9~v&2,\g5,#*`)3 `WWGx*pxLP#2YrZ Wtי's'sߵ[e0 Jr˗009N#gaT7rD⌕QPF`Gr*e bfO֡I uD|5!.”–!r"V6723V#t`w>؉Z9Lbm7,pQYQWf0c:J 84g.vvxPOVP"V4Sw$ߘ"@GX>@`Hc օK!(xB%;1H'x$/Q`bJ@*JY@G@ PvZ%k0v80bVSzEc7]1&"K=6@sTttJD*jwՉ g)ouKI@F9#+k/ W@bsKkں:,-y K.{B 7 4gu*rc}DVd҉| r&?LUoTo[l;J`̲TpTp|-銮2(E 6|V/gqzaӞs)5L/C!DVCFYv/ V'|J,{F(__| ¢2*|; nzؠ ,nBw$aFiEPzp{4l̾dz¡LcKHFPF%l*|w +{ SǟP8)NV'Jqph#&#cFKӍ,ύ@΀ L}MХ>"L|2jۮzebN(B F%/@&P)# uN`W`+a~~0]T🇽.IKrRp_<] ٧Jر|ٝ=R ڲ)lG2HinwOi{ϑ* z,F0& $ 5;T۽D9=H9?(>/ ,SFOp)pKKs+KMԩlB>ԯ<<+[\{K=]*`/߇8)_[60'/j| @N_!_F9M@Ta0 `hxxhhxxPtDed$I ()ps4 )*j*hJ䊋KI)H| ,HL< j$9+eANp/?O_o%*YteHZ0ӕ_V tՋʎ Ɉ !:D耡LdM>S#/=tCINvڙLLL9: +_aL)'][+7ofaTҭ#8`ذ7޽|;FD;`鰗l2̎ )1DT Nr'4cYub0 YC*tRXJlOs(l/Q \F.FY Ugaj /WAB(m X6E,xzcM@AKacF$Tpr Ym6)C';XGPlpUT%=@Nى VI7L !X尉peW~pLE} 2@&MF Ⱥ$JA B@Ұ> =XF U"d$iK89cHhl} q+Hg &U@aaOEBy(x~{IUq(TTE:ۄH"1eN\*9 AzF5K 3n9n[yS\?vJ_MC:UHd0Wo GPB 9ioDR6q$8 邑%#+ePK[ nxrS _PN7[?z{$wq| byG4 !PĄRQ-.O1B & GE<$o@,IA- 9{oM̆ᆭWKDZ(GaL|޳tYqq@w"AOWر!aTRcR4@v NeK0yQC5 v e4[R:`Kz ^ةPo)䮶"B(Drm§O-z٦B̄D4nwOBӫ/=9άɥ! W &tL]y,8N08d4>ԓ6 SԄGd6&p7m<$ ^Y଄]Jv#A`bIg6E7! -kA*DpX./m2w\'l@|}a$oz )Z;ȳd@ZE< 64 0B &;p,uȍ(Hh爎騎ݨ: _0xS)'r,+"VbTaKTU ~FRдBcE@Ңi?1~#C}5cUCC%3I5i79ٍ> A*7DJ99!j [mrATDnc@dU9r3 wǗ"SCB|rPQV)dFK8!I6LY!1PCf}CXx:Ii=U3β[BSII tya* wا;7}8p1'hOq~xɳs j)-dr'?Jt)Kܲ<$%r.Tg/i ژ׉٩UIP8h*-KJ('cQ_Ae9`B' .q!S␔pwR ;1'6pCxї X d;pR0'1 ."OGg `0HD"v82uD(ۨ-/0pI`5D#';5 !`^:4qr!pS8 tJ)*!LzKH p4v=UBQC.4!m" T'!EBJ Sg00 R$`IH0JڢI];q>i^|dB!pքO3 Yw.DpF(Q- )`YPZb5 $$82aq ,IrfiJIGeaDOYp+00CUsN4á+@(RjWT %#ɛ mplБqGP+buT1r Wt,Z 9sWw!¨a JSRUI C M CrSkUr)"?Y*wnShxF RZ1h$mQ+C*Jgڍ3&Av N;qr9vhЂV^.2r~cڤ"`+X]fe8(Tw8s2_Vrz2KE a>i-EhTѨ1}TjB4!wOq('qHB@AR;E^c"wEqh m7-< TPb\Q; ђ+2iS&!r;^K${q^vG:N+hJ i=C?";qr|GQ @@,`Gky$$)0W +L!V$$E^&upu:|0-v&A9XuЖ RhJ'ݒ:-0 0z !4W IӅ 3t͔Kh*#Z`cD)B^t؄xC`p6P!6g.p-g (cqDt $*+Fk`Tc7vaVۡeRY:02rpB1\78;ỴƣmvE֠G*cg:x +Ь&> -][Ng&hjB1*@16cx;O$(mĵ6$СDBG0,0\ldg ,U`ne}j[px:*3tfCfW%4\%Q2F.Kt& e: [!$0L:\Å=,V.s|@Q ܴ!=f r$gpau㣎GNl89!i7 P "i1q,`#pfi.ӛ}-OWtQV! :s x @~]H9]D9%*4Z ޚO q&$7$WJx,0kf>}=C+5;8 M9:Fi)c`d@aEX ]ٮَ.Nnn]Qq?b->j-} '^!zwhs0. |#!`e o">\ 㝜ZL E6>CqȰqW)4;=.qD3H,#jpr xV'Mt sy̙x/ e׿$*'x羰hр t}-p qн2I~9/ڎbSQN443#zaJH&$fdMm#9\3 k^ 毮gzT}ATC__tΘx!zX;/OsXb`=\*8+@BzGR!JQTJTGJFTQ; YG,#!# #!JWHGJTGHFWḞ)GTHޚߔTFRFH;E816 H*\pQD&Qӕ,TxKF/Q(ZWHx)d+0Q!B  *8PAP 3cHU,PS,RjURډMR\8rB\b)\pd騤#&u!RЍ$ӷLFvXC<L``˘3k9vͣF 5f(VBžm4#4Ŧ4bH $,bqBN6FRXn#?-6ӁW 5թ !"D!*t5ׁ"205k -GnƄCL88ИxAgev U4[$eQFYĖ]Tt Fx]Z:;[2Rm L!$x߭ L'T-ey^uqS p}Hc,'ImDD5`}HA`3a a  pϡ`ᢌ6Tph͘ť!yE0FQvbԦm4-x8"0TŖ)T\yrNU汧Žw"qijTdZ @%|#Ӹu`1` &|8j DD^E^G ̚6K1S*Jh`K*Eo\;e YUNay^myVSgm+7q򡄉/䲭{tm`d `cXb8<\w/p$QHv"Fb lZUFu#5g̵L4@֘HuUUR0W UwL TkX~)'V Q[U,ъ-;EDCUHJhRT|,.dAI[nJ7aB?#Ʈ!*@/BftY e! Ȅ'PAj`O=Ph6-`N]a 98=UPM{[ *$C fqk;b,c1 0 4q+끦pwº"-w$2NVQJ;H8& ިu Hp;Y })96S9&V~*q{G駎Cp܊w5XUe#NR0I+F 2=p0bTa[Vh`b)C;8凮 ך,ދD? NtnV>,  D>T"2 {KPZiUV~'1ҳ[2 dQ F( B}wk_T5Nf"VI'Cy"U@0'nsC'n5nT"n8pR?WvQw>WUWVZo84FK,F4crmj s#=z[Ha+Z$T8#R~L5IFIOE6bFn|}nWs@t8@v>pn,N'EohKVGu!Ku{t8εt8 Xbv(1RkRPP=ev(ш}8u*3"g".^ 4t0b C찏Nȏ nC HQkXW.WhEzKI WLcRT 1fof#FFc! vEvjWZeSH1q Es'(T@(U}}}m`T0+n}T脧X)Uc^WR29E]ZQd]`][DWbWDosc,2xun'?UGcPi0P*Qs%v:yM:.80/}V @瀾XupEЕ#%' , ptlqz 8cAF%9&8かC D&ҸRvr|]3@M.1@;"/ƙ(}+/B*BCrBJPGn ވafl hQhhǩ{ pTXdu8WPhC'0ye5`)f h+&Ew: J*o dAo3cu+3 JRVc IݥbJduRx9b5g'C /=E;Au\]c0BqBŎ.t+@Kwc?d¨ i RkLW+2 uWxuSoc9R^#pN7d6]wU*@Kw$+|xm.!PU GauzگY1LJ]DNKWX88ts*sJ'(`=˼+&v~q6Q\]cеch>`;!R(QF\EliuV>\kUTV[M Eؖj'SG!ı`"d" 6tY>2GƁ0bZ/q8;u3V{{eREl{%ӀЩy.tR 8iGŒecPmCwCqv h[W @Ø&TKwnm27cA3&+>fܵHME.pkugfW)Dl! $Ip\VP1S]!C Էy;y% `ӥVR,:ʨQS)zi&c EᑹԌpjp*cH}mAdpGް /±,|!e+4 )QTX+tcVy n2WQML@M=zQ#ۗV<:"W> v9nˤ0Zva8"Ii+!]$R<4҂lV=@QdyuN<%YhKKy~8 ЋJ܋L9ħI=ꦝ|9UT>:8CGx lͻ!fS} 1`їzgVl/3/.V%K'Wz@KyWQVoI.{\W Eީ>I6[ʂ}~.V8zdHax%WG_bxㆪz{KSW\(DT$[g R$Xo^^N/oTk*bH[z}h! $"Gf ,X" ]C; G LA RMĦEAW4ӾtRdjn]*E"0@|jvč / (w e )L^+=?ĩpf W;|uz/K=d@{ju^ŝ>Q鐿 Njoܦ'8믇g~q@Hq1P"(@R@XaHh)9IYiyyEuDDu53+0 R2ۋˋ+<<"ܠ+\LKp!PP==}=]@-2Ύа0\܀?12ÂőGQʑ* <(,X:E%c*V6JEHF$BR!)%#R 1#pSRMz 4P" )UHNE  ܰboǺbUZz =fޘ9"]Vnt; ^fyoG>rCD->!` QC+BUh ʽN*'kv& tBjr#H]D?g|`]3nc^j2a%+_v]-4`'{ lA+5Ѝ~7' n+5BRC;eRSˊj6IE"HcE)LweY@eDed#`],#WGlH6 ,c2%{RCk">E ;`0)( z0sF*WE|(flbvؠ7o0z7rZq%Kf),[,ť.A{ 3&1Jc"_uiI b̏e'1ŁBUPC pg+l-9l@0Ap1z[9HJhUgqJ!|8*C+:,{[93CsZ21#hԣ `ٵZTup|Pgu D:h= BVC6hC \T ;$9CݐًB@r#.r]ixޣo+y=ndc)A٤F0 `:*@ m4D*t1~  *.X] ͫ)ăKhO/l)ʉݤt$<MMUNޥcV/_qPP.>Z~!˳HCi5Zڳq#]<̗ )AϤ`A(H(!ܚO;x=1[LTE'lE2թPmSQpѬd 釱 c* ^H&' t$ +% w50 y? sS8rP\,TiMSCTa4T(UT*  (nT x))#E[z=nc7sŻEUÊ|6f)M{E^'.= 22+yY3M 5yiH)̗kiڴ} F̓@e &XF^[+sL-ȋ*5sޣHAXVbzOL:ԲF^cz֘uNjAvMktQ>ִB0XO=HvDC`x`[oN|`4zKp'~y٨'(/1a5@A( b%?/Ĝ*?Whe<ڢ o2cymͧh3lE fCPSњq C 8P D5#y]hJ r;ad3vPԝ?K:X b!(wc~44ke-k<}͊.c)W%omҝSDE9cNAz/;H\|W貌ͅ7䙱Uvmg >{ږ.,g` I:}S^XH+9T։"r7S&:B62v$-;}҄5~D1J铕<D ~.IZ9'EQ9WFZ]@&Oui?љҐz ^ RR+H*N_64G{ǀd7 hG)+pdF $m P?d >0^v  $.Gkn3v2&nl`w9RzF+ƂE/ jk&ooNGoQ0α)a"r_,aH/@-B=C ؀@fcQbr8dlfaR2K{LIb&'Ik-OhBa*: :@xbxsR b1`.7u׳t idU1;;/YG.aZ`dk0dH`v "CƂOtFK*&Jqa#?Ve~]*'&#J5C9ls&k\KrO$~@;oh𖄺3S)F%d)_{ŋ Y Fd/C?O nJ+&8V DF@4&{^5 ӅR߀} \B &2Wl9 Au5Yd.ISpPd=@G@ P^uCa &_Z i ) CtFdD"?PwQ|2&9Ft'80WQٲDP:=c-sR -t]n;W& (OQRy*pK揚z)Z""\Na ]'DO. n8nOpi&YrRpLvKܨR@8) )&btbŀ}J/2I7YQd׳dUi1_UHpA@NF"T0Bh{ G"Il7}$ zX |)&q φO~RAqmd4!` `0&9xV@#t"V|ۀ?o?WY|,05_FGjD!O` C1/:#FUZ" W 8x$AD.O[ QWX&-> *shy?5K|Q}sG~'-@:M$ȗ,yGJ) GTAkE_z/SpBN C0"'.1pZj1ZCuڀC%P'm,EUQH"AA^AD@,dT P8u&BCgsRUs]u~mSAzdJDh]FA)i0_:pJˁвmgk5y"93gQ@iU"x'Ş72kdw6:)cMPaj˟1j^8]GputBd``0 Hzzc6z:~§nJfg2-C4RM@C|Q\s[F2 w"]ʔ t{dt!JZdk$ApHP/"54ppwKJ)zsg3:-ۧq+44|;V $/SeBq b\ F 9+ UaM?פSĺWVH`D@0/)]8 UN8`pSLNKIVf{3'Cвmw7Q'}71D}8vTK!t7'S̖4G?&wP _GV/Y(N*P6U)i̻A!,F0J² 1z!?$%ip?ږԙi IER:&*Rq&{GP6HiD2%(|䟲LZ?<Ueʻ,H#zN0`ǺX60pf[U˲d|'CR( 4 `R(F5 2R[P9J 23 '‚+GGd}US|Z1\̻X Z v̽h 9+^Gײ /l|4Sօ<~itEhwt0'R8fRn9T+/ՄoAju!|SH)zC]m<"“"Y(6#( eW)JP,aͶ} ӈ;QpV?P8ڱ,py+WJi"r3s3pIoIGY7S xT(j'tN4e{Hp(ZP1M7.< }'b^%|a4Xu5-V xRK2?lD&vY?,2 uY[A ~Ta;USmCTtB"&9`Z;! QqFJf| ՛{T#7 J֦b& | D?* maMoId U K֏uAL` X/.Q`"e 3$k1CPK T"406RջL,06^@QA*LJl4>bفK E7: D4[$YQG}d ܄Y>y$u0^1dˡ5Uyq(5 \*&͎i%RzÕPn|>$ԗfLrI.5xӵ៷?u=*(/!z4Q8,y*h,|$}CMpѣ3 &prPIYK?QHݞof\'F LU`މn>%&!X8NS6"$@6WV,TQpRc|W//swi13@XDj~Kl? BOw RvR|BlԌB}cyJ:7X YQUQGQUQJGQ=JJGS;CACCTJTTHFRF;FC16$0TQHYG!,,GGWU?4##,# #! !! !  #[pALaB~! (ѫxaE/$t O;z/k.],*$C tє# 9џMP BB#6`@jBzڕpʝK--G*)1̊$Hfaq¶ UƢG8Y26ȸ$z)h`"D@LޓyzAʄ˸NG#*޶ RAJ.o>]ZjQ$cgHiPBG&X H8UcRTNZF&r.(`\#e4B]Í6% +N"ІPqhtO"Ԑ@5Dր@T=Lx%tAV[pT\qq:!4tA)$@BHsNADR 1P8Y_"E|R0 p@i/h衈5^:WHJ!a@6TXb-z3S[hc>-ԢDcAuxH>)ZHfGmBiPKqЯ2B@Q+w@RT&D#1f/ Tq'i (x~m Sh,0|y(;danps76ϪCF^ى>͇]H#B Rm&SNHHw">i4*Ġ) C['{H.$p DY6d:b27< K?ȸrs AWtQώ4I;#JM]H!H1tTB8b;wZHЉ9iVЛ}g}1sZ); >. U|,I i8WfIk*#F!)?t:xcv#D5 j Mx󝷶*./b ->YJ)t'VО1pJqQ!Q*MPT(G܁$+9㢌59"0 A8C Qr!1VtHG[cGdRDApUZ Q.L ip)HU>8x,\?,1,{1+F  @I,7rfYQGDD)_2ˑ5 b*tO6>E uvL犀u'\t(qPbJ"yDpJ?1D^pxB P! {şТro [v1R_/ȋ3,H h(NF=B#m&[1ӒװlKȱRy($%R֍4r*X]-*Qn5ƄQ7lg-mJ{i 31RN1Ž$Df=jkNd cHH*RF?cXaH (G cPB:xL!*xˮ`y*@O.XpPr,:Rl\ X Bx_ rt Ӛ@Y0O|Sq_V"=4B.PC<cb\{|0ϝ֪\-N4E$!jrLlb`AE ` UX\ab焤s|jįX,BjABNUy8ͮ#-*hP;}  VJ0$(υ_4>N ~E MaN",h/X6#5և`elcIEйϬzMHsc#5ղ.hd&!hI9nIǓ1 d$0ILNS|,J{dJS]AK,7G=@.Ql=zN gsZ'|!!&5 &WlٜnS/MHY~_H4rR/*GaLa!PBht%$UCGVZbG7vGN$&2/PmG}~s=z]cQɕ X <'ΙD6e(y3HtJ !7M6L193sag|6bZ4iE7o{LǤ,V${N8S@F&dAg=&as'f8Ѓ&/g+rd 7Y6w6~U0 )a#T2btC5XT2A\`a{nA@ !A"Z@8u?z53Um 0lSrsJkxG'1Cw0h&%} @/  2KW6gh `|[thuz f$će$)98+R2#@(o/$o2[adE Eem=e|Ek8y5JfP'/`=Q:J~$ RPDp1J*8p'1:R=$S0ng9 $wa+և";ACdꞕ2nTf&:=$&. 0|waѦ/(iK:YLkYsz3=;@ VWg1Zt t#7hh u+oUFHNA* ZSZ'kqp聧0{}z0DV(C[~<Zq~N[s[s;: %)Pz8SduRj4%wu&29 +c;2~Ȣ:ֱ5YA6Agugnh!|.0xKswb JHlCﵹڹx`d Y\R]Ygiq$30Gu8|#a|Sj@hTQbp`)R't9@n5Q* '&+Yqw 0=C."O=N\lZSTPsw D~N:N1PP[ui[$\qFC)'k[Z4oU0lη)L`8L"+1c{d @Ps - LY 'y3d6H ޗLjʩȊ:y3Ǯ<5;Ph97Ɍv(a!E\XSyn`rh!}<- )L`h p1m&Z^;5J(\126 k0`e+p ;s뿕~ p1M 9m! tISFs#+1:zq/} ) 7@-#(`'`3DJ_p·%BG1ժ,гkJ@Qv ~I >/Q,y[ZyG 1+UVޑ] R t m;g|*1)0S)p } }Th$,T"Θ׃/628^6ޱA\^%X6J` lZ|7@|adK 1-YHC)O ӒMDH5?# ")l~kn5j^ڥکڴ"10ɉ1B܊^{k6 r :D8R&ҹ~K wTyM^ m5`g* WS43SBA:VZ" E 4{/ j/ ~ R.:`5rÔl)p1ڦ @]r|DMHqsb^!JWX=yeKHL[i1:z6 |ebmePg 1X |: 梅F.䢠k!վ^7o֞^ 75y j^}ށ}Z=խ rb0+ީkPd`<%OۅɅsηi8[g.^کӎ3rrQ_Q[_p0@0 b 8X @@Ta  :ə$0!W^&*|ŋ /("E  |wԦmR ,x1p}@ADŽE;6ڵl@B$mtnqfݎk1.8ƷAu0C$n(C YhBcJ65PAl #RP d{m͆d?؉87pOJZ U,$HD/ν 3 }ۻ_ő#ֶ (I'Aw`FDܵOb4Os-B`XY,PnMD\`A!It!P`@Jh,t n[n37 p t1,XUlUZ1 ]Y 3grY Yda߂ ڧ'V3h&(Rɠeʃ&A֋P&t!DP .4emZ?$!PLP+xA: |Qj \P.AJXapvs0 )RU0ʘR q x0güޜ 4$*w 9%8_1*]ۘBE\1C T eQXMl.<*X 1T@ `"Tگ s lTDp7T@7 (]d5*5C^DeTdJ۰`1v DtEaN| ]mW3 w@q 04>QPR&ǔ%IDJ-KGsTdF H (sN|G)@H7T/:Uµ*lCXPa1C z = &B=fDb(Nwr}]s Ce \jFt%Xc1`PlH?d} %1@lp)@D0 jHPcIIIlV_,5*RiB`O8 c({E+^#ᅺ` sZyz <)0p83&Q U'[_u;&f\ R|Xn$]XH,,4Gh~ $P| (QPJ¸Znx,pP)\$ƛ8̘%",\! ~bP# H_UyQ &i:2}務1LPj̣;Q1V0AT&A[p @U}, KtUī8-2Dډ)ϚW iHS F,G/f̺v,?3A@ڟTBqT/4[g8PDOC{@!A`ր.n4apE(D"X@0_`YHy4*ê vLQ)j$PtZJM8i֢ k}Vp58͖O`7 xB0,pDsZ5PM}J$ DPGHsZZb 1LF`A&t`^A叁 TʁI69M0ҚQ6u(A*.DV.ǞL=C4Ps[CI I *T̋ݳ*ke.{Q D̴ij݆<2[Tf˧#7z*~Ɇ `K[λtFnuPubPGhqϚX.1z2vsCFSVo*p;%~fm_H/ bRW˭] THgɑP(ł诧&r `R FF42׭fa"TSMY£!=izX12f|V"gvZAb *`bκtӛdm]u5&bzq. z޼HK~nNaWǍ ᜗ƔAA.xA;Bw{u1V_3xn|ݐn4i hbÝ7RL(#%K_N o㉀23! r,؃N&#`ea L7 {7l5O9:޾6Sp@ `~C0dR ?EgUnENzfhuUY0majpRvCLpkohS}Qn$O}?Y 0qzt 0ԁ/!aʃm0zGFc8S11GGdz00ܲcw'bf;PɅ5e'? #e *eGSY kϲ6]~7$}Ga&p E~M4[Wj&KvaThM E\+pyT9 wd݁P0 Aljx`35yXՔ8YQ# ._T. @-cJH"5V"!*2iWD zRmPs-T8MN~F2pD /@6xH D q7ѴaXu@tAqѷ/i,  4fd LBv^&A$1a_ V%ch'R&ey0ۦ-Zrj ֡~Q!(LfRU2DaS(8 }قhDrN$J}1]V )Bhz16 Qr Ewp Gz#V&bc%tAs)FDL`&>s/| lbi$VI*.jsf_I^xpgMtEs =(8\6aUIpxf0m([C1@y5qo#@d(4#7qyD9 Mwsg3bQ  zxT(8ңmϨlF Fyr}XUqD29R Ʃ7` J1WP:9&@.0EbZwua!aMQ?T@8)_߲ c :<ʍ YAd33L}Sn ;rg x3P[QxOERiTz#r'j;:zJq/k&NVؤ@I*J:)6_ Iyy[xx 2(szf(su[r1&E: z06 յљ}r3 @h88 .r L% f~~ 0GI]@7}ʮO(+p$FJ;(2. QRQ* 1ZD(M ~?pC `MA*%[qi0ղX>`ilcA x//HP=gZf&@$y2˂ZYe{6٧õ`[ ;.2]"C2rȁ( NG|D@Ƹ3.黒;S^dR)Z sJ:s`JB"ibY@ۉ ;!GiJ0kyJKYC {:K;?&kj̻_[ȫ_++ e0Mʎq1h:6 c;,% XN%C6 (,$D8*,/)i68\(}4,$?9y*,7-:\H`"nk;3CLEF F</^{4Ŝ`!Dǒ k¿k$D cܼ c<,ă gsǹxEɹlSr7ǗɴYĦlw쾳>mƩ엣|Ǿ<ˇˀ\Ŷ,ż| [ɥlqL ,q{\<6ܼ@lŬˮ,B8<,S LLa{&G< }Ü}y L.L!-#M%m')+-/ 1-3M5m79;=? A-CMEmGIKMO Q-SMUmWY[]_ a-cMemgikmo q-sMumwy{}^ ؁-؃M؅m؇؉؋؍؏ ّ-ٓMٕmٟٗٙٛٝ ڡ-ڣMڥmڧکګڭگ ۱-۳M۵m۷۹ۻՁ;spam/images/white.gif0100644000567100000120000000061407675436652014600 0ustar jcameronwheelGIF89a00!,00x0I+8; di(.(3jߣj-^+!nj5zʤqsIx4rh.$ma(aK"|$ןRmzwfk,wxX9.UBPn ^t~{}/Bwuy~"½ɗ1uy$ҷxӇ~+vߥ{$爈ȣ[H`=|+7a;BB*nQ )Bɓ(S\y̌K;spam/images/settings.gif0100644000567100000120000000047407674516170015315 0ustar jcameronwheelGIF89a00UUU999rrr㎎!Made with GIMP,00I8ͻρ 1AS!p r+r}co3~ q ;"%BԆ>>'''˱rrrtttkkkݦwww껻qqq~~~sssyyyzzzϜ猌ߋ)))ܡ***+++ nnnlll___񓓓,,,mmmfffQQQ000eeeppp҈%%%HHHvvv"""FFFGGG!!!KKKEEE999###dddccc666hhh```OOO777???JJJ\\\<<1/L zDP@{G;"dM!VA04O90 JP@lT1! 0Q@ (H H4!NE5 M)E TFǺpPBD,X 4 pX-.䉀C|PBD1I/W/$3^D.iCE!'1L>~$@ FZ0q" A xp|sĴ3ڑ #!ȁ~c .<`@G #I0ӐYPE@Z!0@eBЄ">1}1p06 e~ TL@X,OFD 2TF(rxP5<`?a$!P3Qp b&J[bx@\F鍀 IB ;spam/images/header.gif0100664000567100000120000000134007723371741014676 0ustar jcameronwheelGIF89a00Ȁnnn[[[,00I8 !@eA0Cq61t#I!pR:@% ! XP]PYn ÔNJi|9N+dvduuxtwT~*}eYgVebUZCh)/DiIDC<;(Y3,?!( [0wa_DHBHe=?O&ׯ8i]Ce\^`^[Wcytdw#oT",(`@|ӧzd&qAC%Zt֬1`#f|1e0ӌi 74m^@3f "LTЕ F)#3VICKvEV4N V:y74|3A zK aC@˓i~M%3)+(j^ nq_(*U^ux5XKcs%1T)l5KH'< Xj3Mq@u/PB mB~ 4^?w~AF&~+(?_Gu0`]]!Q'>2 aL55RKH Zx-8z@p8L8iPVF?J(eШD_Kb3A#wȉx="OX# AAs\B{SDY'ne8"(G4D;spam/images/user.gif0100644000567100000120000000050407723371565014427 0ustar jcameronwheelGIF89a00UUU999rrr㎎!Made with GIMP!,00I8ͻρ 1AS!p r+r}co3~ q ;"%BԆ>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~,00 H*\ȰÆ"F|hPŋ-/Ǐ =;}:\Rn\U^˛G; aT(?h"Jt-ڲ,!ѳTS\-`PBe-XJd?T&RjQ -<{ -Lldf"xqE#zR%Q seԌ(G+7G}*×H'}ۇsb 0H1C " pܚ>P #PCJSu@Ds '.3( ֹ' kڰD\q-\#-cC(LO>8>w*#C &@.܄t&p1 z)eC .l pS,? #ݠw806 "X,G3  `82c+֠7&=O(-:2pBؤ#,l9 ?D0 xؒ%f̰B гe150 x^)NDP |+9 ?|B 2X2* '@?堰BÉ̳3&4~- ?1E&:`>b-d$Ґ6؃O>(c̔*B m?0% (XˊF߂${>0/pB`p'd!=ŀD 6PA-3^>G:2 )pDQ6sc? 8z@G&x! : pF`;!Փ"wW9~,8#KB ǂBLV@  {Ha016 C r3׸ n"*A( @|aB X+1Zz~BRd2~8/ b^ % bzWB~406`=`.Ȃ1cS jRAb Nk<(() V@%/F hm6xuHKxv`ܨ;|`= $8=[Ђ# Ul= , p`'RъWB,PqB! E B  `<#`=u@C:!^Gh!؋Z* etB,O GJYA;spam/images/smallicon.gif0100664000567100000120000000220007675513512015423 0ustar jcameronwheelGIF87agGX#r5$X,1Bs;(SB`ak<( ;86<7-;fEU\b[Ex_\I?fJxyx|RK4^curkn*X^Ks<'s:'gd2|wkzXjTG:94gG;aS=kJ+;"o?3w*-;&HRUpro"8Hv=)eGQ_|{tA;%Ui^pJ>67vsF@@<6 g4'sPⱧb{S۩P6f!7;70~~u_AO!<;4xxr~~xXM+U[~752GEE 9<@[`}S"NJ1cimer3#=+CDQT=SA;Ajxrg@=0'(J?@PyWanLuVxo`@@@ǺX:,tUH77-gd1>=7A4HTyk*Ƹcs>)gI9=8IS\s>=:rrmmJ`I77=^*(!)o]F*}yq$3i0"M6.IGKbvp`,wHpǯ_ VJXpBp+NX l@cBs0CE0ZDJRHfV 6I@c(~q* 30"#*3(pI%ɋ7%Unq@C"U)@b1%RCz!'xb,^#V`0AÃ? CS,Ӏy\iΡDGJ$ H F[,ZH#̱GD.RЍf0K}^=(dPW@GTQdŕ% Y2 -8   }t*.ti_*]=B/Y9dP=U5oT9C$!,00 HÇ#J0ŋ3jQ)2Ȏ Xi⁗/q 8$PA D0L*̬)&ɑ%qZ!4lʡ/"Y1F!D\ADF NHq@Ҳf/XqE .^pͼc00FK\ w#Ρ$EB MM/HAH 8@HH۵sBpjڤ,<>IH0w&, &#"կ#  ^"oǐS6 F}!TJV؇rWDłX\Ԡ0Q hj[E\@l]XxҊ+z!}a""q!F!ّc# 9@QyVjDFf8ّg!3C;Q%GkŜs8trnnGa&ṟtD*餏 Pħwhy ԇW?r Z!\B!F"(#` )L[E"$ ,AJ@%\u &ZlB '+_'`eUm(ȫ( "T) *J +",JK-`KdzBIȸ+r\./z.֬)/2' "D't20C'mP02;0,K,;spam/images/mail.gif0100644000567100000120000000047207715735565014404 0ustar jcameronwheelGIF89a00fff!,00I8ͻ`(dihlptmxpH,`\6(@'FL'+ąlMyN8r[{{}~ytnUf@NChiBe\Mh?AjjOzi@]Gz»DOPkPE׽ͱޑɾut^R2 H7D;spam/images/.xvpics/0040755000567100000120000000000007723371711014351 5ustar jcameronwheelspam/images/.xvpics/score.gif0100664000567100000120000000450607723371656016167 0ustar jcameronwheelP7 332 #IMGINFO:48x48 Indexed (1924 bytes) #END_OF_COMMENTS 48 48 255 I$II۶IH%I۶%HI%۶ڶ%HIIڶ%HII۶I$II۶I$II۶IH%I۶%HI%۶ڶ%HIIڶ%HII۶I$II۶I$II۶IH%I۶%HI%۶ڶ%HIIڶ%HII۶I$II۶I$II۶IH%I۶%HI%۶ڶ%HIIڶ%HII۶I$II۶۶I$II۶%H%I۶ڶ%HI%۶ڶ%HIIڶI$II۶HI$I۶I$II۶%H%I۶ڶ%HI%۶ڶ%HIIڶI$II۶HI$I۶I$II۶%H%I۶ڶ%HI%۶ڶ%HI۶$IIIڷH%II۶I$II۶%H%I۶ڶllnHII۶$I%II$II۶IH%I۶%H$$%۶HI$۶۶I$II۶IH%I۶ۑ%$$l%II۶I$II۶IH%I۶%m%$$$$ڒI$nH%IڷI$II۶IH%I۶%ڶۑm%$$$II۶۶I$II۶%H%Iۑnڶ$IHI۶I$II۶%H%ImnڷHI%I۶I$II۶%H%Iڒmm$ڶ$IHI۶I$II۶%H%Iڷmnnmmmmڷ$IIHI$II۶IH%I۶%ۑnۑm$%H%ڶI$II۶IH%IۑIm$$$$$II۶I$II۶IH%I۶ڷۑImnm$$II۶I$II۶IH%InmImۑI%$IIڷ۶I$II۶%ImmmڶI$۶$III۶I$II۶$mmڒIHI$I۶I$II۶mI$%$I$۶$III۶I$II۶nmmm$nIHH%III$II۶IHmmm$mI%H%I۶I$II۶Imnےlm$mI%$II۶I$II۶mmۑmm$mI%$II۶I$II۶ۑ$۶mm$mI%H%I۶۶I$IIn$ڑI$ے$%۶$IIH۶I$Iڶ%lm$m%۶$IIH۶I$ۑnڒI$mIH%IH۶I$I$m۶l$mIH%IHI$II۶Inmےlm$m%$II۶I$II۶m%۶$mۑmm$mI%HIڶI$II۶$mmIۑmm$m$%HI%۶ڷI$II۶%I$$HےڒI$ےHn$III۶۶I$I$mnmۑmm$mInڷH%IH۶I$Im$I%$۵I$mInڶ$I%H۶I$I$%۶۶mHn$$$m$II%۶I$II$IڶHI۶$%m۶$I$II$II۶$%$۶$nڶڷڷHI$IH%۶۶I$II۶Iڷ$۶m$I%m$I%IڷڶI$II۶IH%I۶%HI%۶mmn$II$۶۶I$II۶IH%I۶%HI%۶ڶ%HIIڶ%HII۶I$II۶۶I$II۶%H%I۶ڶ%HI%۶ڶ%HIIڶI$II۶HI$I۶I$II۶%H%I۶ڶ%HI%۶ڶ%HIIڶI$II۶HI$I۶I$II۶%H%I۶ڶ%HI%۶ڶ%HIIڶI$II۶HI$I۶I$II۶%H%I۶ڶ%HI%۶ڶ%HIIڶI$II۶HI$Ispam/images/.xvpics/header.gif0100664000567100000120000000450507723371741016276 0ustar jcameronwheelP7 332 #IMGINFO:48x48 Indexed (736 bytes) #END_OF_COMMENTS 48 48 255 ڶڶڒڒnmnۑڷmۑڒnڒڒmڷڷڷڶ۶ڷڶ۶ڷڶڷڶ۶ڷnۑڷڶڶmۑ۶mnۑۑm۶۶ڒۑmۑۑ۵nڒ۶ۑۑڷHۑڒIIn۶۶H۶ڷۑڒ۵۶ڷڶڷڶnڷڶ۶mڶmۑnH۶ڷ۶ڷڒۑ۶ۑۑڒ۵ےm۶I۶Iڒڶmmۑڶmۑ۶ڶm۶ۑmڶ۶ڷڷl۷ۑےI۶ڶۑ۶ۑڒۑ۶ۑImۑۑۑnڒ۶Iڒڒۑۑۑmnm۶ڷmڒ۶ڷn۶ۑmnnڒڒۑnnmۑۑۑmۑmڶےnۑmnۑڒ۶mm۶۵Iڶۑۑۑmڶspam/edit_user.cgi0100775000567100000120000000632607705401073014165 0ustar jcameronwheel#!/usr/local/bin/perl # edit_user.cgi # Display other misc user-level options require './spam-lib.pl'; &can_use_check("user"); &header($text{'user_title'}, ""); print "
\n"; $conf = &get_config(); print "$text{'user_desc'}

\n"; &start_form("save_user.cgi", $text{'user_header'}); $dns = lc(&find_value("dns_available", $conf)); $dns = "test" if (!$dns && $config{'defaults'}); print " $text{'user_dns'} \n"; printf " %s\n", $dns eq 'yes' ? "checked" : "", $text{'yes'}; printf " %s\n", $dns eq 'no' ? "checked" : "", $text{'no'}; if (!$config{'defaults'}) { printf " %s (%s)\n", !$dns ? "checked" : "", $text{'default'}, $text{'user_dnstest'}; } printf " %s\n", $dns =~ /^test/ ? "checked" : "", $text{'user_dnslist'}; printf " \n", $dns =~ /^test:\s*(.*)/ ? $1 : ""; print "


\n"; print " $text{'user_razor'} \n"; $razor = &find("razor_timeout", $conf); &opt_field("razor_timeout", $razor, 5, 10); print " \n"; print "
\n"; print " $text{'user_dcc'} \n"; $dcc = &find("dcc_path", $conf); &opt_field("dcc_path", $dcc, 40, $text{'user_inpath'}, 1); print &file_chooser_button("dcc_path", 0); print " \n"; print " $text{'user_bodymax'} \n"; $bodymax = &find("dcc_body_max", $conf); &opt_field("dcc_body_max", $bodymax, 6, 999999); print " \n"; print " $text{'user_timeout'} \n"; $timeout = &find("dcc_timeout", $conf); &opt_field("dcc_timeout", $timeout, 5, 10); print " \n"; print " $text{'user_fuz1max'} \n"; $fuz1max = &find("dcc_fuz1_max", $conf); &opt_field("dcc_fuz1_max", $fuz1max, 6, 999999); print " \n"; print " $text{'user_fuz2max'} \n"; $fuz2max = &find("dcc_fuz2_max", $conf); &opt_field("dcc_fuz2_max", $fuz2max, 6, 999999); print " \n"; print " $text{'user_dheader'} \n"; $dheader = &find("dcc_header", $conf); &yes_no_field("dcc_header", $dheader, 0); print " \n"; print "
\n"; print " $text{'user_pyzor'} \n"; $pyzor = &find("pyzor_path", $conf); &opt_field("pyzor_path", $pyzor, 40, $text{'user_inpath'}, 1); print &file_chooser_button("pyzor_path", 0); print " \n"; print " $text{'user_pbodymax'} \n"; $pbodymax = &find("pyzor_body_max", $conf); &opt_field("pyzor_body_max", $pbodymax, 6, 999999); print " \n"; print " $text{'user_ptimeout'} \n"; $ptimeout = &find("pyzor_timeout", $conf); &opt_field("pyzor_timeout", $ptimeout, 5, 10); print " \n"; print " $text{'user_pheader'} \n"; $pheader = &find("pyzor_header", $conf); &yes_no_field("pyzor_header", $pheader, 0); print " \n"; &end_form(undef, $text{'save'}); print "
\n"; &footer("", $text{'index_return'}); spam/lang/0040775000567100000120000000000007752544432012441 5ustar jcameronwheelspam/lang/en0100664000567100000120000002744407752544415012777 0ustar jcameronwheelindex_title=SpamAssassin Mail Filter index_ecmd=The SpamAssassin command $1 was not found on your system. Maybe it is not installed, or your module configuration is incorrect. index_econfig=The SpamAssassin local configuration file or directory $1 was not found on your system. Maybe SpamAssassin is not installed, or your module configuration is incorrect. index_version=SpamAssassin version $1 index_warn_usermin=SpamAssassin does not appear to be set up in your Procmail configuration file $2 or the global file $1, so any configuration done using this module will have no effect unless SpamAssassin has been setup globally. index_warn_webmin=SpamAssassin does not appear to be set up in the system's Procmail configuration file $1, so any configuration done using this module will have no effect unless users have it set up individually. index_return=module index index_apply=Apply Changes index_applydesc=Click this button to apply the current SpamAssassin configuration by sending a HUP signal to all running $1 processes. white_title=Allowed and Denied Addresses white_desc=The tables on this page allow you to specify From: and To: addresses for email that is always or never categorized as spam. Any other email will be processed as normal by SpamAssassin's rules. All email addresses can contain wildcards, like *@foo.com or *.foo.com to match entire domains. white_header=Email addresses to categorize as spam white_from=From: addresses to never classify as spam white_gfrom=System-wide addresses to never classify as spam white_addr=Address white_rcvd=From: addresses to never classify as spam, depending on Received: domain white_rcvdhost=Source domain white_unfrom=Exceptions for From: addresses to never classify as spam white_gunfrom=System-wide exceptions for addresses to never classify as spam white_black=From: addresses to always classify as spam white_gblack=System-wide addresses to always classify as spam white_unblack=Exceptions for From: addresses to always classify as spam white_gunblack=System-wide exceptions for addresses to always classify as spam white_to=To: or Cc: addresses to allow some or all spam to white_level=Allow white_level0=Some spam white_level1=More spam white_level2=All spam white_err=Failed to save white and black lists white_efrom='$1' is not a valid From: address white_ercvd='$1' is not a valid domain name white_importdesc=This form can be used to add email addresses from a file (such as an exported Outlook or Eudora address book) to the allowed list. white_import=Import addresses from file white_sort=Sort allowed addresses after import? white_importok=Import Now white_return=allowed and denied addresses score_title=Spam Classification score_desc=SpamAssassin assigns a score to each message based on its content and headers. The options on this page determine the score above which a message is considered spam, and some of the methods via which that score is calculated. score_header=Spam message classification options score_score=SpamAssassin test scores score_name=Test name score_points=Points score_hits=Hits above which a message is considered spam score_rbl=Skip RBL open-relay check? score_mx=Number of times to check From: address MX score_mxdelay=Seconds to wait between MX checks score_langs=Languages in email that are not considered potential spam score_langsall=All languages score_langssel=Selected languages .. score_locales=Character sets in email that are not considered potential spam score_localesall=All character sets score_localessel=Selected character sets .. score_auto=Whitelist score factor score_timeout=Seconds to wait for RBL queries score_received=Number of Received: headers to check with RBL score_describe=Test descriptions for report score_descr=Description score_err=Failed to save message scoring score_ename='$1' is not a valid test name score_epoints='$1' is not a valid number of points score_edesc=Missing description for score '$1' score_ehits=Missing or invalid number of hits above which a message is considered spam score_eauto=Missing or invalid whitelist score factor (must be between 0 and 1) score_emx=Missing or invalid number of times to check From: address MX score_emxdelay=Missing or invalid seconds to wait between MX checks score_etimeout=Missing or invalid seconds to wait for RBL queries score_ereceived=Missing or invalid number of Received: headers to check with RBL report_title=Message Modification report_desc=The options on this page control the modifications that SpamAssassin makes to the headers and body of all messages that it analyzes, and modifications that it makes to those classified as spam. report_header=Analysed and spam message modification options report_report=Report attached to messages exceeding the spam threshold report_clear=Use just text below .. report_noclear=Add text below to default message .. report_terse=Report attached to spam messages when in terse mode report_rewrite=Modify Subject: header of spam? report_subject=Text to prepend to spam Subject: header report_rheader=Put report in X-Spam-Status: header instead of body? report_useterse=Only generate terse report? report_fold=Split X-Spam-Status: header over multiple lines? report_detail=Include details of spam phrases? report_stars=Include X-Spam-Level: header? report_char=X-Spam-Level: header character report_defang=Change MIME type of spam to text/plain? report_err=Failed to save spam report options report_echar=A single character must be entered for the X-Spam-Level: header user_title=Miscellaneous User Options user_desc=The options on this page are mostly related to the paths and settings that SpamAssassin uses for the external spam identification packages Razor, DCC and Pyzor. You can also tell SpamAssassin if it will be able to perform DNS lookups or not. user_header=Miscellaneous user-level options user_dns=Can SpamAssassin do DNS lookups? user_dnslist=Test by checking servers user_dnstest=Test user_razor=Razor request timeout in seconds user_dcc=Location of DCC client program user_inpath=In PATH user_bodymax=DCC body checksum count before match user_fuz1max=DCC fuz1 checksum count before match user_fuz2max=DCC fuz2 checksum count before match user_timeout=DCC request timeout in seconds user_dheader=Add DCC header to messages? user_pyzor=Location of Pyzor client program user_pbodymax=Pyzor body checksum count before match user_ptimeout=Pyzor request timeout in seconds user_pheader=Add Pyzor header to messages? user_err=Failed to save user options user_etimeout='$1' is not a valid timeout user_epath='$1' is not a valid client program path user_emax='$1' is not a valid checksum count header_title=Header and Body Tests header_desc=This page allows you to define additional tests that SpamAssassin will apply to email, based on message headers, the body content, URLs found in the body, or combinations of other tests. The name assigned to each test is up to you, but is usually something like CONTAINS_FOO. The actual score that SpamAssassin adds to messages matching a test can be set by entering your own or built-in test names in the tables at the bottom of the page. header_header=Additional header and body tests header_allow=Allow users to define tests? header_test=Header tests header_tname=Test name header_name=For header header_op=Check if header_op0=Matches.. header_op1=Doesn't match.. header_op2=Exists header_op3=Evaluate.. header_pat=Regular expession header_default=Default value header_uri=Email URL tests header_body=Body tests header_mode=Body part header_mode0=Plain text header_mode1=All text header_mode2=Raw text header_mode3=Entire mail header_meta=Tests based on others header_bool=Boolean test expression header_err=Failed to save tests header_ename='$1' is not a valid test name header_eeval='$1' is not a valid evaluation function header_eheader='$1' is not a valid email header header_eregexp='$1' is not a valid regular expression (must be like /expression/) header_emeta=Missing test expression for test '$1' priv_title=Miscellaneous Privileged Options priv_desc=The options on this can only be set globally, rather than in individual users' configuration files. They control with paths to various configuration and logging file. priv_header=Miscellaneous privilege-level settings priv_white=Automatic whitelist file path priv_mode=Whitelist octal file mode priv_dcc=DCC command arguments priv_log=Timing log files path priv_razor=Razor configuration file path priv_phrases=Spam indicator phrases priv_phrase=Two-word phrase priv_score=Score priv_highest=Highest phrase score priv_err=Failed to save privileged options priv_epath='$1' is not a valid path priv_emode='$1' is not a 4-digit octal file mode priv_eargs='$1' is not a valid list of arguments priv_emscore='$1' is not a valid highest phrase score priv_ephrase='$1' is not a valid two-word spam phrase priv_escore=Missing or invalid score for spam phrase '$1' usually=Usually $1 ecannot=You are not allowed to use this page setup_title=Setup Procmail For SpamAssassin setup_desc_webmin=This form can be used to setup Procmail in $1 to run SpamAssassin on all email messages received by your system. However, this will only have any effect if your mail server has been configured to use Procmail for local delivery, or for users whose .forward files are set up to run Procmail. setup_desc_usermin=This form can be used to setup Procmail in $1 to run SpamAssassin on all email messages sent to your account. However, this will only have any effect if the mail server has been configured to use Procmail for local delivery, or if your .forward files is set up to feed all email to Procmail. setup_head=All messages processed by SpamAssassin will have the X-Spam headers set, so that they can be further filtered by mail clients. setup_rel=Any non-absolute mail file or directory paths entered above will be relative to the home directory of the user receiving email. setup_to=Action for messages classified as spam setup_null=Throw away setup_default=Deliver normally setup_file=Append to mbox-format mail file .. setup_maildir=Append to Qmail-style mail directory .. setup_mhdir=Append to MH-style mail directory .. setup_ok=Setup Procmail for SpamAssassin setup_err=Failed to setup SpamAssassin setup_efile=Missing or invalid mbox-format file setup_emaildir=Missing or invalid Qmail mail directory setup_emhdir=Missing or invalid MH mail directory log_white=Modified allowed and denied addresses log_score=Modified spam classification log_report=Modified message modification log_user=Modified miscellaneous user options log_header=Modified header and body tests log_priv=Modified miscellaneous privileged options log_setup=Setup Procmail for SpamAssassin log_import=Imported $1 allowed addresses import_title=Import Addresses import_err=Failed to import addresses import_efile=No file to import from selected import_enone=No email addresses found in file import_ok1=$2 email addresses were found in the file, of which $1 were new and have been added to the alllowed addresses list. import_ok2=$1 email addresses were found in the file, but they were all already in the allowed addresses list. mail_title=Spam Mail mail_desc=This page lists messages that have been classified as spam, and are awaiting some action. Messages that have been incorrectly indentified can be moved to your Inbox, while those that are really spam can be deleted. mail_level=Level mail_level2=Spam level mail_inbox=Move to Inbox mail_whitelist=Move to Inbox and Allow Sender mail_blacklist=Delete and Report to SpamAssassin mail_return=spam mail list mail_pos=Spam messages $1 to $2 of $3 mail_none=There are no messages in your spam folder mail_refresh=Refresh mail_will=Automatic refresh in $1 minutes mail_wills=Automatic refresh in $1 seconds process_eclean=An error occurred removing the SpamAssassin headers from this email process_ereport=Failed to report email to SpamAssassin : $1 apply_err=Failed to apply changes apply_none=No SpamAssassin daemon processes found! spam/save_score.cgi0100775000567100000120000000323307747562376014351 0ustar jcameronwheel#!/usr/local/bin/perl # save_score.cgi # Save message scoring options require './spam-lib.pl'; &error_setup($text{'score_err'}); &can_use_check("score"); &ReadParse(); &lock_spam_files(); $conf = &get_config(); &parse_opt($conf, "required_hits", \&hits_check); &parse_opt($conf, "auto_whitelist_factor", \&auto_check); &parse_opt($conf, "check_mx_attempts", \&mx_check); &parse_opt($conf, "check_mx_delay", \&mxdelay_check); &parse_yes_no($conf, "skip_rbl_checks"); &parse_opt($conf, "rbl_timeout", \&timeout_check); &parse_opt($conf, "num_check_received", \&received_check); if ($in{'langs_def'} == 2) { &save_directives($conf, "ok_languages", [ ], 1); } elsif ($in{'langs_def'} == 1) { &save_directives($conf, "ok_languages", [ "all" ], 1); } else { &save_directives($conf, "ok_languages", [ join(" ", split(/\0/, $in{'langs'})) ], 1); } if ($in{'locales_def'} == 2) { &save_directives($conf, "ok_locales", [ ], 1); } elsif ($in{'locales_def'} == 1) { &save_directives($conf, "ok_locales", [ "all" ], 1); } else { &save_directives($conf, "ok_locales", [ join(" ", split(/\0/, $in{'locales'})) ], 1); } &flush_file_lines(); &unlock_spam_files(); &webmin_log("score"); &redirect(""); sub hits_check { $_[0] =~ /^\d+(\.\d+)?$/ || &error($text{'score_ehits'}); } sub auto_check { $_[0] =~ /^\d+(\.\d+)?$/ && $_[0] >= 0 && $_[0] <= 1 || &error($text{'score_eauto'}); } sub mx_check { $_[0] =~ /^\d+$/ || &error($text{'score_emx'}); } sub mxdelay_check { $_[0] =~ /^\d+$/ || &error($text{'score_emxdelay'}); } sub timeout_check { $_[0] =~ /^\d+$/ || &error($text{'score_etimeout'}); } sub received_check { $_[0] =~ /^\d+$/ || &error($text{'score_ereceived'}); } spam/locales0100664000567100000120000000007107674516170013061 0ustar jcameronwheelja Japanese ko Korea ru Cyrillic th Thai zh Chinese spam/edit_score.cgi0100775000567100000120000000672707705401046014327 0ustar jcameronwheel#!/usr/local/bin/perl # edit_score.cgi # Display a form for editing spam scoring options require './spam-lib.pl'; &can_use_check("score"); &header($text{'score_title'}, ""); print "
\n"; $conf = &get_config(); print "$text{'score_desc'}

\n"; &start_form("save_score.cgi", $text{'score_header'}); print " $text{'score_hits'} "; $hits = &find("required_hits", $conf); &opt_field("required_hits", $hits, 5, "5"); print " \n"; print " $text{'score_auto'} "; $auto = &find("auto_whitelist_factor", $conf); &opt_field("auto_whitelist_factor", $auto, 5, "0.5"); print " \n"; print " $text{'score_mx'} "; $mx = &find("check_mx_attempts", $conf); &opt_field("check_mx_attempts", $mx, 4, "2"); print " \n"; print " $text{'score_mxdelay'} "; $mxdelay = &find("check_mx_delay", $conf); &opt_field("check_mx_delay", $mxdelay, 4, "2"); print " \n"; print " $text{'score_rbl'} "; $rbl = &find("skip_rbl_checks", $conf); &yes_no_field("skip_rbl_checks", $rbl, 0); print " \n"; print " $text{'score_timeout'} "; $timeout = &find("rbl_timeout", $conf); &opt_field("rbl_timeout", $timeout, 5, "30"); print " \n"; print " $text{'score_received'} "; $received = &find("num_check_received", $conf); &opt_field("num_check_received", $received, 5, 2); print " \n"; print "


\n"; @langs = &find_value("ok_languages", $conf); %langs = map { $_, 1 } split(/\s+/, join(" ", @langs)); $lmode = !@langs ? 2 : $langs{'all'} ? 1 : 0; print " $text{'score_langs'} \n"; printf " %s (%s)
\n", $lmode == 2 ? 'checked' : '', $text{'default'}, $text{'score_langsall'}; printf " %s
\n", $lmode == 1 ? 'checked' : '', $text{'score_langsall'}; printf " %s
\n", $lmode == 0 ? 'checked' : '', $text{'score_langssel'}; print " \n"; @locales = &find_value("ok_locales", $conf); %locales = map { $_, 1 } split(/\s+/, join(" ", @locales)); $lmode = !@locales ? 2 : $locales{'all'} ? 1 : 0; print " $text{'score_locales'} \n"; printf " %s (%s)
\n", $lmode == 2 ? 'checked' : '', $text{'default'},$text{'score_localesall'}; printf " %s
\n", $lmode == 1 ? 'checked' : '', $text{'score_localesall'}; printf " %s
\n", $lmode == 0 ? 'checked' : '', $text{'score_localessel'}; print " \n"; &end_form(undef, $text{'save'}); print "
\n"; &footer("", $text{'index_return'}); spam/process.cgi0100755000567100000120000000456207741173707013670 0ustar jcameronwheel#!/usr/local/bin/perl # process.cgi # Delete, move or whitelist messages require './spam-lib.pl'; &foreign_require("mailbox", "mailbox-lib.pl"); $folder = &spam_file_folder(); &disable_indexing($folder); &ReadParse(); @delete = sort { $a <=> $b } split(/\0/, $in{'d'}); if ($in{'inbox'} || $in{'whitelist'}) { # Move mails to inbox @delete || &error($mailbox::text{'delete_emnone'}); @folders = &mailbox::list_folders(); ($mfolder) = grep { $_->{'inbox'} } @folders; @mail = &mailbox::mailbox_list_mails($delete[0], $delete[@delete-1], $folder); foreach $d (@delete) { push(@movemail, $mail[$d]); push(@addrs, map { $_->[0] } &mailbox::split_addresses($mail[$d]->{'header'}->{'from'})); } # Pass through spamassassin to remove headers, then add to Inbox &mailbox::lock_folder($mfolder); foreach $d (@movemail) { local $temp = &tempname(); &mailbox::send_mail($d, $temp); local $newmail = &mailbox::read_mail_file("$config{'spamassassin'} --remove-markup <$temp |"); $newmail || &error($text{'process_eclean'}); &mailbox::write_mail_folder($newmail, $mfolder); unlink($temp); } &mailbox::unlock_folder($mfolder); # Delete from spam folder &mailbox::lock_folder($folder); &mailbox::mailbox_delete_mail($folder, $mfolder, @movemail); &mailbox::unlock_folder($folder); if ($in{'whitelist'}) { # Add senders to whitelist &lock_file($local_cf); $conf = &get_config(); @from = map { @{$_->{'words'}} } &find("whitelist_from", $conf); %already = map { $_, 1 } @from; @newaddrs = grep { !$already{$_} } &unique(@addrs); push(@from, @newaddrs); &save_directives($conf, 'whitelist_from', \@from, 1); &flush_file_lines(); &unlock_file($local_cf); } } else { # Delete messages @delete || &error($mailbox::text{'delete_enone'}); @mail = &mailbox::mailbox_list_mails($delete[0], $delete[@delete-1], $folder); foreach $d (@delete) { push(@delmail, $mail[$d]); } &mailbox::lock_folder($folder); &mailbox::mailbox_delete_mail($folder, @delmail); &mailbox::unlock_folder($folder); if ($in{'razor'}) { # Report to razor local $temp = &tempname(); foreach $d (@delmail) { &mailbox::send_mail($d, $temp); local $out = `$config{'spamassassin'} --report <$temp 2>&1`; unlink($temp); if ($? || $out =~ /failed/i) { &error(&text('process_ereport', "
$out
")); } } } } &redirect("mail.cgi"); spam/edit_header.cgi0100775000567100000120000001177707752663451014461 0ustar jcameronwheel#!/usr/local/bin/perl # edit_header.cgi # Display extra header and body test require './spam-lib.pl'; &can_use_check("header"); &header($text{'header_title'}, ""); print "
\n"; $conf = &get_config(); print "$text{'header_desc'}

\n"; &start_form("save_header.cgi", $text{'header_header'}); if (!$module_info{'usermin'}) { print " $text{'header_allow'} "; $allow = &find("allow_user_rules", $conf); &yes_no_field("allow_user_rules", $allow, 0); print " \n"; } @header = &find("header", $conf); print " $text{'header_test'} \n"; &edit_table("header", [ $text{'header_tname'}, $text{'header_name'}, $text{'header_op'}, $text{'header_pat'}, $text{'header_default'} ], [ map { [ &split_header($_->{'value'}) ] } @header ], [ ], \&header_conv, 2); print " \n"; print "


\n"; push(@body, map { [ &split_body($_->{'value'}), 0 ] } &find("body", $conf)); push(@body, map { [ &split_body($_->{'value'}), 1 ] } &find("rawbody", $conf)); push(@body, map { [ &split_body($_->{'value'}), 2 ] } &find("fullbody", $conf)); push(@body, map { [ &split_body($_->{'value'}), 3 ] } &find("full", $conf)); print " $text{'header_body'} \n"; &edit_table("body", [ $text{'header_tname'}, $text{'header_mode'}, $text{'header_op'}, $text{'header_pat'} ], \@body, [ ], \&body_conv, 2); print "
\n"; @uri = &find("uri", $conf); print " $text{'header_uri'} \n"; &edit_table("uri", [ $text{'header_tname'}, $text{'header_pat'} ], [ map { $_->{'words'} } @uri ], [ 20, 40 ], undef, 2); print " \n"; print "
\n"; @meta = &find("meta", $conf); print " $text{'header_meta'} \n"; &edit_table("meta", [ $text{'header_tname'}, $text{'header_bool'} ], [ map { $_->{'value'} =~ /^(\S+)\s*(.*)$/ ? [ $1, $2 ] : [ ] } @meta ], [ 20, 40 ], undef, 2); print "
\n"; @score = &find("score", $conf); print " $text{'score_score'} \n"; &edit_table("score", [ $text{'score_name'}, $text{'score_points'} ], [ map { $_->{'words'} } @score ], [ 30, 6 ]); print " \n"; @describe = &find("describe", $conf); print " $text{'score_describe'} \n"; &edit_table("describe", [ $text{'score_name'}, $text{'score_descr'} ], [ map { $_->{'value'} =~ /^(\S+)\s*(.*)/ ? [ $1, $2 ] : [ ] } @describe ], [ 30, 40 ]); print " \n"; &end_form(undef, $text{'save'}); print "
\n"; &footer("", $text{'index_return'}); # header_conv(col, name, size, value, &values) sub header_conv { if ($_[0] == 0) { return sprintf "", &html_escape($_[3]); } elsif ($_[0] == 1) { local $h = $_[3] =~ /^exists:(\S+)$/ ? $1 : $_[3] =~ /^eval:/ ? "" : $_[3]; return sprintf "", &html_escape($h); } elsif ($_[0] == 2) { local $rv = "\n"; return $rv; } elsif ($_[0] == 3) { return sprintf "", &html_escape($_[4]->[1] =~ /^eval:(\S+)/ ? $1 : $_[3]); } elsif ($_[0] == 4) { return sprintf "", &html_escape($_[3]); } } # body_conv(col, name, size, value, &values) sub body_conv { if ($_[0] == 0) { return sprintf "", &html_escape($_[4]->[0]); } elsif ($_[0] == 1) { local $rv = "\n"; return $rv; } elsif ($_[0] == 2) { local $rv = "\n"; return $rv; } elsif ($_[0] == 3) { return sprintf "", &html_escape($_[4]->[1] =~ /^eval:(\S+)$/ ? $1 : $_[4]->[1]); } } sub split_header { if ($_[0] =~ /^(\S+)\s+(\S+)\s+(\S+)\s+(\/.*\/\S*)\s*(if-unset:\s*(.*))?/) { return ($1, $2, $3, $4, $6); } else { return ( ); } } sub split_body { if ($_[0] =~ /^(\S+)\s+((\/.*\/\S*)|(eval:\S+))/) { return ($1, $2); } else { return ( ); } } spam/config0100664000567100000120000000035407747704037012712 0ustar jcameronwheellocal_cf=.spamassassin/user_prefs spamassassin=spamassassin global_procmailrc=/etc/procmailrc global_cf=/etc/mail/spamassassin show_global=0 avail_icons=white,score,report,user,header,setup,mail warn_procmail=1 index_spam=0 call_spam=1 spam/edit_white.cgi0100775000567100000120000001054507731252510014324 0ustar jcameronwheel#!/usr/local/bin/perl # edit_white.cgi # Display white and black lists of to and from addresses require './spam-lib.pl'; &can_use_check("white"); &header($text{'white_title'}, ""); print "
\n"; $conf = &get_config(); print "$text{'white_desc'}

\n"; &start_form("save_white.cgi", $text{'white_header'}); print " $text{'white_from'} ", "$text{'white_unfrom'} \n"; print " \n"; @from = &find("whitelist_from", $conf); &edit_textbox("whitelist_from", [ map { @{$_->{'words'}} } @from ], 40, 5); print " \n"; @un = &find("unwhitelist_from", $conf); &edit_textbox("unwhitelist_from", [ map { @{$_->{'words'}} } @un ], 40, 5); print " \n"; if ($config{'show_global'}) { print " $text{'white_gfrom'} ", "$text{'white_gunfrom'} \n"; $gconf = &get_config($config{'global_cf'}); print " \n"; @gfrom = &find("whitelist_from", $gconf); &edit_textbox("gwhitelist_from", [ map { @{$_->{'words'}} } @gfrom ], 40, 5); print " \n"; @gun = &find("unwhitelist_from", $gconf); &edit_textbox("gunwhitelist_from", [ map { @{$_->{'words'}} } @gun ], 40, 5); print " \n"; print "\n"; } else { print " $text{'white_rcvd'} \n"; print " \n"; @rcvd = &find("whitelist_from_rcvd", $conf); &edit_table("whitelist_from_rcvd", [ $text{'white_addr'}, $text{'white_rcvdhost'} ], [ map { $_->{'words'} } @rcvd ], [ 40, 30 ], undef, 3); print " \n"; } print "


\n"; print " $text{'white_black'} ", "$text{'white_unblack'} \n"; print " \n"; @from = &find("blacklist_from", $conf); &edit_textbox("blacklist_from", [ map { @{$_->{'words'}} } @from ], 40, 5); print " \n"; @un = &find("unblacklist_from", $conf); &edit_textbox("unblacklist_from", [ map { @{$_->{'words'}} } @un ], 40, 5); print " \n"; if ($config{'show_global'}) { print " $text{'white_gblack'} ", "$text{'white_gunblack'} \n"; print " \n"; @gfrom = &find("blacklist_from", $gconf); &edit_textbox("gblacklist_from", [ map { @{$_->{'words'}} } @gfrom ], 40, 5); print " \n"; @gun = &find("gunblacklist_from", $gconf); &edit_textbox("gunblacklist_from", [ map { @{$_->{'words'}} } @gun ], 40, 5); print " \n"; print "\n"; } else { print "
\n"; push(@to, map { [ $_, 0 ] } map { @{$_->{'words'}} } &find("whitelist_to", $conf)); push(@to, map { [ $_, 1 ] } map { @{$_->{'words'}} } &find("more_spam_to", $conf)); push(@to, map { [ $_, 2 ] } map { @{$_->{'words'}} } &find("all_spam_to", $conf)); print " $text{'white_to'} \n"; print " \n"; &edit_table("whitelist_to", [ $text{'white_addr'}, $text{'white_level'} ], \@to, [ 40, 0 ], \&whitelist_to_conv, 3); print " \n"; } &end_form(undef, $text{'save'}); # Show whitelist import form print "
\n"; print "$text{'white_importdesc'}

\n"; print "

\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
$text{'white_import'}
$text{'white_sort'} $text{'yes'}\n"; print " $text{'no'}
\n"; print "
\n"; print "
\n"; &footer("", $text{'index_return'}); # whitelist_to_conv(col, name, size, value) sub whitelist_to_conv { if ($_[0] == 0) { return &default_convfunc(@_); } else { local $rv = "\n"; return $rv; } } spam/index.cgi0100775000567100000120000000607707747556551013336 0ustar jcameronwheel#!/usr/local/bin/perl # index.cgi # Display a menu of spamassassin config category icons require './spam-lib.pl'; $hsl = $module_info{'usermin'} ? undef : &help_search_link("spamassassin", "perl", "google"); if (!&has_command($config{'spamassassin'}) || (!$module_info{'usermin'} && !($vers = &get_spamassassin_version(\$out)))) { # Program not found &header($text{'index_title'}, "", undef, 1, 1, undef, $hsl); print "
\n"; print "

",&text('index_ecmd', "$config{'spamassassin'}", "$gconfig{'webprefix'}/config.cgi?$module_name"),"

\n"; } else { $vtext = $module_info{'usermin'} ? undef : &text('index_version', $vers); &header($text{'index_title'}, "", undef, 1, 1, undef, $hsl, undef, undef, $vtext); print "


\n"; if (!-r $local_cf && -d $local_cf && !$module_info{'usermin'}) { # Config not found print "

",&text('index_econfig', "$config{'local_cf'}", "$gconfig{'webprefix'}/config.cgi?$module_name"), "

\n"; } else { # Work out of SpamAssassin is enabled in procmail if ($config{'warn_procmail'} && &foreign_check("procmail")) { &foreign_require("procmail", "procmail-lib.pl"); $enabled = 0; @pmrcs = &get_procmailrc(); foreach $pmrc (@pmrcs) { local @recipes = &procmail::parse_procmail_file($pmrc); foreach $r (@recipes) { if ($r->{'action'} =~ /spamassassin/i || $r->{'action'} =~ /spamc/i) { # Looks like it is! $enabled = 1; last; } foreach $c (@{$r->{'conds'}}) { if ($c->[1] =~ /X-Spam/i) { # A condition exists $enabled = 1; last; } } } last if ($enabled); } } else { $enabled = -1; # don't know, or checking disabled } if ($enabled == 0) { if ($module_info{'usermin'}) { print &text('index_warn_usermin', "$pmrcs[0]", "$pmrcs[1]"),"

\n"; } else { print &text('index_warn_webmin', "$pmrcs[0]"),"

\n"; } } # Show icons @pages = ( 'white', 'score', 'report', 'user' ); push(@pages, 'header') if (!$module_info{'usermin'} || &find_default("allow_user_rules", 0)); push(@pages, 'priv') if (!$module_info{'usermin'}); push(@pages, 'mail') if ($module_info{'usermin'} && $userconfig{'spam_file'}); push(@pages, 'setup') if ($enabled == 0); @pages = grep { &can_use_page($_) } @pages; @links = map { $_ eq "mail" ? "mail.cgi" : "edit_${_}.cgi" } @pages; @icons = map { "images/${_}.gif" } @pages; @titles = map { $text{"${_}_title"} } @pages; &icons_table(\@links, \@titles, \@icons); # Show buttons for HUPing spamd processes (if any) if (!$module_info{'usermin'} && (@pids = &get_process_pids())) { print "


\n"; print "
\n"; print "\n"; print "\n"; print "\n"; print "
",&text('index_applydesc', "".join(" and ", &unique( map { $_->[1] } @pids)).""),"
\n"; } } } print "
\n"; &footer("/", $text{'index'}); spam/langs0100664000567100000120000000131607674516170012546 0ustar jcameronwheelaf afrikaans am amharic ar arabic be byelorussian bg bulgarian bs bosnian ca catalan cs czech cy welsh da danish de german el greek en english eo esperanto es spanish et estonian eu basque fa persian fi finnish fr french fy frisian ga irish gd scots he hebrew hi hindi hr croatian hu hungarian hy armenian id indonesian is icelandic it italian ja japanese ka georgian ko korean la latin lt lithuanian lv latvian mr marathi ms malay ne nepali nl dutch no norwegian pl polish pt portuguese qu quechua rm rhaeto-romance ro romanian ru russian sa sanskrit sco scots sk slovak sl slovenian sq albanian sr serbian sv swedish sw swahili ta tamil th thai tl tagalog tr turkish uk ukrainian vi vietnamese yi yiddish zh chinese spam/save_header.cgi0100775000567100000120000000556607747703460014470 0ustar jcameronwheel#!/usr/local/bin/perl # save_header.cgi # Save custom header and body tests require './spam-lib.pl'; &can_use_check("header"); &error_setup($text{'header_err'}); &ReadParse(); &lock_spam_files(); $conf = &get_config(); if (!$module_info{'usermin'}) { &parse_yes_no($conf, "allow_user_rules"); } @header = &parse_table("header", \&header_parser); &save_directives($conf, "header", \@header, 1); @oldbody = ( &find("body", $conf), &find("rawbody", $conf), &find("fullbody", $conf), &find("full", $conf) ); @body = &parse_table("body", \&body_parser); &save_directives($conf, \@oldbody, \@body, 0); @uri = &parse_table("uri", \&uri_parser); &save_directives($conf, "uri", \@uri, 1); @meta = &parse_table("meta", \&meta_parser); &save_directives($conf, "meta", \@meta, 1); @score = &parse_table("score", \&score_parser); &save_directives($conf, 'score', \@score, 1); @describe = &parse_table("describe", \&describe_parser); &save_directives($conf, 'describe', \@describe, 1); &flush_file_lines(); &unlock_spam_files(); &webmin_log("header"); &redirect(""); # header_parser(rowname, value, ...) sub header_parser { return undef if ($_[1] eq ''); $_[1] =~ /^\S+$/ || &error(&text('header_ename', $_[1])); if ($_[3] eq 'eval') { $_[4] =~ /^\S+$/ || &error(&text('header_eeval', $_[4])); return "$_[1] eval:$_[4]"; } elsif ($_[3] eq 'exists') { $_[2] =~ /^\S+$/ || &error(&text('header_eheader', $_[2])); return "$_[1] exists:$_[2]"; } else { $_[2] =~ /^\S+$/ || &error(&text('header_eheader', $_[2])); $_[4] =~ /^\/(.*)\/\S*$/ || &error(&text('header_eregexp', $_[4])); return "$_[1] $_[2] $_[3] $_[4]".($_[5] ? " if-unset: $_[5]" : ""); } } # body_parser(rowname, value, ...) sub body_parser { return undef if ($_[1] eq ''); $_[1] =~ /^\S+$/ || &error(&text('header_ename', $_[1])); local $v; if ($_[3] == 0) { $_[4] =~ /^\/(.*)\/\S*$/ || &error(&text('header_eregexp', $_[4])); $v = "$_[1] $_[4]"; } else { $_[4] =~ /^\S+$/ || &error(&text('header_eeval', $_[4])); $v = "$_[1] eval:$_[4]"; } return { 'name' => $_[2] == 0 ? 'body' : $_[2] == 1 ? 'rawbody' : $_[2] == 2 ? 'fullbody' : 'full', 'value' => $v }; } sub uri_parser { return undef if ($_[1] eq ''); $_[1] =~ /^\S+$/ || &error(&text('header_ename', $_[1])); $_[2] =~ /^\/(.*)\/\S*$/ || &error(&text('header_eregexp', $_[2])); return "$_[1] $_[2]"; } sub meta_parser { return undef if ($_[1] eq ''); $_[1] =~ /^\S+$/ || &error(&text('header_ename', $_[1])); $_[2] =~ /\S/ || &error(&text('header_emeta', $_[1])); return "$_[1] $_[2]"; } sub score_parser { return undef if (!$_[1]); $_[1] =~ /^\S+$/ || &error(&text('score_ename', $_[1])); $_[2] =~ /^\-?\d+(\.\d+)?$/ || &error(&text('score_epoints', $_[2])); return "$_[1] $_[2]"; } sub describe_parser { return undef if (!$_[1]); $_[1] =~ /^\S+$/ || &error(&text('score_ename', $_[1])); $_[2] =~ /\S/ || &error(&text('score_edesc', $_[1])); return "$_[1] $_[2]"; } spam/edit_report.cgi0100775000567100000120000000602307705401040014506 0ustar jcameronwheel#!/usr/local/bin/perl # edit_report.cgi # Display a form for editing the spam report text require './spam-lib.pl'; &can_use_check("report"); &header($text{'report_title'}, ""); print "
\n"; $conf = &get_config(); print "$text{'report_desc'}

\n"; &start_form("save_report.cgi", $text{'report_header'}); print " $text{'report_rewrite'} "; $rewrite = &find("rewrite_subject", $conf); &yes_no_field("rewrite_subject", $rewrite, 1); print " \n"; print " $text{'report_subject'} "; $subject = &find("subject_tag", $conf); &opt_field("subject_tag", $subject, 15, "*****SPAM*****"); print " \n"; print " $text{'report_rheader'} "; $header = &find("report_header", $conf); &yes_no_field("report_header", $header, 0); print " \n"; print " $text{'report_useterse'} "; $terse = &find("use_terse_report", $conf); &yes_no_field("use_terse_report", $terse, 0); print " \n"; print " $text{'report_fold'} "; $fold = &find("fold_headers", $conf); &yes_no_field("fold_headers", $fold, 1); print " \n"; print " $text{'report_detail'} "; $detail = &find("detailed_phrase_score", $conf); &yes_no_field("detailed_phrase_score", $detail, 0); print " \n"; print " $text{'report_stars'} "; $stars = &find("spam_level_stars", $conf); &yes_no_field("spam_level_stars", $stars, 1); print " \n"; print " $text{'report_char'} "; $char = &find("spam_level_char", $conf); &opt_field("spam_level_char", $char, 2, "*"); print " \n"; print " $text{'report_defang'} "; $defang = &find("defang_mime", $conf); &yes_no_field("defang_mime", $defang, 1); print " \n"; print "


\n"; @report = &find_value("report", $conf); $clear = &find("clear_report_template", $conf); print " $text{'report_report'} \n"; printf " %s\n", $clear ? "" : "checked", $text{'report_noclear'}; printf " %s
\n", $clear ? "checked" : "", $text{'report_clear'}; print " \n"; @report = &find_value("terse_report", $conf); $clear = &find("clear_terse_report_template", $conf); print " $text{'report_terse'} \n"; printf " %s\n", $clear ? "" : "checked", $text{'report_noclear'}; printf " %s
\n", $clear ? "checked" : "", $text{'report_clear'}; print " \n"; print "\n"; &end_form(undef, $text{'save'}); print "
\n"; &footer("", $text{'index_return'}); spam/detach.cgi0100755000567100000120000000165307725214134013430 0ustar jcameronwheel#!/usr/local/bin/perl # detach.cgi # View one attachment from a message use Socket; require './spam-lib.pl'; &foreign_require("mailbox", "mailbox-lib.pl"); $folder = &spam_file_folder(); &disable_indexing($folder); &ReadParse(); @mail = &mailbox::mailbox_list_mails($in{'idx'}, $in{'idx'}, $folder); $mail = $mail[$in{'idx'}]; &mailbox::parse_mail($mail); @sub = split(/\0/, $in{'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; } &mailbox::decrypt_attachments($mail); $attach = $mail->{'attach'}->[$in{'attach'}]; print "X-no-links: 1\n"; print "Content-type: $attach->{'type'}\n\n"; if ($attach->{'type'} =~ /^text\/html/i) { print &filter_javascript($attach->{'data'}); } else { print $attach->{'data'}; } spam/mail.cgi0100775000567100000120000001237007741174051013123 0ustar jcameronwheel#!/usr/local/bin/perl # mail.cgi # Display messages that have been categorized as spam require './spam-lib.pl'; &foreign_require("mailbox", "mailbox-lib.pl"); &ReadParse(); $folder = &spam_file_folder(); &disable_indexing($folder); dbmopen(%read, "$user_config_directory/mailbox/read", 0600); $ref = $userconfig{'refresh'} || $mailbox::userconfig{'refresh'}; if ($ref) { print "Refresh: $ref\r\n"; &header($text{'mail_title'}, "", undef, 0, 0, 0, $ref > 60 ? &text('mail_will', int($ref/60)) : &text('mail_wills', $ref)); } else { &header($text{'mail_title'}, ""); } print &check_clicks_function() if (defined(&check_clicks_function)); print "
\n"; #print "$text{'mail_desc'}

\n"; # View mail from the most recent $perpage = $folder->{'perpage'} || $mailbox::userconfig{'perpage'}; @mail = reverse(&mailbox::mailbox_list_mails(-$in{'start'}, -$in{'start'}-$perpage+1, $folder, 1, \@error)); print "

\n"; if ($in{'start'}+$perpage < @mail) { printf "%s\n", $in{'start'}+$perpage, ''; } local $s = @mail-$in{'start'}; local $e = @mail-$in{'start'}-$perpage+1; print "\n"; if (@mail) { print &text('mail_pos', $s, $e < 1 ? 1 : $e, scalar(@mail)); } else { print &text('mail_none'); } print " \n"; if ($in{'start'}) { printf "%s\n", $in{'start'}-$perpage, ''; } print "
\n"; print "
\n"; if ($mailbox::userconfig{'top_buttons'} && @mail) { &show_buttons(1); print "$mailbox::text{'mail_all'} \n"; print "$mailbox::text{'mail_invert'} \n"; } if (@mail) { print "\n"; print " ", " ", " ", " ", " ", "\n"; } for($i=$in{'start'}; $i<@mail && $i<$in{'start'}+$perpage; $i++) { local $idx = $mail[$i]->{'idx'}; print "\n"; print "\n"; if ($userconfig{'full_from'}) { print "\n"; } else { print "\n"; } print "\n"; print "\n"; print "\n"; print "\n"; } if (@mail) { print "
 $mailbox::text{'mail_from'}$mailbox::text{'mail_date'}$mailbox::text{'mail_size'}$text{'mail_level'}$mailbox::text{'mail_subject'}
", &html_escape($mail[$i]->{'header'}->{'from'}), "", &mailbox::simplify_from($mail[$i]->{'header'}->{'from'}), "",&mailbox::simplify_date($mail[$i]->{'header'}->{'date'}), "",int($mail[$i]->{'size'}/1000)+1," kB","",length($mail[$i]->{'header'}->{'x-spam-level'}),"", "
",&mailbox::simplify_subject($mail[$i]->{'header'}->{'subject'}), " "; if ($mail[$i]->{'header'}->{'content-type'} =~ /multipart\/\S+/i) { print ""; } local $p = int($mail[$i]->{'header'}->{'x-priority'}); if ($p == 1) { print " "; } elsif ($p == 2) { print " "; } if (!$showto) { if ($read{$mail[$i]->{'header'}->{'message-id'}} == 2) { print " "; } elsif ($read{$mail[$i]->{'header'}->{'message-id'}} == 1) { print " "; } } print "
\n"; print "$mailbox::text{'mail_all'} \n"; print "$mailbox::text{'mail_invert'} \n"; } &show_buttons(2); print "
\n"; print "
\n"; &footer("", $text{'index_return'}); # show_buttons(number) sub show_buttons { print "\n"; if (@mail) { local $onclick = "onClick='return check_clicks(form)'" if (defined(&check_clicks_function)); print "\n"; print "\n"; print "\n"; print "\n"; } print "
\n"; } spam/uconfig.info0100664000567100000120000000025107731250757014023 0ustar jcameronwheelspam_file=Mail file for spam,3,None full_from=Show full From: addresses in spam list?,1,1-Yes,0-No refresh=Seconds between automatic spam list refreshes,3,Don't refresh spam/defaultuconfig0100664000567100000120000000001407725214376014433 0ustar jcameronwheelfull_from=1 spam/config-freebsd0100664000567100000120000000040007747704057014314 0ustar jcameronwheellocal_cf=.spamassassin/user_prefs spamassassin=spamassassin global_procmailrc=/usr/local/etc/procmailrc global_cf=/usr/local/etc/mail/spamassassin show_global=0 avail_icons=white,score,report,user,header,setup,mail warn_procmail=1 index_spam=0 call_spam=1