line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
1
|
|
|
1
|
|
55015
|
use warnings; |
|
1
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
31
|
|
2
|
1
|
|
|
1
|
|
4
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
41
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package Mail::IMAPClient::BodyStructure; |
5
|
1
|
|
|
1
|
|
2703
|
use Mail::IMAPClient::BodyStructure::Parse; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
501
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
# BUG?: old code used name "HEAD" instead of "HEADER", change? |
8
|
|
|
|
|
|
|
my $HEAD = "HEAD"; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# my has file scope, not limited to package! |
11
|
|
|
|
|
|
|
my $parser = Mail::IMAPClient::BodyStructure::Parse->new |
12
|
|
|
|
|
|
|
or die "Cannot parse rules: $@\n" |
13
|
|
|
|
|
|
|
. "Try remaking Mail::IMAPClient::BodyStructure::Parse.\n"; |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub new { |
16
|
9
|
|
|
9
|
1
|
1099
|
my $class = shift; |
17
|
9
|
|
|
|
|
20
|
my $bodystructure = shift; |
18
|
|
|
|
|
|
|
|
19
|
9
|
50
|
|
|
|
101
|
my $self = $parser->start($bodystructure) |
20
|
|
|
|
|
|
|
or return undef; |
21
|
|
|
|
|
|
|
|
22
|
9
|
|
|
|
|
177
|
$self->{_prefix} = ""; |
23
|
9
|
100
|
|
|
|
47
|
$self->{_id} = exists $self->{bodystructure} ? $HEAD : 1; |
24
|
9
|
|
|
|
|
26
|
$self->{_top} = 1; |
25
|
|
|
|
|
|
|
|
26
|
9
|
|
33
|
|
|
72
|
bless $self, ref($class) || $class; |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub _get_thingy { |
30
|
89
|
|
|
89
|
|
105
|
my $thingy = shift; |
31
|
89
|
|
33
|
|
|
128
|
my $object = shift || ( ref $thingy ? $thingy : undef ); |
32
|
|
|
|
|
|
|
|
33
|
89
|
50
|
33
|
|
|
231
|
unless ( $object && ref $object ) { |
34
|
0
|
|
|
|
|
0
|
warn $@ = "No argument passed to $thingy method."; |
35
|
0
|
|
|
|
|
0
|
return undef; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
89
|
50
|
33
|
|
|
270
|
unless ( UNIVERSAL::isa( $object, 'HASH' ) && exists $object->{$thingy} ) { |
39
|
0
|
0
|
|
|
|
0
|
my $a = $thingy =~ /^[aeiou]/i ? 'an' : 'a'; |
40
|
0
|
0
|
|
|
|
0
|
my $has = ref $object eq 'HASH' ? join( ", ", keys %$object ) : ''; |
41
|
0
|
0
|
|
|
|
0
|
warn $@ = |
42
|
|
|
|
|
|
|
ref($object) |
43
|
|
|
|
|
|
|
. " $object does not have $a $thingy. " |
44
|
|
|
|
|
|
|
. ( $has ? "It has $has" : '' ); |
45
|
0
|
|
|
|
|
0
|
return undef; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
89
|
|
|
|
|
123
|
my $value = $object->{$thingy}; |
49
|
89
|
|
|
|
|
126
|
$value =~ s/\\ ( [\\\(\)"\x0d\x0a] )/$1/gx; |
50
|
89
|
|
|
|
|
98
|
$value =~ s/^"(.*)"$/$1/; |
51
|
89
|
|
|
|
|
193
|
$value; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
BEGIN { |
55
|
1
|
|
|
1
|
|
13
|
no strict 'refs'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
82
|
|
56
|
1
|
|
|
1
|
|
5
|
foreach my $datum ( |
57
|
|
|
|
|
|
|
qw/ bodytype bodysubtype bodyparms bodydisp bodyid bodydesc bodyenc |
58
|
|
|
|
|
|
|
bodysize bodylang envelopestruct textlines / |
59
|
|
|
|
|
|
|
) |
60
|
|
|
|
|
|
|
{ |
61
|
11
|
|
|
89
|
|
932
|
*$datum = sub { _get_thingy( $datum, @_ ) }; |
|
89
|
|
|
|
|
1064
|
|
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub parts { |
66
|
6
|
|
|
6
|
0
|
2811
|
my $self = shift; |
67
|
0
|
|
|
|
|
0
|
return wantarray ? @{ $self->{PartsList} } : $self->{PartsList} |
68
|
6
|
0
|
|
|
|
27
|
if exists $self->{PartsList}; |
|
|
50
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
6
|
|
|
|
|
16
|
my @parts; |
71
|
6
|
|
|
|
|
19
|
$self->{PartsList} = \@parts; |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# BUG?: should this default to ($HEAD, TEXT) |
74
|
6
|
50
|
|
|
|
23
|
unless ( exists $self->{bodystructure} ) { |
75
|
0
|
|
|
|
|
0
|
$self->{PartsIndex}{1} = $self; |
76
|
0
|
|
|
|
|
0
|
@parts = ( $HEAD, 1 ); |
77
|
0
|
0
|
|
|
|
0
|
return wantarray ? @parts : \@parts; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
6
|
|
|
|
|
24
|
foreach my $p ( $self->bodystructure ) { |
81
|
85
|
|
|
|
|
133
|
my $id = $p->id; |
82
|
85
|
|
|
|
|
122
|
push @parts, $id; |
83
|
85
|
|
|
|
|
167
|
$self->{PartsIndex}{$id} = $p; |
84
|
85
|
|
50
|
|
|
124
|
my $type = uc $p->bodytype || ''; |
85
|
|
|
|
|
|
|
|
86
|
85
|
100
|
|
|
|
174
|
push @parts, "$id.$HEAD" |
87
|
|
|
|
|
|
|
if $type eq 'MESSAGE'; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
6
|
50
|
|
|
|
64
|
wantarray ? @parts : \@parts; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub bodystructure { |
94
|
55
|
|
|
55
|
1
|
76
|
my $self = shift; |
95
|
55
|
|
|
|
|
63
|
my $partno = 0; |
96
|
55
|
|
|
|
|
62
|
my @parts; |
97
|
|
|
|
|
|
|
|
98
|
55
|
100
|
|
|
|
139
|
if ( $self->{_top} ) { |
99
|
6
|
|
33
|
|
|
23
|
$self->{_id} ||= $HEAD; |
100
|
6
|
|
33
|
|
|
36
|
$self->{_prefix} ||= $HEAD; |
101
|
6
|
|
|
|
|
11
|
$partno = 0; |
102
|
6
|
|
|
|
|
12
|
foreach my $b ( @{ $self->{bodystructure} } ) { |
|
6
|
|
|
|
|
20
|
|
103
|
24
|
|
|
|
|
41
|
$b->{_id} = ++$partno; |
104
|
24
|
|
|
|
|
55
|
$b->{_prefix} = $partno; |
105
|
24
|
|
|
|
|
48
|
push @parts, $b, $b->bodystructure; |
106
|
|
|
|
|
|
|
} |
107
|
6
|
50
|
|
|
|
27
|
return wantarray ? @parts : \@parts; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
49
|
|
50
|
|
|
91
|
my $prefix = $self->{_prefix} || ""; |
111
|
49
|
|
|
|
|
153
|
$prefix =~ s/\.?$/./; |
112
|
|
|
|
|
|
|
|
113
|
49
|
|
|
|
|
70
|
foreach my $p ( @{ $self->{bodystructure} } ) { |
|
49
|
|
|
|
|
98
|
|
114
|
61
|
|
|
|
|
73
|
$partno++; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# BUG?: old code didn't add .TEXT sections, should we skip these? |
117
|
|
|
|
|
|
|
# - This code needs to be generalised (maybe it belongs in parts()?) |
118
|
|
|
|
|
|
|
# - Should every message should have HEAD (actually MIME) and TEXT? |
119
|
|
|
|
|
|
|
# at least dovecot and iplanet appear to allow this even for |
120
|
|
|
|
|
|
|
# non-multipart sections |
121
|
61
|
|
|
|
|
73
|
my $pno = $partno; |
122
|
61
|
|
50
|
|
|
109
|
my $stype = $self->{bodytype} || ""; |
123
|
61
|
|
50
|
|
|
139
|
my $ptype = $p->{bodytype} || ""; |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# a message and the multipart inside of it "collapse together" |
126
|
61
|
100
|
100
|
|
|
182
|
if ( $partno == 1 and $stype eq 'MESSAGE' and $ptype eq 'MULTIPART' ) { |
|
|
|
100
|
|
|
|
|
127
|
15
|
|
|
|
|
48
|
$pno = "TEXT"; |
128
|
15
|
|
|
|
|
30
|
$p->{_prefix} = "$prefix"; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
else { |
131
|
46
|
|
|
|
|
81
|
$p->{_prefix} = "$prefix$partno"; |
132
|
|
|
|
|
|
|
} |
133
|
61
|
|
33
|
|
|
208
|
$p->{_id} ||= "$prefix$pno"; |
134
|
|
|
|
|
|
|
|
135
|
61
|
100
|
|
|
|
149
|
push @parts, $p, $p->{bodystructure} ? $p->bodystructure : (); |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
49
|
50
|
|
|
|
140
|
wantarray ? @parts : \@parts; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
sub id { |
142
|
85
|
|
|
85
|
0
|
107
|
my $self = shift; |
143
|
|
|
|
|
|
|
return $self->{_id} |
144
|
85
|
50
|
|
|
|
174
|
if exists $self->{_id}; |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
return $HEAD |
147
|
0
|
0
|
|
|
|
0
|
if $self->{_top}; |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# BUG?: can this be removed? ... seems wrong |
150
|
0
|
0
|
|
|
|
0
|
if ( $self->{bodytype} eq 'MULTIPART' ) { |
151
|
0
|
|
0
|
|
|
0
|
my $p = $self->{_id} || $self->{_prefix}; |
152
|
0
|
|
|
|
|
0
|
$p =~ s/\.$//; |
153
|
0
|
|
|
|
|
0
|
return $p; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
else { |
156
|
0
|
|
0
|
|
|
0
|
return $self->{_id} ||= 1; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
package Mail::IMAPClient::BodyStructure::Part; |
161
|
|
|
|
|
|
|
our @ISA = qw/Mail::IMAPClient::BodyStructure/; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
package Mail::IMAPClient::BodyStructure::Envelope; |
164
|
|
|
|
|
|
|
our @ISA = qw/Mail::IMAPClient::BodyStructure/; |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub new { |
167
|
1
|
|
|
1
|
|
3
|
my ( $class, $envelope ) = @_; |
168
|
1
|
|
|
|
|
13
|
$parser->envelope($envelope); |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub parse_string { |
172
|
3
|
|
|
3
|
|
1493
|
my ( $class, $envelope ) = @_; |
173
|
3
|
100
|
|
|
|
20
|
$envelope = "(" . $envelope . ")" unless ( $envelope =~ /^\(/ ); |
174
|
3
|
|
|
|
|
30
|
$parser->envelopestruct($envelope); |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
0
|
|
|
0
|
|
0
|
sub from_addresses { shift->_addresses( from => 1 ) } |
178
|
0
|
|
|
0
|
|
0
|
sub sender_addresses { shift->_addresses( sender => 1 ) } |
179
|
0
|
|
|
0
|
|
0
|
sub replyto_addresses { shift->_addresses( replyto => 1 ) } |
180
|
4
|
|
|
4
|
|
19
|
sub to_addresses { shift->_addresses( to => 0 ) } |
181
|
0
|
|
|
0
|
|
0
|
sub cc_addresses { shift->_addresses( cc => 0 ) } |
182
|
0
|
|
|
0
|
|
0
|
sub bcc_addresses { shift->_addresses( bcc => 0 ) } |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
sub _addresses($$$) { |
185
|
4
|
|
|
4
|
|
10
|
my ( $self, $name, $isSender ) = @_; |
186
|
4
|
50
|
|
|
|
20
|
ref $self->{$name} eq 'ARRAY' |
187
|
|
|
|
|
|
|
or return (); |
188
|
|
|
|
|
|
|
|
189
|
4
|
|
|
|
|
7
|
my @list; |
190
|
4
|
|
|
|
|
6
|
foreach ( @{ $self->{$name} } ) { |
|
4
|
|
|
|
|
12
|
|
191
|
4
|
|
|
|
|
15
|
my $pn = $_->personalname; |
192
|
4
|
100
|
66
|
|
|
22
|
my $name = $pn && $pn ne 'NIL' ? "$pn " : ''; |
193
|
4
|
|
|
|
|
17
|
push @list, $name . '<' . $_->mailboxname . '@' . $_->hostname . '>'; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
wantarray ? @list |
197
|
4
|
50
|
|
|
|
19
|
: $isSender ? $list[0] |
|
|
50
|
|
|
|
|
|
198
|
|
|
|
|
|
|
: \@list; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
BEGIN { |
202
|
1
|
|
|
1
|
|
8
|
no strict 'refs'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
78
|
|
203
|
1
|
|
|
1
|
|
4
|
for my $datum ( |
204
|
|
|
|
|
|
|
qw(subject inreplyto from messageid bcc date |
205
|
|
|
|
|
|
|
replyto to sender cc) |
206
|
|
|
|
|
|
|
) |
207
|
|
|
|
|
|
|
{ |
208
|
24
|
50
|
|
24
|
|
570
|
*$datum = sub { @_ > 1 ? $_[0]->{$datum} = $_[1] : $_[0]->{$datum} } |
209
|
10
|
|
|
|
|
105
|
} |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
package Mail::IMAPClient::BodyStructure::Address; |
213
|
|
|
|
|
|
|
our @ISA = qw/Mail::IMAPClient::BodyStructure/; |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
for my $datum (qw(personalname mailboxname hostname sourcename)) { |
216
|
1
|
|
|
1
|
|
6
|
no strict 'refs'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
57
|
|
217
|
12
|
|
|
12
|
|
48
|
*$datum = sub { shift->{$datum}; }; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
1; |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
__END__ |