Mailing List Archive

svn commit: r294971 - in /spamassassin/trunk/lib/Mail: SpamAssassin.pm SpamAssassin/PerMsgStatus.pm SpamAssassin/Plugin.pm SpamAssassin/PluginHandler.pm
Author: jm
Date: Tue Oct 4 19:05:48 2005
New Revision: 294971

URL: http://svn.apache.org/viewcvs?rev=294971&view=rev
Log:
bug 4517: rule instrumentation plugin hooks, from John Gardiner Myers <jgmyers /at/ proofpoint.com>

Modified:
spamassassin/trunk/lib/Mail/SpamAssassin.pm
spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm
spamassassin/trunk/lib/Mail/SpamAssassin/PluginHandler.pm

Modified: spamassassin/trunk/lib/Mail/SpamAssassin.pm
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/lib/Mail/SpamAssassin.pm?rev=294971&r1=294970&r2=294971&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin.pm Tue Oct 4 19:05:48 2005
@@ -1618,6 +1618,15 @@

###########################################################################

+sub have_plugin {
+ my ($self, $subname) = @_;
+
+ # We could potentially get called after a finish(), so just return.
+ return unless $self->{plugins};
+
+ return $self->{plugins}->have_callback ($subname);
+}
+
sub call_plugins {
my $self = shift;


Modified: spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm?rev=294971&r1=294970&r2=294971&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm Tue Oct 4 19:05:48 2005
@@ -1565,10 +1565,20 @@

###########################################################################

-sub ran_rule_debug_code {
+sub start_rules_plugin_code {
+ my ($self, $ruletype) = @_;
+
+ return '' unless $self->{main}->have_plugin("start_rules");
+
+ return '
+ $self->{main}->call_plugins ("start_rules", { permsgstatus => $self, ruletype => \''.$ruletype.'\' });
+ ';
+}
+
+sub hit_rule_plugin_code {
my ($self, $rulename, $ruletype, $bit) = @_;

- return '' unless exists($self->{should_log_rule_hits});
+ return '' unless exists($self->{should_log_rule_hits}) || $self->{main}->have_plugin("hit_rule");

# note: keep this in 'single quotes' to avoid the $ & performance hit,
# unless specifically requested by the caller. Also split the
@@ -1576,6 +1586,15 @@
# doesn't impose that hit anyway (just in case)
my $match = '($' . '&' . '|| "negative match")';

+ my $debug_code = '';
+ if (exists($self->{should_log_rule_hits})) {
+ $debug_code = '
+ dbg("rules: ran '.$ruletype.' rule '.$rulename.' ======> got hit: \"" . '.
+ $match.' . "\"");
+
+ ';
+ }
+
my $save_hits_code = '';
if ($self->{save_pattern_hits}) {
$save_hits_code = '
@@ -1583,10 +1602,24 @@
';
}

+ my $plugin_code = '';
+ if ($self->{main}->have_plugin("hit_rule")) {
+ $plugin_code = '
+ $self->{main}->call_plugins ("hit_rule", { permsgstatus => $self, rulename => \''.$rulename.'\', ruletype => \''.$ruletype.'\' });
+ ';
+ }
+
+ return $debug_code.$save_hits_code.$plugin_code.'
+ ';
+}
+
+sub ran_rule_plugin_code {
+ my ($self, $rulename, $ruletype) = @_;
+
+ return '' unless $self->{main}->have_plugin("ran_rule");
+
return '
- dbg("rules: ran '.$ruletype.' rule '.$rulename.' ======> got hit: \"" . '.
- $match.' . "\"");
- '.$save_hits_code.'
+ $self->{main}->call_plugins ("ran_rule", { permsgstatus => $self, rulename => \''.$rulename.'\', ruletype => \''.$ruletype.'\' });
';
}

@@ -1625,7 +1658,7 @@
return;
}

- my $evalstr = '';
+ my $evalstr = $self->start_rules_plugin_code("header");
my $evalstr2 = '';

while (my($rulename, $rule) = each %{$self->{conf}{head_tests}->{$priority}}) {
@@ -1647,6 +1680,7 @@
$evalstr .= '
if ($self->{conf}->{scores}->{q#'.$rulename.'#}) {
'.$rulename.'_head_test($self, $_); # no need for OO calling here (its faster this way)
+ '.$self->ran_rule_plugin_code($rulename, "header").'
}
';

@@ -1661,7 +1695,7 @@
'.$self->hash_line_for_rule($rulename).'
if ($self->get(q#'.$hdrname.'#, q#'.$def.'#) '.$testtype.'~ '.$pat.') {
$self->got_hit (q#'.$rulename.'#, q{});
- '. $self->ran_rule_debug_code($rulename, "header", 1) . '
+ '. $self->hit_rule_plugin_code($rulename, "header", 1) . '
}
}';

@@ -1726,7 +1760,7 @@
}

# build up the eval string...
- my $evalstr = '';
+ my $evalstr = $self->start_rules_plugin_code("body");
my $evalstr2 = '';

while (my($rulename, $pat) = each %{$self->{conf}{body_tests}->{$priority}}) {
@@ -1734,6 +1768,7 @@
if ($self->{conf}->{scores}->{q{'.$rulename.'}}) {
# call procedurally as it is faster.
'.$rulename.'_body_test($self,@_);
+ '.$self->ran_rule_plugin_code($rulename, "body").'
}
';

@@ -1748,7 +1783,7 @@
'.$self->hash_line_for_rule($rulename).'
if ('.$pat.') {
$self->got_pattern_hit(q{'.$rulename.'}, "BODY: ");
- '. $self->ran_rule_debug_code($rulename, "body", 2) . '
+ '. $self->hit_rule_plugin_code($rulename, "body", 2) . '
# Ok, we hit, stop now.
last;
}
@@ -2138,13 +2173,15 @@
}

# otherwise build up the eval string...
- my $evalstr = '';
+ my $evalstr = $self->start_rules_plugin_code("uri");
my $evalstr2 = '';

while (my($rulename, $pat) = each %{$self->{conf}{uri_tests}->{$priority}}) {
$evalstr .= '
if ($self->{conf}->{scores}->{q{'.$rulename.'}}) {
'.$rulename.'_uri_test($self, @_); # call procedurally for speed
+ '.$self->ran_rule_plugin_code($rulename, "uri").'
+
}
';

@@ -2159,7 +2196,7 @@
'.$self->hash_line_for_rule($rulename).'
if ('.$pat.') {
$self->got_pattern_hit(q{'.$rulename.'}, "URI: ");
- '. $self->ran_rule_debug_code($rulename, "uri", 4) . '
+ '. $self->hit_rule_plugin_code($rulename, "uri", 4) . '
# Ok, we hit, stop now.
last;
}
@@ -2227,13 +2264,14 @@
}

# build up the eval string...
- my $evalstr = '';
+ my $evalstr = $self->start_rules_plugin_code("rawbody");
my $evalstr2 = '';

while (my($rulename, $pat) = each %{$self->{conf}{rawbody_tests}->{$priority}}) {
$evalstr .= '
if ($self->{conf}->{scores}->{q{'.$rulename.'}}) {
'.$rulename.'_rawbody_test($self, @_); # call procedurally for speed
+ '.$self->ran_rule_plugin_code($rulename, "rawbody").'
}
';

@@ -2248,7 +2286,7 @@
'.$self->hash_line_for_rule($rulename).'
if ('.$pat.') {
$self->got_pattern_hit(q{'.$rulename.'}, "RAW: ");
- '. $self->ran_rule_debug_code($rulename, "rawbody", 8) . '
+ '. $self->hit_rule_plugin_code($rulename, "rawbody", 8) . '
# Ok, we hit, stop now.
last;
}
@@ -2317,7 +2355,7 @@
}

# build up the eval string...
- my $evalstr = '';
+ my $evalstr = $self->start_rules_plugin_code("full");

while (my($rulename, $pat) = each %{$self->{conf}{full_tests}->{$priority}}) {
$evalstr .= '
@@ -2325,8 +2363,9 @@
'.$self->hash_line_for_rule($rulename).'
if ($$fullmsgref =~ '.$pat.') {
$self->got_pattern_hit(q{'.$rulename.'}, "FULL: ");
- '. $self->ran_rule_debug_code($rulename, "full", 16) . '
+ '. $self->hit_rule_plugin_code($rulename, "full", 16) . '
}
+ '.$self->ran_rule_plugin_code($rulename, "full").'
}
';
}

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm?rev=294971&r1=294970&r2=294971&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm Tue Oct 4 19:05:48 2005
@@ -395,6 +395,63 @@

=back

+=item $plugin->start_rules ( { options ... } )
+
+Called before testing a set of rules of a given type and priority.
+
+=over 4
+
+=item permsgstatus
+
+The C<Mail::SpamAssassin::PerMsgStatus> context object for this scan.
+
+=item ruletype
+
+The type of the rules about to be performed.
+
+=back
+
+=item $plugin->hit_rule ( { options ... } )
+
+Called when a rule fires.
+
+=over 4
+
+=item permsgstatus
+
+The C<Mail::SpamAssassin::PerMsgStatus> context object for this scan.
+
+=item ruletype
+
+The type of the rule that fired.
+
+=item rulename
+
+The name of the rule that fired.
+
+=back
+
+=item $plugin->ran_rule ( { options ... } )
+
+Called after a rule has been tested, whether or not it fired. When the
+rule fires, the hit_rule callback is always called before this.
+
+=over 4
+
+=item permsgstatus
+
+The C<Mail::SpamAssassin::PerMsgStatus> context object for this scan.
+
+=item ruletype
+
+The type of the rule that was tested.
+
+=item rulename
+
+The name of the rule that was tested.
+
+=back
+
=item $plugin->check_end ( { options ... } )

Signals that a message check operation has just finished, and the

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/PluginHandler.pm
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/lib/Mail/SpamAssassin/PluginHandler.pm?rev=294971&r1=294970&r2=294971&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/PluginHandler.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/PluginHandler.pm Tue Oct 4 19:05:48 2005
@@ -130,10 +130,8 @@

###########################################################################

-sub callback {
- my $self = shift;
- my $subname = shift;
- my ($ret, $overallret);
+sub have_callback {
+ my ($self, $subname) = @_;

# have we set up the cache entry for this callback type?
if (!exists $self->{cbs}->{$subname}) {
@@ -148,6 +146,19 @@
}
}
$self->{cbs}->{$subname} = \@subs;
+ }
+
+ return scalar(@{$self->{cbs}->{$subname}});
+}
+
+sub callback {
+ my $self = shift;
+ my $subname = shift;
+ my ($ret, $overallret);
+
+ # have we set up the cache entry for this callback type?
+ if (!exists $self->{cbs}->{$subname}) {
+ return unless $self->have_callback($subname);
}

foreach my $cbpair (@{$self->{cbs}->{$subname}}) {