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 2007/07/13 14:16:16 UTC

svn commit: r555965 - /spamassassin/branches/jm_bug_3852_two_level_configs/lib/Mail/SpamAssassin/Conf/Parser.pm

Author: jm
Date: Fri Jul 13 05:16:15 2007
New Revision: 555965

URL: http://svn.apache.org/viewvc?view=rev&rev=555965
Log:
bug 3852: first checkin on branch for two-level system/user configs, branched from r555963

Modified:
    spamassassin/branches/jm_bug_3852_two_level_configs/lib/Mail/SpamAssassin/Conf/Parser.pm

Modified: spamassassin/branches/jm_bug_3852_two_level_configs/lib/Mail/SpamAssassin/Conf/Parser.pm
URL: http://svn.apache.org/viewvc/spamassassin/branches/jm_bug_3852_two_level_configs/lib/Mail/SpamAssassin/Conf/Parser.pm?view=diff&rev=555965&r1=555964&r2=555965
==============================================================================
--- spamassassin/branches/jm_bug_3852_two_level_configs/lib/Mail/SpamAssassin/Conf/Parser.pm (original)
+++ spamassassin/branches/jm_bug_3852_two_level_configs/lib/Mail/SpamAssassin/Conf/Parser.pm Fri Jul 13 05:16:15 2007
@@ -111,6 +111,13 @@
 Set to 1 if this value occurs frequently in the config. this means it's looked
 up first for speed.
 
+=item accessor
+
+Set to a string containing the perl code of a method to get the configuration
+value. The string C<${SETTING}> will be replaced with the name of the setting.
+Optional; if C<type> is defined, an accessor suitable for that type of
+data will be provided automatically.
+
 =back
 
 =head1 METHODS
@@ -156,6 +163,63 @@
 
 ###########################################################################
 
+# Implementations for default accessors.
+# access a scalar configuration setting. e.g.:
+#   my $val = $conf->cf_foo_bar();
+my $cf_accessor_scalar_value = '
+
+  sub cf_${SETTING} {
+    if (defined $_[0]->{tiers}->[1]->{${SETTING}}) {
+      return $_[0]->{tiers}->[1]->{${SETTING}};
+    } else {
+      return $_[0]->{tiers}->[0]->{${SETTING}};
+    }
+  }
+
+';
+
+# access a hash key=>value configuration setting. e.g.:
+#   my $val = $conf->cf_foo_bar("baz");
+my $cf_accessor_hash_key_value = '
+
+  sub cf_${SETTING} {
+    if (defined $_[0]->{tiers}->[1]->{${SETTING}}->{$_[1]}) {
+      return $_[0]->{tiers}->[1]->{${SETTING}}->{$_[1]};
+    } else {
+      return $_[0]->{tiers}->[0]->{${SETTING}}->{$_[1]};
+    }
+  }
+
+';
+
+# access a whitelist/blacklist address-list hash in its entirety. e.g.:
+#   my $hashref = $conf->cf_foo_bar();
+#   foreach my $addr (keys %{$hashref}) {
+#     do something with $hashref->{$addr}
+#   }
+# TODO: it would be more efficient to fix calling code to iterate
+# through the tiers instead of using this API.
+my $cf_accessor_addrlist_value = '
+
+  sub cf_${SETTING} {
+    if (defined $_[0]->{tiers}->[1]->{${SETTING}}) {
+      # return the user configuration whitelists and system-wide stuff
+      return \(
+          %{$_[0]->{tiers}->[1]->{${SETTING}}},
+          %{$_[0]->{tiers}->[0]->{${SETTING}}}
+        );
+    } else {
+      # just the system-wide stuff
+      return \(
+          %{$_[0]->{tiers}->[0]->{${SETTING}}}
+        );
+    }
+  }
+
+';
+
+###########################################################################
+
 sub register_commands {
   my($self, $arrref) = @_;
   my $conf = $self->{conf};
@@ -174,6 +238,8 @@
     if (exists($cmd->{default})) {
       $conf->{$cmd->{setting}} = $cmd->{default};
     }
+
+    $self->setup_accessor($cmd);
   }
 }
 
@@ -556,6 +622,55 @@
       for my $index (0..3) {
         $conf->{scoreset}->[$index]->{$k} = $set_score;
       }
+    }
+  }
+}
+
+###########################################################################
+
+sub setup_accessor {
+  my ($self, $cmd) = @_;
+
+  # find a default accessor method, if possible
+  if (!defined $cmd->{accessor} && $cmd->{type}) {
+    my $type = $cmd->{type};
+    if ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_STRING) {
+      $cmd->{accessor} = $cf_accessor_scalar_value;
+    }
+    elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL) {
+      $cmd->{accessor} = $cf_accessor_scalar_value;
+    }
+    elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC) {
+      $cmd->{accessor} = $cf_accessor_scalar_value;
+    }
+    elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_TEMPLATE) {
+      $cmd->{accessor} = $cf_accessor_scalar_value;
+    }
+    elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE) {
+      $cmd->{accessor} = $cf_accessor_hash_key_value;
+    }
+    elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST) {
+      $cmd->{accessor} = $cf_accessor_addrlist_value;
+    }
+  }
+  
+  # now eval the accessor
+  # note: (accessor == "") means do not generate any accessor method
+  my $methodname = "Mail::SpamAssassin::Conf::cf_".$cmd->{setting};
+  if ($cmd->{accessor} && !defined &{$methodname})
+  {
+    my $evalstr = $cmd->{accessor};
+    $evalstr =~ s/\$\{SETTING\}/$cmd->{setting}/gs;
+    eval "package Mail::SpamAssassin::Conf; ".$evalstr;
+
+    if ($@) {
+      die "config: failed to parse accessor: $@\n";
+      return;
+    }
+
+    if (!defined &{$methodname}) {
+      die "config: accessor $methodname not created\n";
+      return;
     }
   }
 }