diff --git a/lib/Qpsmtpd/DB/File/DBM.pm b/lib/Qpsmtpd/DB/File/DBM.pm index 6126a1d..7a30c5a 100644 --- a/lib/Qpsmtpd/DB/File/DBM.pm +++ b/lib/Qpsmtpd/DB/File/DBM.pm @@ -180,9 +180,13 @@ sub flush { } sub dir { - my ( $self, @arg ) = @_; - return $self->{dir} if $self->{dir} and ! @arg; - for my $d ( $self->candidate_dirs(@arg) ) { + my ( $self, $dir ) = @_; + if ( $dir ) { + die "Cannot use DB directory '$dir'\n" if !$self->validate_dir($dir); + return $self->{dir} = $dir; + } + return $self->{dir} if $self->{dir}; + for my $d ( $self->candidate_dirs ) { next if ! $self->validate_dir($d); return $self->{dir} = $d; # first match wins } diff --git a/plugins/greylisting b/plugins/greylisting index 72b04f2..3c872a3 100644 --- a/plugins/greylisting +++ b/plugins/greylisting @@ -266,12 +266,17 @@ sub init_dbm { name => 'greylist', class => 'Qpsmtpd::DB::File::DBM' ); - my $cdir = $self->{_args}{db_dir}; - $cdir = $1 if $cdir and $cdir =~ m{^([-a-zA-Z0-9./_]+)$}; - # greylisting-specific hints for where to store the greylist DB - my $db_dir = $self->db->dir( $cdir, '/var/lib/qpsmtpd/greylisting' ); $self->db->nfs_locking( $self->{_args}{nfslock} ); + # Add to the default list of possible DB directories + $self->db->candidate_dirs('/var/lib/qpsmtpd/greylisting'); + if ( my $dir_arg = $self->{_args}{db_dir} ) { + # user-supplied db dir + $dir_arg = $1 if $dir_arg =~ m{^([-a-zA-Z0-9./_]+)$}; + $self->db->dir($dir_arg); + } + my $db_dir = $self->db->dir; + # Work around old DBM filename my $oldname = 'denysoft_greylist'; if ( ! -f "$db_dir/greylist.dbm" && -f "$db_dir/$oldname.dbm" ) { diff --git a/t/qpsmtpd-db-file-dbm.t b/t/qpsmtpd-db-file-dbm.t index c9e471d..65e1eb0 100644 --- a/t/qpsmtpd-db-file-dbm.t +++ b/t/qpsmtpd-db-file-dbm.t @@ -137,11 +137,17 @@ sub __validate_dir { sub __dir { my $db2 = Qpsmtpd::DB::File::DBM->new( name => 'dirtest' ); is( $db2->dir(), 't/config', 'default directory' ); - is( $db2->dir('_invalid','t/Test'), 't/Test', 'skip invalid candidate dirs' ); + delete $db2->{dir}; + $db2->candidate_dirs('_invalid','t/Test'); + is( $db2->dir, 't/Test', 'skip invalid candidate dirs' ); $db2->{dir} = '_cached'; is( $db2->dir(), '_cached', 'cached directory' ); is( $db2->dir('t/Test'), 't/Test', 'passing candidate dirs resets cache' ); - is( $db2->dir('_invalid'), 't/config', 'invalid candidate dirs reverts to default' ); + delete $db2->{dir}; + $db2->candidate_dirs('_invalid'); + is( $db2->dir, 't/config', 'invalid candidate dirs reverts to default' ); + eval { $db2->dir('_invalid'); }; + is( $@, "Cannot use DB directory '_invalid'\n", 'die on invalid dir' ); } sub __untie_gotcha {