File Coverage

blib/lib/Mail/Audit/Attach.pm
Criterion Covered Total %
statement 18 111 16.2
branch 0 34 0.0
condition 0 17 0.0
subroutine 6 19 31.5
pod 7 10 70.0
total 31 191 16.2


line stmt bran cond sub pod time code
1             package Mail::Audit::Attach;
2              
3             # Copyright (c) 2002-2010 Christian Renz . All rights reserved.
4             # This program is free software; you can redistribute it and/or modify
5             # it under the same terms as Perl itself.
6              
7 2     2   53481 use strict;
  2         6  
  2         218  
8 2     2   16 use vars qw($VERSION @ISA $ERROR);
  2         4  
  2         302  
9 2     2   3300 use MIME::Entity;
  2         370772  
  2         73  
10 2     2   26 use File::Spec;
  2         4  
  2         1602  
11              
12             $VERSION = '0.96';
13              
14             @ISA = qw(MIME::Entity);
15              
16             $ERROR = '';
17              
18             # constructor
19              
20             sub new {
21 0     0 1   my $class = shift;
22 0           my %opts = @_;
23 0           my $self = $opts{ENTITY};
24 0           $self->{MAIL_AUDIT_OBJ} = $opts{CREATOR};
25              
26 0           bless $self, $class;
27             }
28              
29             # properties
30              
31             sub error {
32 0     0 1   return $ERROR;
33             }
34              
35             sub _set_error {
36 0     0     my ($error) = @_;
37              
38 0           $ERROR = $error;
39              
40 0           return undef;
41             }
42              
43             sub size {
44 0     0 1   my $self = shift;
45 0           my $body = $self->bodyhandle;
46              
47 0 0         if (defined($body->path)) {
48 0           return -s $body->path;
49             } else {
50 0           return length($body->as_string);
51             }
52             }
53              
54             sub filename {
55 0     0 1   my $self = shift;
56              
57 0           return $self->head->recommended_filename;
58             }
59              
60             sub safe_filename {
61 0     0 1   my $self = shift;
62 0           my $filename = $self->filename;
63              
64 0           $filename =~ s,([/:;|]|\s|\\|\[|\])+,_,g;
65              
66 0   0       return ($filename || 'attachment');
67             }
68              
69             # actions
70              
71             sub remove {
72 0     0 1   my $self = shift;
73              
74 0           return _remove_part($self->{MAIL_AUDIT_OBJ}, $self);
75             }
76              
77             # Internal helper function that walks through MIME parts to remove a part.
78             sub _remove_part {
79 0     0     my $msg = shift;
80 0           my $part = shift;
81 0           local $_;
82            
83 0           foreach ($msg->parts) {
84 0 0         if ($_ == $part) {
    0          
85 0           $part->bodyhandle->purge;
86 0           $msg->parts([ grep { $_ != $part } $msg->parts ]);
  0            
87 0           return 1;
88             } elsif ($_->parts > 0) {
89 0           return _remove_part($_, $part);
90             }
91             }
92              
93 0           return undef;
94             }
95              
96             sub save {
97 0     0 1   my $self = shift;
98 0   0       my $location = shift || File::Spec->curdir;
99 0           my $filename = $self->safe_filename;
100 0           my $n = 1;
101 0           local $_;
102              
103 0 0         if (-d $location) {
104 0           $filename = File::Spec->catfile($location, $self->safe_filename);
105             } else {
106 0           $filename = $location;
107             }
108              
109 0 0         if (-e $filename) {
110 0           while (-e "$filename.$n") {
111 0           $n++;
112             }
113              
114 0           $filename = "$filename.$n";
115             }
116              
117 0 0         my $io = $self->open("r")
118             or return _set_error("Can't open internal bodyhandle");
119 0 0         open(SAVE, ">$filename")
120             or return _set_error("Can't save to '$filename': $!\n");
121 0           while (defined($_ = $io->getline)) {
122 0           print SAVE $_;
123             }
124 0           close(SAVE);
125 0           $io->close;
126              
127 0           return $filename;
128             }
129              
130             1;
131              
132             package Mail::Audit;
133              
134 2     2   14 use MIME::Entity;
  2         4  
  2         48  
135 2     2   10 use MIME::Head;
  2         4  
  2         1100  
136              
137             sub num_attachments {
138 0     0 0   my $self = shift;
139 0           my $count = 0;
140 0           local $_;
141              
142 0 0         if (UNIVERSAL::isa($self, "MIME::Entity")) {
143 0           foreach ($self->parts_DFS) {
144 0 0         $count++
145             if (defined $_->head->recommended_filename());
146             }
147              
148 0           return $count;
149             } else {
150 0           return 0;
151             }
152             }
153              
154             sub attachments {
155             # TODO: walk the tree ourself and save the parent instead of CREATOR.
156 0     0 0   my $self = shift;
157 0           local $_;
158              
159 0 0         if (UNIVERSAL::isa($self, "MIME::Entity")) {
160 0           my @entities = grep { defined $_->head->recommended_filename }
  0            
161             $self->parts_DFS;
162 0           my $attachments = [];
163 0           foreach (@entities) {
164 0           push @$attachments, Mail::Audit::Attach->new(ENTITY => $_,
165             CREATOR => $self);
166             }
167              
168 0           return $attachments;
169             } else {
170 0           return undef;
171             }
172             }
173              
174             sub remove_attachments {
175 0     0 0   my $self = shift;
176 0           my %opts = @_;
177              
178 0 0         if (UNIVERSAL::isa($self, "MIME::Entity")) {
179 0           return _remove_attachments($self, %opts);
180             } else {
181 0           return undef;
182             }
183             }
184              
185             # Internal helper function that walks through MIME parts to remove
186             # attachments
187             sub _remove_attachments {
188 0     0     my $msg = shift;
189 0           my %opts = @_;
190 0           my $count = 0;
191 0           local $_;
192              
193 0           my @parts = $msg->parts;
194 0           foreach my $part (@parts) {
195 0 0         if (defined $part->head->recommended_filename()) {
    0          
196 0 0 0       COND: {
197 0           last COND if (defined($opts{mime_type}) &&
198             $part->mime_type !~ $opts{mime_type});
199 0 0 0       last COND if (defined($opts{filename}) &&
200             $part->filename !~ $opts{filename});
201 0 0 0       last COND if (defined($opts{bigger_than}) &&
202             $part->size >= $opts{smaller_than});
203 0 0 0       last COND if (defined($opts{bigger_than}) &&
204             $part->size <= $opts{bigger_than});
205              
206 0           $part->bodyhandle->purge;
207 0           $msg->parts([ grep { $_ != $part } $msg->parts ]);
  0            
208 0           $count++;
209             }
210             } elsif ($part->parts > 0) {
211 0           $count += _remove_attachments($part, %opts);
212             }
213             }
214              
215 0           return $count;
216             }
217              
218              
219              
220             1;
221              
222             __END__