./Mimedefang.pm


# -*- Perl -*-
#  $Id: Mimedefang.pm,v 1.8 2005/05/23 21:55:32 johnpc Exp $
# stub package to import Mimedefang symbols

package Mimedefang;
use strict;
use warnings;

require Exporter;

our @ISA = qw(Exporter);
our $VERSION = main::md_version();
our @EXPORT_OK;

### the below lists the entire documented mimedefang interface,
### grouped in convenient subgroups
### The only important group (for this code) is action_decisive,
### which lists all actions that "do something", meaning that 
### subsequent filters are not called.
our %EXPORT_TAGS = (
    action_decisive => [qw{
        action_accept_and_no_more_filtering
        action_drop
        action_drop_with_warning
        action_replace_with_warning
        action_replace_with_url
        action_external_filter
        action_quarantine
        action_quarantine_entire_message
        action_sm_quarantine
        action_bounce
        action_tempfail
        action_discard
    }],
    action_other => [qw{
        action_accept
        action_rebuild
        action_add_header
        action_change_header
        action_delete_header
        action_delete_all_headers
        action_accept_with_warning
        action_defang
        action_notify_sender
        action_notify_administrator
        anomy_clean_html
        append_text_boilerplate
        append_html_boilerplate
        action_add_part
    }],
    useful => [qw{
        send_quarantine_notifications
        get_quarantine_dir
        add_recipient
        delete_recipient
        resend_message
        remove_redundant_html_parts
        replace_entire_message
        read_commands_file
        stream_by_domain
        stream_by_recipient
    }],
    logging => [qw{
        md_graphdefang_log_enable
        md_graphdefang_log
        md_syslog
        md_openlog
    }],
    rbltest => [qw{
        relay_is_blacklisted
        relay_is_blacklisted_multi
        relay_is_blacklisted_multi_list
        relay_is_blacklisted_multi_count
    }],
    spamassassin => [qw{
        spam_assassin_is_spam
        spam_assassin_check
        spam_assassin_status
        spam_assassin_init
        spam_assassin_mail
    }],
    viruscheck => [qw{
        message_contains_virus
        message_contains_virus_trend
        message_contains_virus_nai
        message_contains_virus_bdc
        message_contains_virus_nvcc
        message_contains_virus_csav
        message_contains_virus_fsav
        message_contains_virus_hbedv
        message_contains_virus_vexira
        message_contains_virus_sophos
        message_contains_virus_clamav
        message_contains_virus_avp
        message_contains_virus_avp5
        message_contains_virus_filescan
        message_contains_virus_fprot
        message_contains_virus_fprotd
        message_contains_virus_openantivirus
        message_contains_virus_carrier_scan
        message_contains_virus_sophie
        message_contains_virus_clamd
        message_contains_virus_trophie
        message_contains_virus_saviperl
        entity_contains_virus
        entity_contains_virus_trend
        entity_contains_virus_nai
        entity_contains_virus_bdc
        entity_contains_virus_nvcc
        entity_contains_virus_csav
        entity_contains_virus_fsav
        entity_contains_virus_hbedv
        entity_contains_virus_sophos
        entity_contains_virus_clamav
        entity_contains_virus_avp
        entity_contains_virus_avp5
        entity_contains_virus_filescan
        entity_contains_virus_fprot
        entity_contains_virus_fprotd
        entity_contains_virus_openantivirus
        entity_contains_virus_carrier_scan
        entity_contains_virus_sophie
        entity_contains_virus_trophie
        entity_contains_virus_clamd
        entity_contains_virus_saviperl
    }],
    testing => [qw{
        md_version
        message_rejected
        md_copy_orig_msg_to_work_dir
        md_copy_orig_msg_to_work_dir_as_mbox_file
    }],
    config => [qw{
        $AdminAddress
        $DaemonAddress
        $AddWarningsInline
        $MaxMIMEParts
        %Stupidity
        $AddApparentlyToForSpamAssassin
        $SyslogFacility
        $WarningLocation
        $DaemonName
        $AdminName
        $SALocalTestsOnly
        $NotifySenderSubject
        $NotifyAdministratorSubject
        $QuarantineSubject
        $NotifyNoPreamble
        $OpenAVHost
        $CSSHost
        $SophieSock
        $ClamdSock
        $TrophieSock
    }],
    global => [qw{
        %Features
        $CWD
        $SuspiciousCharsInHeaders
        $SuspiciousCharsInBody
        $RelayHostname
        $RelayAddr
        $Helo
        $Subject
        $Sender
        @Recipients
        $MessageID
        $QueueID
        $MsgID
        $VirusScannerMessages
        $VirusName
        $SASpamTester
        %SendmailMacros
        @SenderESMTPArgs
        %RecipientESMTPArgs
        %RecipientMailers
    }],
### filterchain are internal for Mimedefang.pm and mimedefang-filter-select
    filterchain => [qw{
        filterchain_reset
        filterchain_tookaction
    }],
### undocumented mimedefang.pl routines that are very valueable nonetheless
    undocumented => [qw{
        get_host_name
        percent_decode
    }],
);

