You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by jm...@apache.org on 2004/09/09 05:40:19 UTC

svn commit: rev 43564 - in spamassassin/trunk/lib/Mail/SpamAssassin: . Plugin

Author: jm
Date: Wed Sep  8 20:40:18 2004
New Revision: 43564

Modified:
   spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm
   spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
   spamassassin/trunk/lib/Mail/SpamAssassin/PluginHandler.pm
Log:
bug 3759: plugins loaded from the site config path were not getting their parse_config() methods called; fix by invalidating certain method caches when a new plugin is registered.  also, INHIBIT_CALLBACKS as a return type wasn't working, because it forces plugins to only support numeric return types. not good.  removed; implementors should use the alternative $self->inhibit_further_callbacks() API.  also removed a redundant sort() call

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm	(original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm	Wed Sep  8 20:40:18 2004
@@ -61,11 +61,9 @@
 
 SpamAssassin implements a plugin chain; each callback event is passed to each
 of the registered plugin objects in turn.  Any plugin can call
-C<$plugin->inhibit_further_callbacks()> to block delivery of that event to
+C<$self-E<gt>inhibit_further_callbacks()> to block delivery of that event to
 later plugins in the chain.  This is useful if the plugin has handled the
 event, and there will be no need for later plugins to handle it as well.
-Some methods can also return C<$Mail::SpamAssassin::Plugin::INHIBIT_CALLBACKS>
-to do this, too; this will be noted in the method description below.
 
 If you're looking to write a simple eval rule, skip straight to 
 C<register_eval_rule()>, below.
@@ -101,12 +99,11 @@
 use bytes;
 
 use vars qw{
-  @ISA $VERSION $INHIBIT_CALLBACKS
+  @ISA $VERSION
 };
 
 @ISA =                  qw();
 $VERSION =              'bogus';
-$INHIBIT_CALLBACKS =    -1;
 
 ###########################################################################
 
@@ -185,8 +182,7 @@
 =back
 
 If the configuration line was a setting that is handled by this plugin, the
-method implementation should return
-C<$Mail::SpamAssassin::Plugin::INHIBIT_CALLBACKS>.
+method implementation should call C<$self-E<gt>inhibit_further_callbacks()>.
 
 If the setting is not handled by this plugin, the method should return C<0> so
 that a later plugin may handle it, or so that SpamAssassin can output a warning
@@ -194,7 +190,7 @@
 
 Lifecycle note: it is suggested that configuration be stored on the
 C<Mail::SpamAssassin::Conf> object in use, instead of the plugin object itself.
-That can be found as C<$plugin->{main}->{conf}>.   This allows per-user and
+That can be found as C<$plugin-E<gt>{main}-E<gt>{conf}>.   This allows per-user and
 system-wide configuration to be dealt with correctly, with per-user overriding
 system-wide.
 
@@ -233,7 +229,7 @@
 itself, since the plugin object will be shared between all active scanners.
 
 The message being scanned is accessible through the
-C<$permsgstatus->get_message()> API; there are a number of other public
+C<$permsgstatus-E<gt>get_message()> API; there are a number of other public
 APIs on that object, too.  See C<Mail::SpamAssassin::PerMsgStatus> perldoc.
 
 =back
@@ -454,7 +450,7 @@
 
   $plugin->register_eval_rule ('check_for_foo')
 
-will cause C<$plugin->check_for_foo()> to be called for this
+will cause C<$plugin-E<gt>check_for_foo()> to be called for this
 SpamAssassin rule:
 
   header   FOO_RULE	eval:check_for_foo()
@@ -482,7 +478,7 @@
 C<Mail::SpamAssassin::PerMsgStatus> object, and the body by
 C<get_decoded_stripped_body_text_array()> and other similar methods.
 Similarly, the C<Mail::SpamAssassin::Conf> object holding the current
-configuration may be accessed through C<$permsgstatus->{main}->{conf}>.
+configuration may be accessed through C<$permsgstatus-E<gt>{main}-E<gt>{conf}>.
 
 The eval rule should return C<1> for a hit, or C<0> if the rule
 is not hit.

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm	(original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm	Wed Sep  8 20:40:18 2004
@@ -215,7 +215,7 @@
 	zone => $zone, type => $type,
         is_rhsbl => 0
       };
-      return $Mail::SpamAssassin::Plugin::INHIBIT_CALLBACKS;
+      $self->inhibit_further_callbacks(); return 1;
     }
   }
   elsif ($key eq 'urirhsbl') {
@@ -228,7 +228,7 @@
 	zone => $zone, type => $type,
         is_rhsbl => 1
       };
