Add hook_user_config

This adds a hook_user_config for plugins designed to return per-user
configuration directives.  Qpsmtpd::Address::config() triggers a
hook_user_config plugin.
This commit is contained in:
Jared Johnson 2014-09-09 18:08:09 -05:00
parent bd47c06966
commit b22d037c39
5 changed files with 50 additions and 3 deletions

View File

@ -732,6 +732,35 @@ is called. It's probably best not to try acessing it.
Example plugin is F<http_config> from the qpsmtpd distribution. Example plugin is F<http_config> from the qpsmtpd distribution.
=head2 hook_user_config
Called when a per-user configuration directive is requested, for example
if someone calls C<my @cfg = $rcpt-E<gt>config($cfg_name);>.
Allowed return codes are
=over 4
=item DECLINED
plugin didn't find the requested value
=item OK
requested values as C<@list>, example:
return (OK, @{$config{$value}})
if exists $config{$value};
return (DECLINED);
=back
Arguments:
my ($self,$transaction,$user,$value) = @_;
# $value: the requested config item(s)
Example plugin is F<user_config> from the qpsmtpd distribution.
=head2 hook_unrecognized_command =head2 hook_unrecognized_command
This is called if the client sent a command unknown to the core of qpsmtpd. This is called if the client sent a command unknown to the core of qpsmtpd.

View File

@ -148,14 +148,17 @@ sub config {
# first try the cache # first try the cache
# XXX - is this always the right thing to do? what if a config hook # XXX - is this always the right thing to do? what if a config hook
# can return different values on subsequent calls? # can return different values on subsequent calls?
if ($_config_cache->{$c}) { my $is_address = (ref $type and $type->can('address'));
if ($_config_cache->{$c} and ! $is_address) {
$self->log(LOGDEBUG, $self->log(LOGDEBUG,
"config($c) returning (@{$_config_cache->{$c}}) from cache"); "config($c) returning (@{$_config_cache->{$c}}) from cache");
return wantarray ? @{$_config_cache->{$c}} : $_config_cache->{$c}->[0]; return wantarray ? @{$_config_cache->{$c}} : $_config_cache->{$c}->[0];
} }
# then run the hooks # then run the hooks
my ($rc, @config) = $self->run_hooks_no_respond("config", $c); my @args = $is_address ? ('user_config',$type,$c) : ('config',$c);
my ($rc, @config) = $self->run_hooks_no_respond(@args);
return wantarray ? @config : $config[0] if $is_address;
$self->log(LOGDEBUG, "config($c): hook returned ($rc, @config) "); $self->log(LOGDEBUG, "config($c): hook returned ($rc, @config) ");
if ($rc == OK) { if ($rc == OK) {
$self->log(LOGDEBUG, $self->log(LOGDEBUG,

View File

@ -338,6 +338,19 @@ sub notes {
return $self->{_notes}->{$key} = shift; return $self->{_notes}->{$key} = shift;
} }
=head2 config($value)
Looks up a configuration directive based on this recipient, using any plugins that utilize
hook_rcpt_config
=cut
sub config {
my ($self,$key) = @_;
my $qp = $self->notes('qp_obj') or return;
return $qp->config($key,$self);
}
sub _addr_cmp { sub _addr_cmp {
require UNIVERSAL; require UNIVERSAL;
my ($left, $right, $swap) = @_; my ($left, $right, $swap) = @_;

View File

@ -9,7 +9,7 @@ use Qpsmtpd::Constants;
# more or less in the order they will fire # more or less in the order they will fire
our @hooks = qw( our @hooks = qw(
logging config post-fork pre-connection connect ehlo_parse ehlo logging config user_config post-fork pre-connection connect ehlo_parse ehlo
helo_parse helo auth_parse auth auth-plain auth-login auth-cram-md5 helo_parse helo auth_parse auth auth-plain auth-login auth-cram-md5
rcpt_parse rcpt_pre rcpt mail_parse mail mail_pre rcpt_parse rcpt_pre rcpt mail_parse mail mail_pre
data data_headers_end data_post queue_pre queue queue_post vrfy noop data data_headers_end data_post queue_pre queue queue_post vrfy noop

View File

@ -396,6 +396,7 @@ sub mail_pre_respond {
} }
return $self->respond(501, "could not parse your mail from command") return $self->respond(501, "could not parse your mail from command")
unless $from; unless $from;
$from->notes('qp_obj',$self);
$self->run_hooks("mail", $from, %$param); $self->run_hooks("mail", $from, %$param);
} }
@ -485,6 +486,7 @@ sub rcpt_pre_respond {
return $self->respond(501, "could not parse recipient") return $self->respond(501, "could not parse recipient")
if (!$rcpt or ($rcpt->format eq '<>')); if (!$rcpt or ($rcpt->format eq '<>'));
$rcpt->notes('qp_obj',$self);
$self->run_hooks("rcpt", $rcpt, %$param); $self->run_hooks("rcpt", $rcpt, %$param);
} }