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__ |