-      return $Mail::SpamAssassin::Plugin::INHIBIT_CALLBACKS;
+      $self->inhibit_further_callbacks(); return 1;
     }
   }
   elsif ($key eq 'urirhssub') {
@@ -248,12 +248,12 @@
         rulename => $rulename
       };
 
-      return $Mail::SpamAssassin::Plugin::INHIBIT_CALLBACKS;
+      $self->inhibit_further_callbacks(); return 1;
     }
   }
   elsif ($key eq 'uridnsbl_timeout') {
     $opts->{conf}->{uridnsbl_timeout} = $opts->{value};
-    return $Mail::SpamAssassin::Plugin::INHIBIT_CALLBACKS;
+    $self->inhibit_further_callbacks(); return 1;
   }
   return 0;
 }

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/PluginHandler.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/PluginHandler.pm	(original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/PluginHandler.pm	Wed Sep  8 20:40:18 2004
@@ -30,13 +30,28 @@
 use File::Spec;
 
 use vars qw{
-  @ISA $VERSION
+  @ISA $VERSION @CONFIG_TIME_HOOKS
 };
 
 @ISA = qw();
 
 $VERSION = 'bogus';     # avoid CPAN.pm picking up version strings later
 
+# Normally, the list of active plugins that should be called for a given hook
+# method name is compiled and cached at runtime.  This means that later calls
+# will not have to traverse the entire plugin list more than once, since the
+# list of plugins that implement that hook is already cached.
+#
+# However, some hooks should not receive this treatment. One of these is
+# parse_config, which may be compiled before all config files have been read;
+# if a plugin is loaded from a config file after this has been compiled, it
+# will not get callbacks.
+#
+# Any other such hooks that may be compiled at config-parse-time should be
+# listed here.
+
+@CONFIG_TIME_HOOKS = qw( parse_config );
+
 ###########################################################################
 
 sub new {
@@ -103,6 +118,12 @@
   $plugin->{main} = $self->{main};
   push (@{$self->{plugins}}, $plugin);
   dbg ("plugin: registered $plugin");
+
+  # invalidate cache entries for any configuration-time hooks, in case
+  # one has already been built; this plugin may implement that hook!
+  foreach my $subname (@CONFIG_TIME_HOOKS) {
+    delete $self->{cbs}->{$subname};
+  }
 }
 
 ###########################################################################
@@ -117,7 +138,7 @@
     # nope.  run through all registered plugins and see which ones
     # implement this type of callback
     my @subs = ();
-    foreach my $plugin (sort @{$self->{plugins}}) {
+    foreach my $plugin (@{$self->{plugins}}) {
       my $methodref = $plugin->can ($subname);
       if (defined $methodref) {
         push (@subs, [ $plugin, $methodref ]);
@@ -138,11 +159,6 @@
     if ($ret) {
       #dbg ("plugin: ${plugin}->${methodref} => $ret");
       $overallret = $ret;
-
-      if ($ret == $Mail::SpamAssassin::Plugin::INHIBIT_CALLBACKS) {
-        $plugin->{_inhibit_further_callbacks} = 1;
-        $ret = 1;
-      }
     }
 
     if ($plugin->{_inhibit_further_callbacks}) {