File Coverage

blib/lib/URI/_idna.pm
Criterion Covered Total %
statement 45 47 95.7
branch 14 20 70.0
condition 3 3 100.0
subroutine 11 11 100.0
pod 0 6 0.0
total 73 87 83.9


line stmt bran cond sub pod time code
1             package URI::_idna;
2              
3             # This module implements the RFCs 3490 (IDNA) and 3491 (Nameprep)
4             # based on Python-2.6.4/Lib/encodings/idna.py
5              
6 3     3   98998 use strict;
  3         6  
  3         110  
7 3     3   14 use warnings;
  3         6  
  3         208  
8              
9 3     3   1543 use URI::_punycode qw(decode_punycode encode_punycode);
  3         16  
  3         330  
10 3     3   27 use Carp qw(croak);
  3         6  
  3         395  
11              
12             our $VERSION = '5.34';
13              
14             BEGIN {
15             *URI::_idna::_ENV_::JOIN_LEAKS_UTF8_FLAGS = "$]" < 5.008_003
16             ? sub () { 1 }
17             : sub () { 0 }
18 3 50   3   1824 ;
19             }
20              
21             my $ASCII = qr/^[\x00-\x7F]*\z/;
22              
23             sub encode {
24 9     9 0 548421 my $idomain = shift;
25 9         44 my @labels = split(/\./, $idomain, -1);
26 9         17 my @last_empty;
27 9 100 100     55 push(@last_empty, pop @labels) if @labels > 1 && $labels[-1] eq "";
28 9         22 for (@labels) {
29 19         39 $_ = ToASCII($_);
30             }
31              
32 8         11 return eval 'join(".", @labels, @last_empty)' if URI::_idna::_ENV_::JOIN_LEAKS_UTF8_FLAGS;
33 8         61 return join(".", @labels, @last_empty);
34             }
35              
36             sub decode {
37 12     12 0 26 my $domain = shift;
38 12         85 return join(".", map ToUnicode($_), split(/\./, $domain, -1))
39             }
40              
41             sub nameprep { # XXX real implementation missing
42 17     17 0 27 my $label = shift;
43 17         129 $label = lc($label);
44 17         36 return $label;
45             }
46              
47             sub check_size {
48 29     29 0 47 my $label = shift;
49 29 50       60 croak "Label empty" if $label eq "";
50 29 100       360 croak "Label too long" if length($label) > 63;
51 28         101 return $label;
52             }
53              
54             sub ToASCII {
55 29     29 0 47 my $label = shift;
56 29 100       206 return check_size($label) if $label =~ $ASCII;
57              
58             # Step 2: nameprep
59 17         37 $label = nameprep($label);
60             # Step 3: UseSTD3ASCIIRules is false
61             # Step 4: try ASCII again
62 17 50       79 return check_size($label) if $label =~ $ASCII;
63              
64             # Step 5: Check ACE prefix
65 17 50       65 if ($label =~ /^xn--/) {
66 0         0 croak "Label starts with ACE prefix";
67             }
68              
69             # Step 6: Encode with PUNYCODE
70 17         51 $label = encode_punycode($label);
71              
72             # Step 7: Prepend ACE prefix
73 17         38 $label = "xn--$label";
74              
75             # Step 8: Check size
76 17         37 return check_size($label);
77             }
78              
79             sub ToUnicode {
80 29     29 0 43 my $label = shift;
81 29 50       190 $label = nameprep($label) unless $label =~ $ASCII;
82 29 100       139 return $label unless $label =~ /^xn--/;
83 10         47 my $result = decode_punycode(substr($label, 4));
84 10         56 my $label2 = ToASCII($result);
85 10 50       45 if (lc($label) ne $label2) {
86 0         0 croak "IDNA does not round-trip: '\L$label\E' vs '$label2'";
87             }
88 10         26 return $result;
89             }
90              
91             1;