line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyrights 2001-2022 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::Field::Attribute; |
10
|
21
|
|
|
21
|
|
643
|
use vars '$VERSION'; |
|
21
|
|
|
|
|
43
|
|
|
21
|
|
|
|
|
1092
|
|
11
|
|
|
|
|
|
|
$VERSION = '3.012'; |
12
|
|
|
|
|
|
|
|
13
|
21
|
|
|
21
|
|
116
|
use base 'Mail::Reporter'; |
|
21
|
|
|
|
|
38
|
|
|
21
|
|
|
|
|
2234
|
|
14
|
|
|
|
|
|
|
|
15
|
21
|
|
|
21
|
|
124
|
use strict; |
|
21
|
|
|
|
|
44
|
|
|
21
|
|
|
|
|
361
|
|
16
|
21
|
|
|
21
|
|
95
|
use warnings; |
|
21
|
|
|
|
|
48
|
|
|
21
|
|
|
|
|
480
|
|
17
|
|
|
|
|
|
|
|
18
|
21
|
|
|
21
|
|
567
|
use Encode (); |
|
21
|
|
|
|
|
8532
|
|
|
21
|
|
|
|
|
352
|
|
19
|
21
|
|
|
21
|
|
90
|
use Carp; |
|
21
|
|
|
|
|
45
|
|
|
21
|
|
|
|
|
1303
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
22
|
21
|
|
|
21
|
|
113
|
use Carp 'cluck'; |
|
21
|
|
|
|
|
46
|
|
|
21
|
|
|
|
|
3176
|
|
23
|
|
|
|
|
|
|
use overload |
24
|
265
|
|
|
265
|
|
1202
|
'""' => sub {shift->value} |
25
|
158
|
|
|
158
|
|
1542
|
, cmp => sub { my ($self, $other) = @_; |
26
|
158
|
50
|
0
|
|
|
791
|
UNIVERSAL::isa($other, 'Mail::Message::Field') |
27
|
|
|
|
|
|
|
? (lc($_[0])->name cmp lc($_[1]->name) || $_[0]->value cmp $_[1]->value) |
28
|
|
|
|
|
|
|
: $_[0]->value cmp $_[1] |
29
|
|
|
|
|
|
|
} |
30
|
21
|
|
|
21
|
|
138
|
, fallback => 1; |
|
21
|
|
|
|
|
62
|
|
|
21
|
|
|
|
|
251
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub new($$@) |
35
|
120
|
|
|
120
|
1
|
3196
|
{ my ($class, $attr) = (shift, shift); |
36
|
120
|
100
|
|
|
|
352
|
my $value = @_ % 2 == 1 ? shift : undef; |
37
|
120
|
|
|
|
|
464
|
$class->SUPER::new(attr => $attr, value => $value, @_); |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub init($$) |
41
|
120
|
|
|
120
|
0
|
246
|
{ my ($self, $args) = @_; |
42
|
120
|
|
|
|
|
337
|
$self->SUPER::init($args); |
43
|
|
|
|
|
|
|
|
44
|
120
|
|
|
|
|
395
|
my ($attr, $value, $cont) = @$args{ qw/attr value use_continuations/ }; |
45
|
|
|
|
|
|
|
|
46
|
120
|
100
|
|
|
|
727
|
my $name = ($attr =~ m/^(.*?)(?:\*\d+)?\*?\s*\=\s*/ ? $1 : $attr); |
47
|
120
|
50
|
|
|
|
471
|
$self->log(WARNING => "Illegal character in parameter name '$name'.") |
48
|
|
|
|
|
|
|
if $name !~ m/^[!#-'*+\-.0-9A-Z^-~]+$/; |
49
|
|
|
|
|
|
|
|
50
|
120
|
|
|
|
|
239
|
$self->{MMFF_name} = $name; |
51
|
120
|
100
|
|
|
|
314
|
$self->{MMFF_usecont} = defined $cont ? $cont : 1; |
52
|
120
|
100
|
|
|
|
283
|
$self->{MMFF_charset} = $args->{charset} if defined $args->{charset}; |
53
|
120
|
100
|
|
|
|
258
|
$self->{MMFF_language} = $args->{language} if defined $args->{language}; |
54
|
|
|
|
|
|
|
|
55
|
120
|
100
|
|
|
|
504
|
$self->value(defined $value ? "$value" : ''); # enforce stringification |
56
|
120
|
100
|
|
|
|
405
|
$self->addComponent($attr) if $attr ne $name; |
57
|
|
|
|
|
|
|
|
58
|
120
|
|
|
|
|
397
|
$self; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
#------------------------------------------ |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
64
|
69
|
|
|
69
|
1
|
949
|
sub name() { shift->{MMFF_name} } |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub value(;$) |
68
|
581
|
|
|
581
|
1
|
3319
|
{ my $self = shift; |
69
|
581
|
100
|
|
|
|
1041
|
if(@_) |
70
|
128
|
|
|
|
|
193
|
{ delete $self->{MMFF_cont}; |
71
|
128
|
|
|
|
|
307
|
return $self->{MMFF_value} = shift; |
72
|
|
|
|
|
|
|
} |
73
|
453
|
100
|
|
|
|
1975
|
exists $self->{MMFF_value} ? $self->{MMFF_value} : $self->decode; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub addComponent($) |
78
|
81
|
|
|
81
|
1
|
1975
|
{ my ($self, $component) = @_; |
79
|
81
|
|
|
|
|
161
|
delete $self->{MMFF_value}; |
80
|
|
|
|
|
|
|
|
81
|
81
|
|
|
|
|
304
|
my ($name, $value) = split /\=/, $component, 2; |
82
|
81
|
100
|
100
|
|
|
371
|
if( substr($name, -1) eq '*' && $value =~ m/^([^']*)\'([^']*)\'/ ) |
83
|
6
|
100
|
|
|
|
19
|
{ $self->{MMFF_charset} = length $1 ? $1 : undef; |
84
|
6
|
100
|
|
|
|
19
|
$self->{MMFF_language} = length $2 ? $2 : undef; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
81
|
100
|
|
|
|
253
|
if( $name =~ m/\*([0-9]+)\*?$/ ) |
88
|
8
|
|
|
|
|
24
|
{ $self->{MMFF_cont}[$1] = $component } |
89
|
73
|
|
|
|
|
184
|
else { $self->{MMFF_cont} = [ $component ] } |
90
|
|
|
|
|
|
|
|
91
|
81
|
|
|
|
|
155
|
$component; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
|
95
|
7
|
|
|
7
|
1
|
28
|
sub charset() { shift->{MMFF_charset} } |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
|
98
|
7
|
|
|
7
|
1
|
29
|
sub language() { shift->{MMFF_language} } |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub string() |
102
|
63
|
|
|
63
|
1
|
5887
|
{ my $self = shift; |
103
|
63
|
|
66
|
|
|
286
|
my $cont = $self->{MMFF_cont} || $self->encode; |
104
|
63
|
100
|
|
|
|
438
|
return @$cont if wantarray; |
105
|
9
|
50
|
|
|
|
22
|
return [] unless @$cont; |
106
|
|
|
|
|
|
|
|
107
|
9
|
|
|
|
|
17
|
local $" = "; "; |
108
|
9
|
|
|
|
|
55
|
"; @$cont"; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
#------------------------------------------ |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub encode() |
115
|
48
|
|
|
48
|
1
|
85
|
{ my $self = shift; |
116
|
48
|
|
|
|
|
111
|
my $value = $self->{MMFF_value}; |
117
|
|
|
|
|
|
|
|
118
|
48
|
|
|
|
|
81
|
my @lines; |
119
|
48
|
|
|
|
|
93
|
my ($pre, $encoded); |
120
|
|
|
|
|
|
|
|
121
|
48
|
|
100
|
|
|
246
|
my $charset = $self->{MMFF_charset} || ''; |
122
|
48
|
|
100
|
|
|
185
|
my $lang = $self->{MMFF_language} || ''; |
123
|
48
|
|
|
|
|
120
|
my $name = $self->{MMFF_name}; |
124
|
48
|
|
|
|
|
91
|
my $cont = $self->{MMFF_usecont}; |
125
|
|
|
|
|
|
|
|
126
|
48
|
100
|
66
|
|
|
397
|
if($charset || $lang) |
|
|
50
|
|
|
|
|
|
127
|
6
|
|
|
|
|
16
|
{ $pre = "$name*0*=$charset'$lang'"; |
128
|
6
|
|
|
|
|
19
|
$value = Encode::encode($charset, $value, 0); |
129
|
6
|
|
|
|
|
2501
|
$encoded = 1; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
elsif(grep m/[^\x20-\x7E]/, $value) |
132
|
0
|
|
|
|
|
0
|
{ $pre = "$name*0*=''"; |
133
|
0
|
|
|
|
|
0
|
$encoded = 1; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
else |
136
|
42
|
|
|
|
|
108
|
{ $pre = "$name*0="; |
137
|
42
|
|
|
|
|
109
|
$value =~ s/"/\\"/g; |
138
|
42
|
|
|
|
|
133
|
$encoded = 0; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
48
|
100
|
|
|
|
167
|
if($encoded) |
|
|
50
|
|
|
|
|
|
142
|
|
|
|
|
|
|
{ # Use encoding |
143
|
6
|
|
|
|
|
30
|
my @c = split //, $value; |
144
|
6
|
|
|
|
|
13
|
while(@c) |
145
|
169
|
|
|
|
|
214
|
{ my $c = shift @c; |
146
|
169
|
100
|
|
|
|
343
|
$c = '%'. sprintf "%02X", ord $c |
147
|
|
|
|
|
|
|
unless $c =~ m/[a-zA-Z0-9]/; |
148
|
|
|
|
|
|
|
|
149
|
169
|
100
|
100
|
|
|
317
|
if($cont && length($pre) + length($c)> 76) |
150
|
2
|
|
|
|
|
3
|
{ push @lines, $pre; |
151
|
2
|
|
|
|
|
7
|
$pre = $name . '*' . @lines . '*=' . $c; |
152
|
|
|
|
|
|
|
} |
153
|
167
|
|
|
|
|
266
|
else { $pre .= $c } |
154
|
|
|
|
|
|
|
} |
155
|
6
|
|
|
|
|
13
|
push @lines, $pre; |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
elsif($cont) |
158
|
|
|
|
|
|
|
{ # Simple string, but with continuations |
159
|
42
|
|
|
|
|
60
|
while(1) |
160
|
43
|
|
|
|
|
266
|
{ push @lines, $pre.'"'. substr($value, 0, 75-length($pre), '') .'"'; |
161
|
43
|
100
|
|
|
|
147
|
last unless length $value; |
162
|
1
|
|
|
|
|
4
|
$pre = $name . '*' . @lines . '='; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
else |
167
|
|
|
|
|
|
|
{ # Single string only |
168
|
0
|
|
|
|
|
0
|
push @lines, $pre . $value; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
48
|
100
|
|
|
|
246
|
$lines[0] =~ s/\*0// if @lines==1; |
172
|
48
|
|
|
|
|
228
|
$self->{MMFF_cont} = \@lines; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub decode() |
177
|
80
|
|
|
80
|
1
|
156
|
{ my $self = shift; |
178
|
80
|
|
|
|
|
140
|
my $value = ''; |
179
|
|
|
|
|
|
|
|
180
|
80
|
|
|
|
|
121
|
foreach my $cont ( @{$self->{MMFF_cont}} ) |
|
80
|
|
|
|
|
199
|
|
181
|
86
|
100
|
|
|
|
222
|
{ unless(defined $cont) |
182
|
1
|
|
|
|
|
3
|
{ $value .= "[continuation missing]"; |
183
|
1
|
|
|
|
|
3
|
next; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
85
|
|
|
|
|
322
|
(my $name, local $_) = split /\=/, $cont, 2; |
187
|
|
|
|
|
|
|
|
188
|
85
|
100
|
|
|
|
493
|
if(substr($name, -1) eq '*') |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
189
|
12
|
|
|
|
|
40
|
{ s/^[^']*\'[^']*\'//; |
190
|
12
|
|
|
|
|
26
|
s/\%([a-fA-F0-9]{2})/chr hex $1/ge; |
|
47
|
|
|
|
|
106
|
|
191
|
|
|
|
|
|
|
} |
192
|
1
|
|
|
|
|
4
|
elsif( s/^\"(.*)\"$/$1/ ) { s/\\\"/"/g } |
193
|
2
|
|
|
|
|
7
|
elsif( s/^\'(.*)\'$/$1/ ) { s/\\\'/'/g } |
194
|
|
|
|
|
|
|
|
195
|
85
|
|
|
|
|
240
|
$value .= $_; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
80
|
|
|
|
|
169
|
my $charset = $self->{MMFF_charset}; |
199
|
80
|
100
|
|
|
|
207
|
$value = Encode::decode($charset, $value, 0) if $charset; |
200
|
|
|
|
|
|
|
|
201
|
80
|
|
|
|
|
1109
|
$self->{MMFF_value} = $value; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
#------------------------------------------ |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
sub mergeComponent($) |
208
|
1
|
|
|
1
|
1
|
3
|
{ my ($self, $comp) = @_; |
209
|
|
|
|
|
|
|
my $cont = $self->{MMFF_cont} |
210
|
1
|
50
|
|
|
|
4
|
or croak "ERROR: Too late to merge: value already changed."; |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
defined $_ && $self->addComponent($_) |
213
|
1
|
|
33
|
|
|
2
|
foreach @{$comp->{MMFF_cont}}; |
|
1
|
|
|
|
|
5
|
|
214
|
|
|
|
|
|
|
|
215
|
1
|
|
|
|
|
4
|
$self; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
1; |