| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Mail::RFC822::Address; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
697
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
37
|
|
|
4
|
1
|
|
|
1
|
|
6
|
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
942
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
require Exporter; |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# Items to export into callers namespace by default. Note: do not export |
|
11
|
|
|
|
|
|
|
# names by default without a very good reason. Use EXPORT_OK instead. |
|
12
|
|
|
|
|
|
|
# Do not simply export all your public functions/methods/constants. |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
@EXPORT_OK = qw( valid validlist ); |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
@EXPORT = qw( |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
); |
|
19
|
|
|
|
|
|
|
$VERSION = '0.3'; |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my $rfc822re; |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# Preloaded methods go here. |
|
25
|
|
|
|
|
|
|
my $lwsp = "(?:(?:\\r\\n)?[ \\t])"; |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub make_rfc822re { |
|
28
|
|
|
|
|
|
|
# Basic lexical tokens are specials, domain_literal, quoted_string, atom, and |
|
29
|
|
|
|
|
|
|
# comment. We must allow for lwsp (or comments) after each of these. |
|
30
|
|
|
|
|
|
|
# This regexp will only work on addresses which have had comments stripped |
|
31
|
|
|
|
|
|
|
# and replaced with lwsp. |
|
32
|
|
|
|
|
|
|
|
|
33
|
1
|
|
|
1
|
0
|
2
|
my $specials = '()<>@,;:\\\\".\\[\\]'; |
|
34
|
1
|
|
|
|
|
3
|
my $controls = '\\000-\\031'; |
|
35
|
|
|
|
|
|
|
|
|
36
|
1
|
|
|
|
|
2
|
my $dtext = "[^\\[\\]\\r\\\\]"; |
|
37
|
1
|
|
|
|
|
4
|
my $domain_literal = "\\[(?:$dtext|\\\\.)*\\]$lwsp*"; |
|
38
|
|
|
|
|
|
|
|
|
39
|
1
|
|
|
|
|
5
|
my $quoted_string = "\"(?:[^\\\"\\r\\\\]|\\\\.|$lwsp)*\"$lwsp*"; |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# Use zero-width assertion to spot the limit of an atom. A simple |
|
42
|
|
|
|
|
|
|
# $lwsp* causes the regexp engine to hang occasionally. |
|
43
|
1
|
|
|
|
|
5
|
my $atom = "[^$specials $controls]+(?:$lwsp+|\\Z|(?=[\\[\"$specials]))"; |
|
44
|
1
|
|
|
|
|
4
|
my $word = "(?:$atom|$quoted_string)"; |
|
45
|
1
|
|
|
|
|
4
|
my $localpart = "$word(?:\\.$lwsp*$word)*"; |
|
46
|
|
|
|
|
|
|
|
|
47
|
1
|
|
|
|
|
4
|
my $sub_domain = "(?:$atom|$domain_literal)"; |
|
48
|
1
|
|
|
|
|
4
|
my $domain = "$sub_domain(?:\\.$lwsp*$sub_domain)*"; |
|
49
|
|
|
|
|
|
|
|
|
50
|
1
|
|
|
|
|
3
|
my $addr_spec = "$localpart\@$lwsp*$domain"; |
|
51
|
|
|
|
|
|
|
|
|
52
|
1
|
|
|
|
|
4
|
my $phrase = "$word*"; |
|
53
|
1
|
|
|
|
|
7
|
my $route = "(?:\@$domain(?:,\@$lwsp*$domain)*:$lwsp*)"; |
|
54
|
1
|
|
|
|
|
16
|
my $route_addr = "\\<$lwsp*$route?$addr_spec\\>$lwsp*"; |
|
55
|
1
|
|
|
|
|
14
|
my $mailbox = "(?:$addr_spec|$phrase$route_addr)"; |
|
56
|
|
|
|
|
|
|
|
|
57
|
1
|
|
|
|
|
21
|
my $group = "$phrase:$lwsp*(?:$mailbox(?:,\\s*$mailbox)*)?;\\s*"; |
|
58
|
1
|
|
|
|
|
16
|
my $address = "(?:$mailbox|$group)"; |
|
59
|
|
|
|
|
|
|
|
|
60
|
1
|
|
|
|
|
14
|
return "$lwsp*$address"; |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub strip_comments { |
|
64
|
79
|
|
|
79
|
0
|
113
|
my $s = shift; |
|
65
|
|
|
|
|
|
|
# Recursively remove comments, and replace with a single space. The simpler |
|
66
|
|
|
|
|
|
|
# regexps in the Email Addressing FAQ are imperfect - they will miss escaped |
|
67
|
|
|
|
|
|
|
# chars in atoms, for example. |
|
68
|
|
|
|
|
|
|
|
|
69
|
79
|
|
|
|
|
1272
|
while ($s =~ s/^((?:[^"\\]|\\.)* |
|
70
|
|
|
|
|
|
|
(?:"(?:[^"\\]|\\.)*"(?:[^"\\]|\\.)*)*) |
|
71
|
|
|
|
|
|
|
\((?:[^()\\]|\\.)*\)/$1 /osx) {} |
|
72
|
79
|
|
|
|
|
160
|
return $s; |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# valid: returns true if the parameter is an RFC822 valid address |
|
76
|
|
|
|
|
|
|
# |
|
77
|
|
|
|
|
|
|
sub valid ($) { |
|
78
|
67
|
|
|
67
|
1
|
3588
|
my $s = strip_comments(shift); |
|
79
|
|
|
|
|
|
|
|
|
80
|
67
|
100
|
|
|
|
137
|
if (!$rfc822re) { |
|
81
|
1
|
|
|
|
|
5
|
$rfc822re = make_rfc822re(); |
|
82
|
|
|
|
|
|
|
} |
|
83
|
|
|
|
|
|
|
|
|
84
|
67
|
|
|
|
|
4145
|
return $s =~ m/^$rfc822re$/so; |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# validlist: In scalar context, returns true if the parameter is an RFC822 |
|
88
|
|
|
|
|
|
|
# valid list of addresses. |
|
89
|
|
|
|
|
|
|
# |
|
90
|
|
|
|
|
|
|
# In list context, returns an empty list on failure (an invalid |
|
91
|
|
|
|
|
|
|
# address was found); otherwise a list whose first element is the |
|
92
|
|
|
|
|
|
|
# number of addresses found and whose remaining elements are the |
|
93
|
|
|
|
|
|
|
# addresses. This is needed to disambiguate failure (invalid) |
|
94
|
|
|
|
|
|
|
# from success with no addresses found, because an empty string is |
|
95
|
|
|
|
|
|
|
# a valid list. |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub validlist ($) { |
|
98
|
12
|
|
|
12
|
1
|
1706
|
my $s = strip_comments(shift); |
|
99
|
|
|
|
|
|
|
|
|
100
|
12
|
50
|
|
|
|
31
|
if (!$rfc822re) { |
|
101
|
0
|
|
|
|
|
0
|
$rfc822re = make_rfc822re(); |
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
# * null list items are valid according to the RFC |
|
104
|
|
|
|
|
|
|
# * the '1' business is to aid in distinguishing failure from no results |
|
105
|
|
|
|
|
|
|
|
|
106
|
12
|
|
|
|
|
15
|
my @r; |
|
107
|
12
|
100
|
|
|
|
4632
|
if($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so) { |
|
108
|
10
|
|
|
|
|
2538
|
while($s =~ m/(?:^|,$lwsp*)($rfc822re)/gos) { |
|
109
|
15
|
|
|
|
|
130
|
push @r, $1; |
|
110
|
|
|
|
|
|
|
} |
|
111
|
10
|
100
|
|
|
|
53
|
return wantarray ? (scalar(@r), @r) : 1; |
|
112
|
|
|
|
|
|
|
} |
|
113
|
|
|
|
|
|
|
else { |
|
114
|
2
|
100
|
|
|
|
10
|
return wantarray ? () : 0; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
1; |
|
119
|
|
|
|
|
|
|
__END__ |