line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyrights 2001-2023 by [Mark Overmeer ]. |
2
|
|
|
|
|
|
|
# For other contributors see ChangeLog. |
3
|
|
|
|
|
|
|
# See the manual pages for details on the licensing terms. |
4
|
|
|
|
|
|
|
# Pod stripped from pm file by OODoc 2.03. |
5
|
|
|
|
|
|
|
# This code is part of distribution Mail-Message. Meta-POD processed with |
6
|
|
|
|
|
|
|
# OODoc into POD and HTML manual-pages. See README.md |
7
|
|
|
|
|
|
|
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
package Mail::Message::Body::Multipart; |
10
|
34
|
|
|
34
|
|
934
|
use vars '$VERSION'; |
|
34
|
|
|
|
|
84
|
|
|
34
|
|
|
|
|
1846
|
|
11
|
|
|
|
|
|
|
$VERSION = '3.013'; |
12
|
|
|
|
|
|
|
|
13
|
34
|
|
|
34
|
|
216
|
use base 'Mail::Message::Body'; |
|
34
|
|
|
|
|
120
|
|
|
34
|
|
|
|
|
4929
|
|
14
|
|
|
|
|
|
|
|
15
|
34
|
|
|
34
|
|
260
|
use strict; |
|
34
|
|
|
|
|
82
|
|
|
34
|
|
|
|
|
824
|
|
16
|
34
|
|
|
34
|
|
197
|
use warnings; |
|
34
|
|
|
|
|
84
|
|
|
34
|
|
|
|
|
1102
|
|
17
|
|
|
|
|
|
|
|
18
|
34
|
|
|
34
|
|
203
|
use Mail::Message::Body::Lines; |
|
34
|
|
|
|
|
87
|
|
|
34
|
|
|
|
|
1188
|
|
19
|
34
|
|
|
34
|
|
211
|
use Mail::Message::Part; |
|
34
|
|
|
|
|
111
|
|
|
34
|
|
|
|
|
1215
|
|
20
|
|
|
|
|
|
|
|
21
|
34
|
|
|
34
|
|
15055
|
use Mail::Box::FastScalar; |
|
34
|
|
|
|
|
101
|
|
|
34
|
|
|
|
|
1033
|
|
22
|
34
|
|
|
34
|
|
228
|
use Carp; |
|
34
|
|
|
|
|
76
|
|
|
34
|
|
|
|
|
100188
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub init($) |
26
|
40
|
|
|
40
|
0
|
114
|
{ my ($self, $args) = @_; |
27
|
40
|
|
|
|
|
77
|
my $based = $args->{based_on}; |
28
|
40
|
100
|
66
|
|
|
257
|
$args->{mime_type} ||= defined $based ? $based->type : 'multipart/mixed'; |
29
|
|
|
|
|
|
|
|
30
|
40
|
|
|
|
|
180
|
$self->SUPER::init($args); |
31
|
|
|
|
|
|
|
|
32
|
40
|
|
|
|
|
92
|
my @parts; |
33
|
40
|
100
|
|
|
|
150
|
if($args->{parts}) |
34
|
31
|
|
|
|
|
55
|
{ foreach my $raw (@{$args->{parts}}) |
|
31
|
|
|
|
|
92
|
|
35
|
54
|
50
|
|
|
|
114
|
{ next unless defined $raw; |
36
|
54
|
|
|
|
|
180
|
my $cooked = Mail::Message::Part->coerce($raw, $self); |
37
|
|
|
|
|
|
|
|
38
|
54
|
50
|
|
|
|
150
|
$self->log(ERROR => 'Data not convertible to a message (type is ' |
39
|
|
|
|
|
|
|
, ref $raw,")\n"), next unless defined $cooked; |
40
|
|
|
|
|
|
|
|
41
|
54
|
|
|
|
|
148
|
push @parts, $cooked; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
40
|
|
|
|
|
107
|
my $preamble = $args->{preamble}; |
46
|
40
|
50
|
66
|
|
|
139
|
$preamble = Mail::Message::Body->new(data => $preamble) |
47
|
|
|
|
|
|
|
if defined $preamble && ! ref $preamble; |
48
|
|
|
|
|
|
|
|
49
|
40
|
|
|
|
|
77
|
my $epilogue = $args->{epilogue}; |
50
|
40
|
50
|
66
|
|
|
119
|
$epilogue = Mail::Message::Body->new(data => $epilogue) |
51
|
|
|
|
|
|
|
if defined $epilogue && ! ref $epilogue; |
52
|
|
|
|
|
|
|
|
53
|
40
|
100
|
|
|
|
150
|
if($based) |
54
|
24
|
|
33
|
|
|
112
|
{ $self->boundary($args->{boundary} || $based->boundary); |
55
|
|
|
|
|
|
|
$self->{MMBM_preamble} |
56
|
24
|
100
|
|
|
|
128
|
= defined $preamble ? $preamble : $based->preamble; |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
$self->{MMBM_parts} |
59
|
|
|
|
|
|
|
= @parts ? \@parts |
60
|
24
|
100
|
66
|
|
|
98
|
: !$args->{parts} && $based->isMultipart |
|
|
100
|
|
|
|
|
|
61
|
|
|
|
|
|
|
? [ $based->parts('ACTIVE') ] |
62
|
|
|
|
|
|
|
: []; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
$self->{MMBM_epilogue} |
65
|
24
|
100
|
|
|
|
80
|
= defined $epilogue ? $epilogue : $based->epilogue; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
else |
68
|
16
|
|
66
|
|
|
99
|
{ $self->boundary($args->{boundary} ||$self->type->attribute('boundary')); |
69
|
16
|
|
|
|
|
68
|
$self->{MMBM_preamble} = $preamble; |
70
|
16
|
|
|
|
|
50
|
$self->{MMBM_parts} = \@parts; |
71
|
16
|
|
|
|
|
38
|
$self->{MMBM_epilogue} = $epilogue; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
40
|
|
|
|
|
216
|
$self; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub isMultipart() {1} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
# A multipart body is never binary itself. The parts may be. |
80
|
|
|
|
|
|
|
sub isBinary() {0} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub clone() |
83
|
3
|
|
|
3
|
1
|
8
|
{ my $self = shift; |
84
|
3
|
|
|
|
|
9
|
my $preamble = $self->preamble; |
85
|
3
|
|
|
|
|
10
|
my $epilogue = $self->epilogue; |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
my $body = ref($self)->new |
88
|
|
|
|
|
|
|
( $self->logSettings |
89
|
|
|
|
|
|
|
, based_on => $self |
90
|
|
|
|
|
|
|
, preamble => ($preamble ? $preamble->clone : undef) |
91
|
|
|
|
|
|
|
, epilogue => ($epilogue ? $epilogue->clone : undef) |
92
|
3
|
100
|
|
|
|
17
|
, parts => [ map {$_->clone} $self->parts('ACTIVE') ] |
|
7
|
100
|
|
|
|
35
|
|
93
|
|
|
|
|
|
|
); |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub nrLines() |
98
|
22
|
|
|
22
|
1
|
47
|
{ my $self = shift; |
99
|
22
|
|
|
|
|
38
|
my $nr = 1; # trailing part-sep |
100
|
|
|
|
|
|
|
|
101
|
22
|
100
|
|
|
|
56
|
if(my $preamble = $self->preamble) |
102
|
3
|
|
|
|
|
11
|
{ $nr += $preamble->nrLines; |
103
|
3
|
50
|
|
|
|
12
|
$nr++ if $preamble->endsOnNewline; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
22
|
|
|
|
|
67
|
foreach my $part ($self->parts('ACTIVE')) |
107
|
33
|
|
|
|
|
129
|
{ $nr += 1 + $part->nrLines; |
108
|
33
|
100
|
|
|
|
98
|
$nr++ if $part->body->endsOnNewline; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
22
|
100
|
|
|
|
103
|
if(my $epilogue = $self->epilogue) |
112
|
3
|
|
|
|
|
8
|
{ $nr += $epilogue->nrLines; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
22
|
|
|
|
|
62
|
$nr; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub size() |
119
|
26
|
|
|
26
|
1
|
49
|
{ my $self = shift; |
120
|
26
|
|
|
|
|
65
|
my $bbytes = length($self->boundary) +4; # \n--$b\n |
121
|
|
|
|
|
|
|
|
122
|
26
|
|
|
|
|
63
|
my $bytes = $bbytes +2; # last boundary, \n--$b--\n |
123
|
26
|
100
|
|
|
|
73
|
if(my $preamble = $self->preamble) |
124
|
6
|
|
|
|
|
23
|
{ $bytes += $preamble->size } |
125
|
20
|
|
|
|
|
42
|
else { $bytes -= 1 } # no leading \n |
126
|
|
|
|
|
|
|
|
127
|
26
|
|
|
|
|
78
|
$bytes += $bbytes + $_->size foreach $self->parts('ACTIVE'); |
128
|
26
|
100
|
|
|
|
80
|
if(my $epilogue = $self->epilogue) |
129
|
7
|
|
|
|
|
19
|
{ $bytes += $epilogue->size; |
130
|
|
|
|
|
|
|
} |
131
|
26
|
|
|
|
|
74
|
$bytes; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
4
|
|
|
4
|
1
|
15
|
sub string() { join '', shift->lines } |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub lines() |
137
|
4
|
|
|
4
|
1
|
8
|
{ my $self = shift; |
138
|
|
|
|
|
|
|
|
139
|
4
|
|
|
|
|
15
|
my $boundary = $self->boundary; |
140
|
4
|
|
|
|
|
6
|
my @lines; |
141
|
|
|
|
|
|
|
|
142
|
4
|
|
|
|
|
15
|
my $preamble = $self->preamble; |
143
|
4
|
50
|
|
|
|
11
|
push @lines, $preamble->lines if $preamble; |
144
|
|
|
|
|
|
|
|
145
|
4
|
|
|
|
|
13
|
foreach my $part ($self->parts('ACTIVE')) |
146
|
|
|
|
|
|
|
{ # boundaries start with \n |
147
|
8
|
100
|
|
|
|
97
|
if(!@lines) { ; } |
|
|
50
|
|
|
|
|
|
148
|
4
|
|
|
|
|
10
|
elsif($lines[-1] =~ m/\n$/) { push @lines, "\n" } |
149
|
0
|
|
|
|
|
0
|
else { $lines[-1] .= "\n" } |
150
|
8
|
|
|
|
|
37
|
push @lines, "--$boundary\n", $part->lines; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
4
|
50
|
|
|
|
75
|
if(!@lines) { ; } |
|
|
50
|
|
|
|
|
|
154
|
4
|
|
|
|
|
9
|
elsif($lines[-1] =~ m/\n$/) { push @lines, "\n" } |
155
|
0
|
|
|
|
|
0
|
else { $lines[-1] .= "\n" } |
156
|
4
|
|
|
|
|
12
|
push @lines, "--$boundary--"; |
157
|
|
|
|
|
|
|
|
158
|
4
|
50
|
|
|
|
11
|
if(my $epilogue = $self->epilogue) |
159
|
0
|
|
|
|
|
0
|
{ $lines[-1] .= "\n"; |
160
|
0
|
|
|
|
|
0
|
push @lines, $epilogue->lines; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
4
|
50
|
|
|
|
63
|
wantarray ? @lines : \@lines; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub file() # It may be possible to speed-improve the next |
167
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; # code, which first produces a full print of |
168
|
0
|
|
|
|
|
0
|
my $text; # the message in memory... |
169
|
0
|
|
|
|
|
0
|
my $dump = Mail::Box::FastScalar->new(\$text); |
170
|
0
|
|
|
|
|
0
|
$self->print($dump); |
171
|
0
|
|
|
|
|
0
|
$dump->seek(0,0); |
172
|
0
|
|
|
|
|
0
|
$dump; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub print(;$) |
176
|
8
|
|
|
8
|
1
|
19
|
{ my $self = shift; |
177
|
8
|
|
33
|
|
|
24
|
my $out = shift || select; |
178
|
|
|
|
|
|
|
|
179
|
8
|
|
|
|
|
57
|
my $boundary = $self->boundary; |
180
|
8
|
|
|
|
|
15
|
my $count = 0; |
181
|
8
|
100
|
|
|
|
25
|
if(my $preamble = $self->preamble) |
182
|
2
|
|
|
|
|
16
|
{ $preamble->print($out); |
183
|
2
|
|
|
|
|
4
|
$count++; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
8
|
50
|
|
|
|
24
|
if(ref $out eq 'GLOB') |
187
|
0
|
|
|
|
|
0
|
{ foreach my $part ($self->parts('ACTIVE')) |
188
|
0
|
0
|
|
|
|
0
|
{ print $out "\n" if $count++; |
189
|
0
|
|
|
|
|
0
|
print $out "--$boundary\n"; |
190
|
0
|
|
|
|
|
0
|
$part->print($out); |
191
|
|
|
|
|
|
|
} |
192
|
0
|
0
|
|
|
|
0
|
print $out "\n" if $count++; |
193
|
0
|
|
|
|
|
0
|
print $out "--$boundary--"; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
else |
196
|
8
|
|
|
|
|
24
|
{ foreach my $part ($self->parts('ACTIVE')) |
197
|
13
|
100
|
|
|
|
47
|
{ $out->print("\n") if $count++; |
198
|
13
|
|
|
|
|
108
|
$out->print("--$boundary\n"); |
199
|
13
|
|
|
|
|
150
|
$part->print($out); |
200
|
|
|
|
|
|
|
} |
201
|
8
|
100
|
|
|
|
30
|
$out->print("\n") if $count++; |
202
|
8
|
|
|
|
|
69
|
$out->print("--$boundary--"); |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
8
|
100
|
|
|
|
85
|
if(my $epilogue = $self->epilogue) |
206
|
2
|
|
|
|
|
8
|
{ $out->print("\n"); |
207
|
2
|
|
|
|
|
21
|
$epilogue->print($out); |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
8
|
|
|
|
|
20
|
$self; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub foreachLine($) |
215
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $code) = @_; |
216
|
0
|
|
|
|
|
0
|
$self->log(ERROR => "You cannot use foreachLine on a multipart"); |
217
|
0
|
|
|
|
|
0
|
confess; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub check() |
221
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
222
|
0
|
|
|
0
|
|
0
|
$self->foreachComponent( sub {$_[1]->check} ); |
|
0
|
|
|
|
|
0
|
|
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub encode(@) |
226
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, %args) = @_; |
227
|
0
|
|
|
0
|
|
0
|
$self->foreachComponent( sub {$_[1]->encode(%args)} ); |
|
0
|
|
|
|
|
0
|
|
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
sub encoded() |
231
|
19
|
|
|
19
|
1
|
46
|
{ my $self = shift; |
232
|
19
|
|
|
34
|
|
162
|
$self->foreachComponent( sub {$_[1]->encoded} ); |
|
34
|
|
|
|
|
147
|
|
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub read($$$$) |
236
|
7
|
|
|
7
|
1
|
33
|
{ my ($self, $parser, $head, $bodytype) = @_; |
237
|
|
|
|
|
|
|
|
238
|
7
|
|
|
|
|
20
|
my $boundary = $self->boundary; |
239
|
|
|
|
|
|
|
|
240
|
7
|
|
|
|
|
62
|
$parser->pushSeparator("--$boundary"); |
241
|
7
|
|
|
|
|
47
|
my @msgopts = $self->logSettings; |
242
|
|
|
|
|
|
|
|
243
|
7
|
|
|
|
|
18
|
my $te; |
244
|
7
|
100
|
100
|
|
|
28
|
$te = lc $1 |
245
|
|
|
|
|
|
|
if +($head->get('Content-Transfer-Encoding') || '') =~ m/(\w+)/; |
246
|
|
|
|
|
|
|
|
247
|
7
|
|
|
|
|
26
|
my @sloppyopts = |
248
|
|
|
|
|
|
|
( mime_type => 'text/plain' |
249
|
|
|
|
|
|
|
, transfer_encoding => $te |
250
|
|
|
|
|
|
|
); |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
# Get preamble. |
253
|
7
|
|
|
|
|
18
|
my $headtype = ref $head; |
254
|
|
|
|
|
|
|
|
255
|
7
|
|
|
|
|
29
|
my $begin = $parser->filePosition; |
256
|
7
|
|
|
|
|
36
|
my $preamble = Mail::Message::Body::Lines->new(@msgopts, @sloppyopts) |
257
|
|
|
|
|
|
|
->read($parser, $head); |
258
|
|
|
|
|
|
|
|
259
|
7
|
100
|
|
|
|
42
|
$preamble->nrLines |
260
|
|
|
|
|
|
|
or undef $preamble; |
261
|
|
|
|
|
|
|
|
262
|
7
|
100
|
|
|
|
32
|
$self->{MMBM_preamble} = $preamble |
263
|
|
|
|
|
|
|
if defined $preamble; |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
# Get the parts. |
266
|
|
|
|
|
|
|
|
267
|
7
|
|
|
|
|
24
|
my ($has_epilogue, @parts); |
268
|
7
|
|
|
|
|
23
|
while(my $sep = $parser->readSeparator) |
269
|
20
|
100
|
|
|
|
200
|
{ if($sep =~ m/--\Q$boundary\E--[ \t]*\n?/) |
270
|
|
|
|
|
|
|
{ # Per RFC 2046, a CRLF after the close-delimiter marks the presence |
271
|
|
|
|
|
|
|
# of an epilogue. Preserve the epilogue, even if empty, so that the |
272
|
|
|
|
|
|
|
# printed multipart body will also have the CRLF. |
273
|
|
|
|
|
|
|
# This, however, is complicated w.r.t. mbox folders. |
274
|
7
|
|
|
|
|
29
|
$has_epilogue = $sep =~ /\n/; |
275
|
7
|
|
|
|
|
16
|
last; |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
13
|
|
|
|
|
73
|
my $part = Mail::Message::Part->new |
279
|
|
|
|
|
|
|
( @msgopts |
280
|
|
|
|
|
|
|
, container => $self |
281
|
|
|
|
|
|
|
); |
282
|
|
|
|
|
|
|
|
283
|
13
|
50
|
|
|
|
59
|
last unless $part->readFromParser($parser, $bodytype); |
284
|
13
|
50
|
33
|
|
|
53
|
push @parts, $part |
285
|
|
|
|
|
|
|
if $part->head->names || $part->body->size; |
286
|
|
|
|
|
|
|
} |
287
|
7
|
|
|
|
|
24
|
$self->{MMBM_parts} = \@parts; |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
# Get epilogue |
290
|
|
|
|
|
|
|
|
291
|
7
|
|
|
|
|
28
|
$parser->popSeparator; |
292
|
7
|
|
|
|
|
25
|
my $epilogue = Mail::Message::Body::Lines->new(@msgopts, @sloppyopts) |
293
|
|
|
|
|
|
|
->read($parser, $head); |
294
|
|
|
|
|
|
|
|
295
|
7
|
0
|
|
|
|
33
|
my $end = defined $epilogue ? ($epilogue->fileLocation)[1] |
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
296
|
|
|
|
|
|
|
: @parts ? ($parts[-1]->body->fileLocation)[1] |
297
|
|
|
|
|
|
|
: defined $preamble ? ($preamble->fileLocation)[1] |
298
|
|
|
|
|
|
|
: $begin; |
299
|
7
|
|
|
|
|
37
|
$self->fileLocation($begin, $end); |
300
|
|
|
|
|
|
|
|
301
|
7
|
100
|
66
|
|
|
51
|
$has_epilogue || $epilogue->nrLines |
302
|
|
|
|
|
|
|
or undef $epilogue; |
303
|
|
|
|
|
|
|
|
304
|
7
|
100
|
|
|
|
26
|
$self->{MMBM_epilogue} = $epilogue |
305
|
|
|
|
|
|
|
if defined $epilogue; |
306
|
|
|
|
|
|
|
|
307
|
7
|
|
|
|
|
51
|
$self; |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
#------------------------------------------ |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
sub foreachComponent($) |
314
|
19
|
|
|
19
|
1
|
53
|
{ my ($self, $code) = @_; |
315
|
19
|
|
|
|
|
41
|
my $changes = 0; |
316
|
|
|
|
|
|
|
|
317
|
19
|
|
|
|
|
34
|
my $new_preamble; |
318
|
19
|
100
|
|
|
|
53
|
if(my $preamble = $self->preamble) |
319
|
2
|
|
|
|
|
7
|
{ $new_preamble = $code->($self, $preamble); |
320
|
2
|
100
|
|
|
|
12
|
$changes++ unless $preamble == $new_preamble; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
19
|
|
|
|
|
36
|
my $new_epilogue; |
324
|
19
|
100
|
|
|
|
45
|
if(my $epilogue = $self->epilogue) |
325
|
2
|
|
|
|
|
6
|
{ $new_epilogue = $code->($self, $epilogue); |
326
|
2
|
100
|
|
|
|
8
|
$changes++ unless $epilogue == $new_epilogue; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
19
|
|
|
|
|
47
|
my @new_bodies; |
330
|
19
|
|
|
|
|
56
|
foreach my $part ($self->parts('ACTIVE')) |
331
|
30
|
|
|
|
|
128
|
{ my $part_body = $part->body; |
332
|
30
|
|
|
|
|
95
|
my $new_body = $code->($self, $part_body); |
333
|
|
|
|
|
|
|
|
334
|
30
|
100
|
|
|
|
90
|
$changes++ if $new_body != $part_body; |
335
|
30
|
|
|
|
|
113
|
push @new_bodies, [$part, $new_body]; |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
19
|
100
|
|
|
|
87
|
return $self unless $changes; |
339
|
|
|
|
|
|
|
|
340
|
10
|
|
|
|
|
21
|
my @new_parts; |
341
|
10
|
|
|
|
|
28
|
foreach (@new_bodies) |
342
|
21
|
|
|
|
|
53
|
{ my ($part, $body) = @$_; |
343
|
21
|
|
|
|
|
74
|
my $new_part = Mail::Message::Part->new |
344
|
|
|
|
|
|
|
( head => $part->head->clone, |
345
|
|
|
|
|
|
|
container => undef |
346
|
|
|
|
|
|
|
); |
347
|
21
|
|
|
|
|
91
|
$new_part->body($body); |
348
|
21
|
|
|
|
|
58
|
push @new_parts, $new_part; |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
|
351
|
10
|
|
|
|
|
70
|
my $constructed = (ref $self)->new |
352
|
|
|
|
|
|
|
( preamble => $new_preamble |
353
|
|
|
|
|
|
|
, parts => \@new_parts |
354
|
|
|
|
|
|
|
, epilogue => $new_epilogue |
355
|
|
|
|
|
|
|
, based_on => $self |
356
|
|
|
|
|
|
|
); |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
$_->container($constructed) |
359
|
10
|
|
|
|
|
44
|
foreach @new_parts; |
360
|
|
|
|
|
|
|
|
361
|
10
|
|
|
|
|
57
|
$constructed; |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
sub attach(@) |
366
|
2
|
|
|
2
|
1
|
7
|
{ my $self = shift; |
367
|
2
|
|
|
|
|
8
|
my $new = ref($self)->new |
368
|
|
|
|
|
|
|
( based_on => $self |
369
|
|
|
|
|
|
|
, parts => [$self->parts, @_] |
370
|
|
|
|
|
|
|
); |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
sub stripSignature(@) |
375
|
1
|
|
|
1
|
1
|
3
|
{ my $self = shift; |
376
|
|
|
|
|
|
|
|
377
|
1
|
|
|
|
|
4
|
my @allparts = $self->parts; |
378
|
1
|
|
|
|
|
2
|
my @parts = grep {! $_->body->mimeType->isSignature} @allparts; |
|
2
|
|
|
|
|
38
|
|
379
|
|
|
|
|
|
|
|
380
|
1
|
50
|
|
|
|
35
|
@allparts==@parts ? $self |
381
|
|
|
|
|
|
|
: (ref $self)->new(based_on => $self, parts => \@parts); |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
#------------------------------------------ |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
|
387
|
103
|
|
|
103
|
1
|
361
|
sub preamble() {shift->{MMBM_preamble}} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
|
390
|
107
|
|
|
107
|
1
|
300
|
sub epilogue() {shift->{MMBM_epilogue}} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
sub parts(;$) |
394
|
157
|
|
|
157
|
1
|
379
|
{ my $self = shift; |
395
|
157
|
100
|
|
|
|
350
|
return @{$self->{MMBM_parts}} unless @_; |
|
66
|
|
|
|
|
354
|
|
396
|
|
|
|
|
|
|
|
397
|
91
|
|
|
|
|
147
|
my $what = shift; |
398
|
91
|
|
|
|
|
132
|
my @parts = @{$self->{MMBM_parts}}; |
|
91
|
|
|
|
|
237
|
|
399
|
|
|
|
|
|
|
|
400
|
0
|
|
|
|
|
0
|
$what eq 'RECURSE' ? (map {$_->parts('RECURSE')} @parts) |
401
|
|
|
|
|
|
|
: $what eq 'ALL' ? @parts |
402
|
0
|
|
|
|
|
0
|
: $what eq 'DELETED' ? (grep {$_->isDeleted} @parts) |
403
|
154
|
|
|
|
|
415
|
: $what eq 'ACTIVE' ? (grep {not $_->isDeleted} @parts) |
404
|
91
|
0
|
|
|
|
438
|
: ref $what eq 'CODE'? (grep {$what->($_)} @parts) |
|
0
|
50
|
|
|
|
0
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
405
|
|
|
|
|
|
|
: ($self->log(ERROR => "Unknown criterium $what to select parts."), return ()); |
406
|
|
|
|
|
|
|
} |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
|
409
|
13
|
|
|
13
|
1
|
124
|
sub part($) { shift->{MMBM_parts}[shift] } |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
sub partNumberOf($) |
412
|
8
|
|
|
8
|
1
|
22
|
{ my ($self, $part) = @_; |
413
|
8
|
|
|
|
|
22
|
my $msg = $self->message; |
414
|
8
|
50
|
|
|
|
28
|
unless($msg) |
415
|
0
|
|
|
|
|
0
|
{ $self->log(ERROR => 'multipart is not connected'); |
416
|
0
|
|
|
|
|
0
|
return 'ERROR'; |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
8
|
100
|
|
|
|
54
|
my $base = $msg->isa('Mail::Message::Part') ? $msg->partNumber.'.' : ''; |
420
|
|
|
|
|
|
|
|
421
|
8
|
|
|
|
|
23
|
my @parts = $self->parts('ACTIVE'); |
422
|
8
|
|
|
|
|
28
|
foreach my $partnr (0..@parts) |
423
|
15
|
100
|
|
|
|
93
|
{ return $base.($partnr+1) |
424
|
|
|
|
|
|
|
if $parts[$partnr] == $part; |
425
|
|
|
|
|
|
|
} |
426
|
0
|
|
|
|
|
0
|
$self->log(ERROR => 'multipart is not found or not active'); |
427
|
0
|
|
|
|
|
0
|
'ERROR'; |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
sub boundary(;$) |
432
|
112
|
|
|
112
|
1
|
201
|
{ my $self = shift; |
433
|
112
|
|
|
|
|
306
|
my $mime = $self->type; |
434
|
|
|
|
|
|
|
|
435
|
112
|
100
|
|
|
|
313
|
unless(@_) |
436
|
71
|
|
|
|
|
262
|
{ my $boundary = $mime->attribute('boundary'); |
437
|
71
|
50
|
|
|
|
332
|
return $boundary if defined $boundary; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
41
|
100
|
66
|
|
|
462
|
my $boundary = @_ && defined $_[0] ? (shift) : "boundary-".int rand(1000000); |
441
|
41
|
|
|
|
|
140
|
$self->type->attribute(boundary => $boundary); |
442
|
|
|
|
|
|
|
} |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
sub endsOnNewline() { 1 } |
445
|
|
|
|
|
|
|
|
446
|
0
|
0
|
|
0
|
0
|
|
sub toplevel() { my $msg = shift->message; $msg ? $msg->toplevel : undef} |
|
0
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
#------------------------------------------- |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
1; |