Mail::Abuse::Processor::Store - Process a Mail::Abuse::Report


Mail-Abuse documentation Contained in the Mail-Abuse distribution.

Index


Code Index:

NAME

Top

Mail::Abuse::Processor::Store - Process a Mail::Abuse::Report

SYNOPSIS

Top

  use Mail::Abuse::Processor::Store;

  use Mail::Abuse::Report;
  my $p = new Mail::Abuse::Processor::Store;
  my $report = new Mail::Abuse::Report (processors => [ $p ]);

  # ... other pieces of code that configure the report ...

DESCRIPTION

Top

This class stores a processed report in a file hierarchy that is composed using the smallest acceptable timestamp from the list of incidents in a report.

If no incidents are found within a report, a special name is built based on the report text.

The place where the files are created can be controlled with entries in the configuration file. Currently, the following directives are understood.

store root path

Points to the root of the tree where reports are to be stored. Defaults to the current directory.

store empty path

The name of the leaf where reports with no incidents are stored. This is a subdir of store root path. It defaults to the very creative name, "empty".

store mode

The mode in which to store abuse reports. The following modes are supported.

serialized

This is the default, and uses Storable to serialize the in-memory Mail::Abuse::Report object and store it in a flat file.

serialized-gz

Just like serialized, but the resulting file is compressed with the equivalent of gzip, using PerlIO::gzip.

plain

Store only the report text, as a flat file.

plain-gz

Just like plain but the resulting file is compressed on the fly using PerlIO::gzip.

debug store

If set to a true value, causes this module to emit debugging information using warn().

The following functions are implemented.

process($report)

Takes a Mail::Abuse::Report object as an argument and performs the processing action required.

The processed $report will have the filename where the report was stored, added in store_file.

EXPORT

None by default.

HISTORY

Top

0.01

Original version; created by h2xs 1.2 with options

  -ACOXcfkn
	Mail::Abuse
	-v
	0.01

LICENSE AND WARRANTY

Top

This code and all accompanying software comes with NO WARRANTY. You use it at your own risk.

This code and all accompanying software can be used freely under the same terms as Perl itself.

AUTHOR

Top

Luis E. Muñoz <luismunoz@cpan.org>

SEE ALSO

Top

perl(1).


Mail-Abuse documentation Contained in the Mail-Abuse distribution.
package Mail::Abuse::Processor::Store;

require 5.005_62;

use Carp;
use strict;
use warnings;
use Data::Dumper;

use IO::File;
use File::Path;
use File::Spec;
use PerlIO::gzip;
use POSIX qw(strftime);
use Storable qw/nstore_fd/;
use Digest::MD5 qw/md5_hex/;

use base 'Mail::Abuse::Processor';

use constant ROOT	=> 'store root path';
use constant EMPTY	=> 'store empty path';
use constant MODE	=> 'store mode';
use constant DEBUG	=> 'debug store';

				# The code below should be in a single line

our $VERSION = do { my @r = (q$Revision: 1.12 $ =~ /\d+/g); sprintf " %d."."%03d" x $#r, @r };

sub process
{
    my $self	= shift;
    my $rep	= shift;

    my $earliest = $rep->incidents->[0];

    my $path;
    my $file;
    
    unless ($self->root)
    {
	$self->root($rep->config->{&ROOT} || File::Spec->curdir());
	warn "Store: Root set to '" . $self->root . "'\n"
	    if $rep->config->{&DEBUG};
    }

    unless ($self->empty)
    {
	$self->empty($rep->config->{&EMPTY} || 'empty');
	warn "Store: Empty placeholder set to '" . $self->empty . "'\n"
	    if $rep->config->{&DEBUG};
    }

    if ($earliest)
    {
	for my $i (@{$rep->incidents})
	{
	    if ($i->time and $earliest->time and $i->time < $earliest->time) 
	    { 
		$earliest = $i; 
	    }
	    elsif (! defined $earliest->time)
	    {
		$earliest = $i;
	    }
	}

	if (defined $earliest->time)
	{
				# Build the pathname...
	    $path = File::Spec->catdir
		(
		 $self->root, split
		 (/:/, strftime("%Y:%m:%d", 
				(localtime($earliest->time))[0..5])
		  ),
		 );
	    
	    $file = File::Spec->catfile($path, md5_hex($ {$rep->text}));
	}
	else
	{
	    warn "Store: No incident has time!\n"
		if $rep->config->{&DEBUG};
	}
    }

    unless ($file and $path)
    {
	$path = File::Spec->catdir
	    (
	     $self->root,
	     $self->empty,
	     );

	$file = File::Spec->catfile($path, md5_hex($ {$rep->text}));
    }
    
    warn "Store: File name set to $file\n"
	if $rep->config->{&DEBUG};

    eval { mkpath [ $path ] };		# Create the target path...

    if ($@)
    {
	warn "Store: Failed to create dir $path: $!\n";
	return;
    }

    if (-f $file)
    {
	warn "Store: $file already exists. Not overriden\n";
	return 1;
    }

    $rep->store_file($file);

    my $fh = new IO::File;

    if (exists $rep->config->{&MODE}
	and $rep->config->{&MODE} =~ m/-gz$/)
    {
	unless ($fh->open($file, ">:gzip"))
	{
	    warn "Store: Failed to gz-open $file: $!\n";
	    return;
	}
    }
    else
    {
	unless ($fh->open($file, ">"))
	{
	    warn "Store: Failed to open $file: $!\n";
	    return;
	}
    }

    if (not exists $rep->config->{&MODE}
	or $rep->config->{&MODE} =~ m/^serialized/)
    {
	eval 
	{ 
	    nstore_fd($rep, $fh) 
		|| warn "Storable::nstore_fd failed with $!\n";
	};
	
	if ($@)
	{
	    warn "Store: Failed to nstore: $@\n";
	    return;
	}

    }
    elsif ($rep->config->{&MODE} =~ m/^plain/)
    {
	print $fh ${$rep->text};
    }

    unless ($fh->close)
    {
	warn "Failed to close $file: $!\n";
	return;
    }
    
    return 1;
}

__END__