File Coverage

blib/lib/Mail/Spool/Node.pm
Criterion Covered Total %
statement 66 84 78.5
branch 14 28 50.0
condition 6 12 50.0
subroutine 15 20 75.0
pod 10 11 90.9
total 111 155 71.6


line stmt bran cond sub pod time code
1             # -*- perl -*-
2             #
3             # Mail::Spool::Node - adpO - Mail::Spool inode encapsulization
4             #
5             # $Id: Node.pm,v 1.1 2001/12/08 05:52:59 rhandom Exp $
6             #
7             # Copyright (C) 2001, Paul T Seamons
8             # paul@seamons.com
9             # http://seamons.com/
10             #
11             # This package may be distributed under the terms of either the
12             # GNU General Public License
13             # or the
14             # Perl Artistic License
15             #
16             # All rights reserved.
17             #
18             # Please read the perldoc Mail::Spool::Node
19             #
20             ################################################################
21              
22             package Mail::Spool::Node;
23              
24 1     1   5 use strict;
  1         2  
  1         38  
25 1     1   4 use vars qw($AUTOLOAD $VERSION);
  1         2  
  1         50  
26 1     1   4 use File::NFSLock 1.10 ();
  1         27  
  1         13  
27 1     1   4 use IO::File ();
  1         2  
  1         1007  
28              
29             $VERSION = $Mail::Spool::VERSION;
30              
31             ###----------------------------------------------------------------###
32              
33             sub new {
34 2     2 1 3 my $type = shift;
35 2   50     21 my $class = ref($type) || $type || __PACKAGE__;
36 2 50 33     13 my $self = @_ && ref($_[0]) ? shift() : {@_};
37              
38 2         6 bless $self, $class;
39              
40 2 50       6 if( ! $self->load_node_properties ){
41 0         0 return undef;
42             }
43              
44 2         6 return $self;
45             }
46              
47             ###----------------------------------------------------------------###
48              
49             sub load_node_properties {
50 2     2 0 2 my $node = shift;
51            
52 2 50       18 return undef if $node->name =~ /\.NFSLock$/i; # skip lock files
53 2 50       5 return undef if $node->name =~ /^\.+$/; # skip root directory nodes
54 2 50       12 return undef if -d $node->filename; # skip directories
55              
56             # looking for stuff like 995909015-80EA68E2D942BA85-forward@b.c-paul@seamons.com
57 2 50       9 if( $node->name !~ /^(\d+)-([^\-]+)-([^\-]+)-([^\-]*)$/ ){
58 0         0 die "Strange file found in spool dir \"".$node->filename."\"\n";
59             }
60              
61 2         11 my($time,$message_id,$to_addr,$from_addr) = ($1,$2,$3,$4);
62 2   50     4 $from_addr ||= ''; # allow for undeliverables
63              
64             ### unencode the to and from
65 2         4 foreach ( $to_addr, $from_addr ){
66 4         9 s/%([a-f0-9]{2})/chr(hex($1))/eig;
  0         0  
67             }
68              
69             ### store some properties
70 2         14 $node->time( $time );
71 2         9 $node->id( $message_id );
72 2         8 $node->to( $to_addr );
73 2         6 $node->from( $from_addr );
74            
75 2         6 return 1;
76             }
77              
78             ###----------------------------------------------------------------###
79              
80             ### is this node up for processing
81             sub can_process {
82 1     1 1 1 my $node = shift;
83              
84 1 50       4 die "No wait property found in mail spool handle"
85             if ! defined $node->msh->wait;
86              
87 1         3 return (time() - $node->time >= $node->msh->wait);
88             }
89              
90             sub size {
91 1     1 1 2 my $node = shift;
92 1   50     4 return -s $node->filename || 0;
93             }
94              
95             ###----------------------------------------------------------------###
96              
97             ### exclusive lock (NFS or not)
98             sub lock_node {
99 2     2 1 7 my $node = shift;
100 2         4 my $lock = File::NFSLock->new($node->filename,
101             "NONBLOCKING",
102             0,
103             ($node->msh->spool->max_connection_time+2),
104             );
105 2         2773 $node->{lock_error} = $File::NFSLock::errstr;
106 2         5 return $lock;
107             }
108              
109             sub lock_error {
110 0     0 1 0 return shift()->{lock_error};
111             }
112              
113             ###----------------------------------------------------------------###
114              
115             sub filehandle {
116 2     2 1 27 my $node = shift;
117 2         3 my $mode = shift;
118 2 100 66     17 $mode = 'r' if ! $mode || $mode !~ /^(a|w|r|wr)$/;
119              
120 2         5 my $fh = IO::File->new($node->filename,$mode);
121              
122 2 50       209 if( ! $fh ){
123 0         0 warn "Couldn't open file ".$node->filename." [$!]";
124 0         0 return undef;
125             }
126 2         7 return $fh;
127             }
128              
129             sub filename {
130 7     7 1 7 my $node = shift;
131 7         17 return $node->msh->spool_dir .'/'. $node->name;
132             }
133              
134             sub fallback_filename {
135 0     0 1 0 my $node = shift;
136 0         0 my $name = join("-",time(),$node->id,$node->to,$node->from);
137 0 0       0 return undef if ! defined $node->msh->fallback_dir;
138 0         0 return $node->msh->fallback_dir .'/'. $name;
139             }
140              
141             sub fallback {
142 0     0 1 0 my $node = shift;
143            
144 0 0       0 if( ! rename($node->filename,
145             $node->fallback_filename) ){
146 0         0 warn "Couldn't rename ".$node->filename." to ".$node->fallback_filename." [$!]";
147 0         0 unlink $node->filename; # maybe some more error checking
148             }
149             }
150              
151             sub delete_node {
152 0     0 1 0 my $node = shift;
153 0         0 unlink $node->filename;
154             }
155              
156             ###----------------------------------------------------------------###
157              
158             sub AUTOLOAD {
159 6     6   6 my $node = shift;
160 6         26 my ($method) = $AUTOLOAD =~ /([^:]+)$/;
161 6 50       14 die "No method found in \$AUTOLOAD \"$AUTOLOAD\"" unless defined $method;
162            
163             ### allow for dynamic installation of some subs
164 6 50       18 if( $method =~ /^(to|from|id|time|msh|name)$/ ){
165 1     1   6 no strict 'refs';
  1         2  
  1         87  
166 6         18 * { __PACKAGE__ ."::". $method } = sub {
167 33     33   33 my $self = shift;
168 33         56 my $val = $self->{$method};
169 33 100       64 $self->{$method} = shift if @_;
170 33         169 return $val;
171 6         16 };
172 1     1   18 use strict 'refs';
  1         2  
  1         94  
173            
174             ### now that it is installed, call it again
175 6         16 return $node->$method( @_ );
176             }
177              
178 0           die "Unknown method \"$method\"";
179             }
180              
181 0     0     sub DESTROY {}
182              
183             1;
184              
185              
186              
187             __END__