Abstracted spool_dir creation and added temp_file() and temp_dir() subs to
make it easier for plugins to manage temporary workspace. Also add POD and tests for the new functions. Still need to add tests to the temp_*() calls from a plugin. git-svn-id: https://svn.perl.org/qpsmtpd/trunk@369 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
parent
d790bd519d
commit
bb36c60b6a
7
Changes
7
Changes
@ -1,6 +1,13 @@
|
||||
|
||||
0.29
|
||||
|
||||
New temp_file() and temp_dir() methods; when used by plugins, they create
|
||||
a filename or directory which will last only as long as the current
|
||||
transaction. Also created a spool_dir() method which checks/creates the
|
||||
spool_dir when the application starts up. All three methods are also
|
||||
available in the base class where the temp_* objects are not automatically
|
||||
limited to the transaction's lifetime. (John Peacock)
|
||||
|
||||
Added Gavin Carr's greylisting plugin
|
||||
|
||||
Renamed config/ to config.sample/
|
||||
|
@ -200,3 +200,32 @@ With the $Include stuff you order using the filename of the plugin.d
|
||||
file. So if you have a plugin called xyz but want it to come early on,
|
||||
you call it's config file 00_xyz, but that file still refers to the
|
||||
plugin called xyz.
|
||||
|
||||
=head1 Temporary Files
|
||||
|
||||
The temporary file and directory functions can be used for plugin specific
|
||||
workfiles and will automatically be deleted at the end of the current
|
||||
transaction.
|
||||
|
||||
=over 4
|
||||
|
||||
=item temp_file()
|
||||
|
||||
Returns a unique name of a file located in the default spool directory, but
|
||||
does not open that file (i.e. it is the name not a file handle).
|
||||
|
||||
=item temp_dir()
|
||||
|
||||
Returns the name of a unique directory located in the default spool
|
||||
directory, after creating the directory with 0700 rights. If you need a
|
||||
directory with different rights (say for an antivirus daemon), you will
|
||||
need to use the base function $self->qp->temp_dir() which takes a single
|
||||
parameter for the permissions requested (see L<mkdir> for details). A
|
||||
directory created like this will B<not> be deleted when the transaction is
|
||||
ended.
|
||||
|
||||
=item spool_dir()
|
||||
|
||||
Returns the configured system-wide spool directory.
|
||||
|
||||
=back
|
||||
|
@ -255,4 +255,52 @@ sub _register_hook {
|
||||
}
|
||||
}
|
||||
|
||||
sub spool_dir {
|
||||
my $self = shift;
|
||||
|
||||
unless ( $self->{_spool_dir} ) { # first time through
|
||||
my $spool_dir = $self->config('spool_dir')
|
||||
|| Qpsmtpd::Utils::tildeexp('~/tmp/');
|
||||
|
||||
$spool_dir .= "/" unless ($spool_dir =~ m!/$!);
|
||||
|
||||
$spool_dir =~ /^(.+)$/ or die "spool_dir not configured properly";
|
||||
$spool_dir = $1; # cleanse the taint
|
||||
$self->{_spool_dir} = $spool_dir;
|
||||
|
||||
# Make sure the spool dir has appropriate rights
|
||||
if (-e $spool_dir) {
|
||||
my $mode = (stat($spool_dir))[2];
|
||||
warn "Permissions on spool_dir $spool_dir are not 0700" if $mode & 07077;
|
||||
}
|
||||
|
||||
# And finally, create it if it doesn't already exist
|
||||
-d $spool_dir or mkdir($spool_dir, 0700)
|
||||
or die "Could not create spool_dir $spool_dir: $!";
|
||||
}
|
||||
|
||||
return $self->{_spool_dir};
|
||||
}
|
||||
|
||||
# For unique filenames. We write to a local tmp dir so we don't need
|
||||
# to make them unpredictable.
|
||||
my $transaction_counter = 0;
|
||||
|
||||
sub temp_file {
|
||||
my $self = shift;
|
||||
my $filename = $self->spool_dir()
|
||||
. join(":", time, $$, $transaction_counter++);
|
||||
$filename =~ tr!A-Za-z0-9:/_-!!cd;
|
||||
return $filename;
|
||||
}
|
||||
|
||||
sub temp_dir {
|
||||
my $self = shift;
|
||||
my $mask = shift || 0700;
|
||||
my $dirname = $self->temp_file();
|
||||
-d $dirname or mkdir($dirname, $mask)
|
||||
or die "Could not create temporary directory $dirname: $!";
|
||||
return $dirname;
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -53,6 +53,24 @@ sub connection {
|
||||
shift->qp->connection;
|
||||
}
|
||||
|
||||
sub spool_dir {
|
||||
shift->qp->spool_dir;
|
||||
}
|
||||
|
||||
sub temp_file {
|
||||
my $self = shift;
|
||||
my $tempfile = $self->qp->temp_file;
|
||||
push @{$self->qp->transaction->{_temp_files}}, $tempfile;
|
||||
return $tempfile;
|
||||
}
|
||||
|
||||
sub temp_dir {
|
||||
my $self = shift;
|
||||
my $tempdir = $self->qp->temp_dir();
|
||||
push @{$self->qp->transaction->{_temp_dirs}}, $tempdir;
|
||||
return $tempdir;
|
||||
}
|
||||
|
||||
# plugin inheritance:
|
||||
# usage:
|
||||
# sub register {
|
||||
|
@ -7,10 +7,6 @@ use Qpsmtpd::Constants;
|
||||
|
||||
use IO::File qw(O_RDWR O_CREAT);
|
||||
|
||||
# For unique filenames. We write to a local tmp dir so we don't need
|
||||
# to make them unpredictable.
|
||||
my $transaction_counter = 0;
|
||||
|
||||
sub new { start(@_) }
|
||||
|
||||
sub start {
|
||||
@ -71,22 +67,7 @@ sub body_write {
|
||||
my $self = shift;
|
||||
my $data = shift;
|
||||
unless ($self->{_body_file}) {
|
||||
my $spool_dir = $self->config('spool_dir') ? $self->config('spool_dir')
|
||||
: Qpsmtpd::Utils::tildeexp('~/tmp/');
|
||||
|
||||
$spool_dir .= "/" unless ($spool_dir =~ m!/$!);
|
||||
|
||||
$spool_dir =~ /^(.+)$/ or die "spool_dir not configured properly";
|
||||
$spool_dir = $1;
|
||||
|
||||
if (-e $spool_dir) {
|
||||
my $mode = (stat($spool_dir))[2];
|
||||
die "Permissions on spool_dir $spool_dir are not 0700" if $mode & 07077;
|
||||
}
|
||||
|
||||
-d $spool_dir or mkdir($spool_dir, 0700) or die "Could not create spool_dir $spool_dir: $!";
|
||||
$self->{_filename} = $spool_dir . join(":", time, $$, $transaction_counter++);
|
||||
$self->{_filename} =~ tr!A-Za-z0-9:/_-!!cd;
|
||||
$self->{_filename} = $self->temp_file();
|
||||
$self->{_body_file} = IO::File->new($self->{_filename}, O_RDWR|O_CREAT, 0600)
|
||||
or die "Could not open file $self->{_filename} - $! "; # . $self->{_body_file}->error;
|
||||
}
|
||||
@ -129,6 +110,25 @@ sub DESTROY {
|
||||
if ($self->{_filename} and -e $self->{_filename}) {
|
||||
unlink $self->{_filename} or $self->log(LOGERROR, "Could not unlink ", $self->{_filename}, ": $!");
|
||||
}
|
||||
|
||||
# These may not exist
|
||||
if ( $self->{_temp_files} ) {
|
||||
$self->log(LOGDEBUG, "Cleaning up temporary transaction files");
|
||||
foreach my $file ( @{$self->{_temp_files}} ) {
|
||||
next unless -e $file;
|
||||
unlink $file or $self->log(LOGERROR,
|
||||
"Could not unlink temporary file", $file, ": $!");
|
||||
}
|
||||
}
|
||||
# Ditto
|
||||
if ( $self->{_temp_dirs} ) {
|
||||
eval {use File::Path};
|
||||
$self->log(LOGDEBUG, "Cleaning up temporary directories");
|
||||
foreach my $dir ( @{$self->{_temp_dirs}} ) {
|
||||
rmtree($dir) or $self->log(LOGERROR,
|
||||
"Could not unlink temporary dir", $dir, ": $!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
27
t/tempstuff.t
Normal file
27
t/tempstuff.t
Normal file
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/perl -w
|
||||
use Test::More qw(no_plan);
|
||||
use File::Path;
|
||||
use strict;
|
||||
use lib 't';
|
||||
use_ok('Test::Qpsmtpd');
|
||||
|
||||
BEGIN { # need this to happen before anything else
|
||||
my $cwd = `pwd`;
|
||||
chomp($cwd);
|
||||
open my $spooldir, '>', "./config.sample/spool_dir";
|
||||
print $spooldir "$cwd/t/tmp";
|
||||
close $spooldir;
|
||||
}
|
||||
|
||||
ok(my ($smtpd, $conn) = Test::Qpsmtpd->new_conn(), "get new connection");
|
||||
|
||||
my ($spool_dir,$tempfile,$tempdir) = ( $smtpd->spool_dir,
|
||||
$smtpd->temp_file(), $smtpd->temp_dir() );
|
||||
|
||||
ok( $spool_dir =~ m!t/tmp/$!, "Located the spool directory");
|
||||
ok( $tempfile =~ /^$spool_dir/, "Temporary filename" );
|
||||
ok( $tempdir =~ /^$spool_dir/, "Temporary directory" );
|
||||
ok( -d $tempdir, "And that directory exists" );
|
||||
|
||||
unlink "./config.sample/spool_dir";
|
||||
rmtree($spool_dir);
|
Loading…
Reference in New Issue
Block a user