File Coverage

blib/lib/POE/Filter/Transparent/SMTP.pm
Criterion Covered Total %
statement 87 96 90.6
branch 16 26 61.5
condition 8 24 33.3
subroutine 12 12 100.0
pod 7 7 100.0
total 130 165 78.7


line stmt bran cond sub pod time code
1             # Copyright (c) 2008-2009 George Nistorica
2             # All rights reserved.
3             # This program is free software; you can redistribute it and/or
4             # modify it under the same terms as Perl itself. See the LICENSE
5             # file that comes with this distribution for more details.
6              
7             # ($rcs) = (' $Id: SMTP.pm,v 1.11 2009/01/28 12:45:15 george Exp $ ' =~ /(\d+(\.\d+)+)/);
8              
9             package POE::Filter::Transparent::SMTP;
10 4     4   94182 use strict;
  4         8  
  4         148  
11 4     4   22 use warnings;
  4         7  
  4         116  
12              
13 4     4   2947 use POE::Filter::Line;
  4         9356  
  4         95  
14 4     4   3540 use Data::Dumper;
  4         32455  
  4         266  
15 4     4   33 use Carp;
  4         6  
  4         4082  
16              
17             our $VERSION = q{0.2};
18             my $EOL = qq{\015\012};
19              
20             sub new {
21 7     7 1 4187 my $class = shift;
22 7         21 my @options = @_;
23 7         27 my %options = @options;
24              
25 7         15 my ( $filter, $self, %filter_line_opts );
26 7 50       25 if ( ref $class ) {
27 0         0 croak q{->new() is a class method!};
28             }
29              
30 7         18 foreach (qw/InputLiteral OutputLiteral/) {
31 14 100 66     125 if ( exists $options{$_} and defined $options{$_} ) {
32 12         40 $filter_line_opts{$_} = $options{$_};
33             }
34             }
35              
36             # we need this when outputing data prefixed by dot
37 7 100       34 if ( not exists $filter_line_opts{'OutputLiteral'} ) {
38 1         4 $self->{'OutputLiteral'} = $EOL;
39             }
40             else {
41 6         20 $self->{'OutputLiteral'} = $filter_line_opts{'OutputLiteral'};
42             }
43              
44 7 50 33     36 if ( exists $options{'Warn'}
      33        
45             and defined $options{'Warn'}
46             and $options{'Warn'} )
47             {
48 0         0 $self->{'Warn'} = 1;
49             }
50             else {
51 7         22 $self->{'Warn'} = 0;
52             }
53              
54             # check for EscapeSingleInputDot
55             # defaults to no
56             # useful for escaping Single Dot on a line in message bodies (not
57             # entire SMTP transaction logs, that include the message body as
58             # well)
59              
60 7 50 33     34 if ( exists $options{'EscapeSingleInputDot'}
      33        
61             and defined $options{'EscapeSingleInputDot'}
62             and $options{'EscapeSingleInputDot'} )
63             {
64 0         0 $self->{'EscapeSingleInputDot'} = 1;
65             }
66             else {
67 7         18 $self->{'EscapeSingleInputDot'} = 0;
68             }
69              
70             # create the POE::Filter::Line filter to store inside our little so
71             # called object
72 7         56 $filter = POE::Filter::Line->new(%filter_line_opts);
73 7         390 $self->{'filter_line'} = $filter;
74 7         18 bless $self, $class;
75 7         30 return $self;
76             }
77              
78             sub clone {
79 1     1 1 368 my $self = shift;
80 1         3 my $filter;
81 1 50       4 if ( not ref $self ) {
82 0         0 croak q{->clone() is not a package method!};
83             }
84 1         2 my $new_obj = $self;
85 1         3 $filter = $new_obj->{'filter_line'};
86 1         13 $filter = $filter->clone;
87 1         15 $new_obj->{'filter_line'} = $filter;
88 1         10 return $new_obj;
89             }
90              
91             sub get_one_start {
92 13     13 1 200 my $self = shift;
93 13         19 my $arg = shift;
94 13 50       42 if ( ref $arg ne q{ARRAY} ) {
95 0         0 croak q{->get_one_start() accepts an array ref as argument};
96             }
97 13         34 my $filter = $self->{'filter_line'};
98 13         45 $filter->get_one_start($arg);
99 13         124 return;
100             }
101              
102             sub get_one {
103 76     76 1 17087 my $self = shift;
104 76         86 my $data;
105 76         107 my $filter = $self->{'filter_line'};
106 76         193 $data = $filter->get_one();
107              
108             # remove the leading transparent dot
109 76         1371 for ( my $i = 0 ; $i < scalar @{$data} ; $i++ ) {
  144         341  
110 68 100       297 if ( $data->[$i] =~ /^\.(\..*)$/os ) {
111 12         41 $data->[$i] = $1;
112             }
113 68 50 33     238 if ( $self->{'Warn'} and $data->[$i] =~ /^\..+$/os ) {
114 0         0 carp q{Data contains a single leading dot }
115             . q{and is not conforming to RFC 821 Section }
116             . q{4.5.2. TRANSPARENCY};
117             }
118             }
119 76         191 return $data;
120             }
121              
122             sub get {
123 6     6 1 4230 my $self = shift;
124 6         10 my $raw_data = shift;
125              
126 6 50       28 if ( ref $raw_data ne q{ARRAY} ) {
127 0         0 croak q{->get() accepts an array ref as argument};
128             }
129 6         21 my $data = [];
130 6         10 my $temp;
131              
132 6         17 $self->get_one_start($raw_data);
133 6         37 $temp = $self->get_one();
134 6         11 while ( scalar @{$temp} ) {
  43         94  
135 37         40 push @{$data}, $temp->[0];
  37         78  
136 37         77 $temp = $self->get_one();
137             }
138              
139 6         46 return $data;
140             }
141              
142             sub put {
143 6     6 1 5152 my $self = shift;
144 6         11 my $raw_data = shift;
145 6 50       24 if ( ref $raw_data ne q{ARRAY} ) {
146 0         0 croak q{->get_one_start() accepts an array ref as argument};
147             }
148 6         11 my ( $filter, $lines, $literal );
149 6         15 $literal = $self->{'OutputLiteral'};
150 6         11 $filter = $self->{'filter_line'};
151 6         26 $lines = $filter->put($raw_data);
152              
153             # add an extra leading dot on lines starting with a dot
154 6         98 for ( my $i = 0 ; $i < scalar @{$lines} ; $i++ ) {
  30         73  
155 24 100       196 if ( $lines->[$i] =~ /^\..+$literal$/s ) {
156 6         12 $lines->[$i] = q{.} . $lines->[$i];
157             }
158              
159             # do we escape single dot? (for filtering message bodies, not
160             # entire SMTP transaction
161 24 0 0     68 if ( $self->{'EscapeSingleInputDot'}
      33        
162             and ( $lines->[$i] =~ /^\.$/so or $lines->[$i] =~ /^\.$literal$/so )
163             )
164             {
165 0         0 $lines->[$i] = q{.} . $lines->[$i];
166             }
167             }
168              
169 6         20 return $lines;
170             }
171              
172             sub get_pending {
173 6     6 1 3406 my $self = shift;
174 6         13 my $filter = $self->{'filter_line'};
175 6         21 return $filter->get_pending();
176             }
177              
178             1;
179              
180             __END__