### also export these. Do not put them in EXPORT_OK because we
### fill the real @EXPORT_OK down below using export_ok_tags('all')
my @MY_EXPORT_OK = qw{
    md_check_against_smtp_server
    re_match
    re_match_ext
    re_match_in_zip_directory
    add_ip_validation_header
    delete_ip_validation_header
};

### build ":action" tag
{
    my %seen;

    push @{ $EXPORT_TAGS{action} },
        grep { !$seen{$_}++ }
        map { @{ $EXPORT_TAGS{$_} } } qw(action_decisive action_other);
}

### build ":all" tag
{
    my %seen;

    push @{ $EXPORT_TAGS{all} },
         grep { !$seen{$_}++ }
         @MY_EXPORT_OK,
         map { @{ $EXPORT_TAGS{$_} } }
         keys %EXPORT_TAGS;
}

### add to @EXPORT_OK stuff in tags:
Exporter::export_ok_tags('all');

### some implementations

my $Action_Taken;

sub filterchain_reset {
    $Action_Taken = 0;
}

sub filterchain_tookaction {
    return $Action_Taken;
}

### this one is extra
sub action_accept_and_no_more_filtering {
    $Action_Taken++;
    &main::action_accept;
}

### action_defang is special. Make sure to call the defang_warning
### from the same package as where the action_defang was called from.
sub action_defang {
    my $pkg = caller;
    local *main::defang_warning = \&{ $pkg . "::defang_warning" };
    # assume no action taken, other filters can still reject
    &main::action_defang;
}

### all 'decisive' actions set $Action_Taken
for my $fun ( @{ $EXPORT_TAGS{action_decisive} } ) {
    no strict 'refs';
    *$fun = sub {
        $Action_Taken++;
        my $orig = \&{"main::$fun"};
        &$orig;
    } unless exists &$fun;
}

### import everything else from main::
### ... only to be exported again on request. This is a bit of a detour,
### but at least it uses a "clean" Exporter interface, enabling all
### default Exporter feature that you'd expect.
### It would be better if mimedefang.pl itself moved to package
### Mimedefang and incorporated these changes... :)
for my $item ( @{ $EXPORT_TAGS{all} } ) {
    if ( $item =~ s/^\$// ) {
        no strict "refs";
        *$item = \${ "main::$item" };
    }
    elsif ( $item =~ s/^\@// ) {
        no strict "refs";
        *$item = \@{ "main::$item" };
    }
    elsif ( $item =~ s/^\%// ) {
        no strict "refs";
        *$item = \%{ "main::$item" };
    }
    elsif ( !exists &$item ) {
        no strict "refs";
        *$item = \&{"main::$item" };
    }
}

1;