File Coverage

blib/lib/Net/IDN/Encode.pm
Criterion Covered Total %
statement 53 53 100.0
branch 25 32 78.1
condition 6 12 50.0
subroutine 17 17 100.0
pod 6 8 75.0
total 107 122 87.7


line stmt bran cond sub pod time code
1             package Net::IDN::Encode;
2              
3             require 5.006;
4              
5 12     12   213498 use strict;
  12         57  
  12         356  
6 12     12   1198 use utf8;
  12         61  
  12         68  
7 12     12   364 use warnings;
  12         24  
  12         739  
8              
9             our $VERSION = "2.499_20180924";
10             $VERSION = eval $VERSION;
11              
12 12     12   74 use Carp;
  12         26  
  12         741  
13 12     12   76 use Exporter;
  12         26  
  12         1483  
14              
15             our @ISA = ('Exporter');
16             our @EXPORT = ();
17             our %EXPORT_TAGS = (
18             'all' => [
19             'to_ascii',
20             'to_unicode',
21             'domain_to_ascii',
22             'domain_to_unicode',
23             'email_to_ascii',
24             'email_to_unicode',
25             ],
26             '_var' => [
27             '$IDNA_PREFIX',
28             'IsIDNADot',
29             'IsIDNAAtsign',
30             ]
31             );
32             Exporter::export_ok_tags(keys %EXPORT_TAGS);
33              
34 12     12   2014 use Net::IDN::Punycode 1.102 ();
  12         300  
  12         1634  
35              
36             our $IDNA_PREFIX = 'xn--';
37 10     10 0 1522 sub IsIDNADot { "002E\n3002\nFF0E\nFF61" }
38 4     4 0 678 sub IsIDNAAtsign{ "0040\nFE6B\nFF20" }
39              
40             require Net::IDN::UTS46; # after declaration of vars!
41              
42             sub to_ascii {
43 88     88 1 369 my($label,%param) = @_;
44 9 50   9   60 croak 'Invalid label' if $label =~ m/\p{IsIDNADot}/o;
  9         22  
  9         130  
  88         285  
45              
46 88 100       565 if($label =~ m/\P{ASCII}/o) {
47 16         54 $label = Net::IDN::UTS46::to_ascii(@_);
48             } else {
49 72 50       154 croak 'label empty' if length($label) < 1;
50 72 50       134 croak 'label too long' if length($label) > 63;
51             }
52 87         401 return $label;
53             }
54              
55             sub to_unicode {
56 91     91 1 211 my($label,%param) = @_;
57 91 50       290 croak 'Invalid label' if $label =~ m/\p{IsIDNADot}/o;
58              
59 91 100       653 if($label =~ m/\P{ASCII}|^(?:(?i)$IDNA_PREFIX)/o) {
60 29         262 $label = Net::IDN::UTS46::to_unicode(@_);
61             }
62 89         661 return $label;
63             }
64              
65             sub _domain {
66 56     56   152 my ($domain,$to_function,$ascii,%param) = @_;
67 56 100       179 $param{'UseSTD3ASCIIRules'} = 1 unless exists $param{'UseSTD3ASCIIRules'};
68              
69 56         84 my $even_odd = 1;
70             return join '',
71 56 100       445 map { $even_odd++ % 2 ? $to_function->($_, %param) : $ascii ? '.' : $_ }
  274 100       1258  
72             split /(\p{IsIDNADot})/o, $domain;
73             }
74              
75             sub _email {
76 26     26   62 my ($email,$to_function,$ascii,%param) = @_;
77 26 100 100     147 return $email if !defined($email) || $email eq '';
78              
79 18 50       181 $email =~ m/^(
80             (?(?!\p{IsIDNAAtsign}|").|(?!))+
81             |
82             "(?:(?:[^"]|\\.)*[^\\])?"
83             )
84             (?:
85             (\p{IsIDNAAtsign})
86             (?:([^\[\]]*)|(\[.*\]))?
87             )?$/xo || croak "Invalid email address";
88 18         251 my($local_part,$at,$domain,$domain_literal) = ($1,$2,$3);
89              
90 18 50       54 $local_part =~ m/\P{ASCII}/ && croak "Non-ASCII characters in local-part";
91 18 50 0     37 $domain_literal =~ m/\P{ASCII}/ && croak "Non-ASCII characters in domain-literal" if $domain_literal;
92              
93 18 100       106 $domain = $to_function->($domain,%param) if $domain;
94 18 100       52 $at = '@' if $ascii;
95              
96 18 100 66     148 return ($domain || $domain_literal)
      33        
97             ? ($local_part.$at.($domain || $domain_literal))
98             : ($local_part);
99             }
100              
101 27     27 1 3463 sub domain_to_ascii { _domain(shift, \&to_ascii, 1, @_) }
102 29     29 1 3314 sub domain_to_unicode { _domain(shift, \&to_unicode, 0, @_) }
103              
104 13     13 1 48 sub email_to_ascii { _email(shift, \&domain_to_ascii, 1, @_) }
105 13     13 1 48 sub email_to_unicode { _email(shift, \&domain_to_unicode, 0, @_) }
106              
107             1;
108              
109             __END__