File Coverage

blib/lib/URI/_idna.pm
Criterion Covered Total %
statement 48 50 96.0
branch 14 20 70.0
condition 3 3 100.0
subroutine 12 12 100.0
pod 0 6 0.0
total 77 91 84.6


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   72744 use strict;
  3         14  
  3         93  
7 3     3   31 use warnings;
  3         6  
  3         104  
8              
9 3     3   1371 use URI::_punycode qw(decode_punycode encode_punycode);
  3         7  
  3         190  
10 3     3   21 use Carp qw(croak);
  3         4  
  3         348  
11              
12             our $VERSION = '5.21';
13              
14             BEGIN {
15             *URI::_idna::_ENV_::JOIN_LEAKS_UTF8_FLAGS = "$]" < 5.008_003
16             ? sub () { 1 }
17             : sub () { 0 }
18 3 50   3   1766 ;
19             }
20              
21             my $ASCII = qr/^[\x00-\x7F]*\z/;
22              
23             sub encode {
24 9     9 0 113 my $idomain = shift;
25 9         40 my @labels = split(/\./, $idomain, -1);
26 9         13 my @last_empty;
27 9 100 100     46 push(@last_empty, pop @labels) if @labels > 1 && $labels[-1] eq "";
28 9         21 for (@labels) {
29 19         32 $_ = ToASCII($_);
30             }
31              
32 8         12 return eval 'join(".", @labels, @last_empty)' if URI::_idna::_ENV_::JOIN_LEAKS_UTF8_FLAGS;
33 8         54 return join(".", @labels, @last_empty);
34             }
35              
36             sub decode {
37 12     12 0 19 my $domain = shift;
38 12         48 return join(".", map ToUnicode($_), split(/\./, $domain, -1))
39             }
40              
41             sub nameprep { # XXX real implementation missing
42 17     17 0 26 my $label = shift;
43 17     1   86 $label = lc($label);
  1         6  
  1         2  
  1         10  
44 17         26657 return $label;
45             }
46              
47             sub check_size {
48 29     29 0 57 my $label = shift;
49 29 50       58 croak "Label empty" if $label eq "";
50 29 100       392 croak "Label too long" if length($label) > 63;
51 28         65 return $label;
52             }
53              
54             sub ToASCII {
55 29     29 0 46 my $label = shift;
56 29 100       186 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       42 if ($label =~ /^xn--/) {
66 0         0 croak "Label starts with ACE prefix";
67             }
68              
69             # Step 6: Encode with PUNYCODE
70 17         39 $label = encode_punycode($label);
71              
72             # Step 7: Prepend ACE prefix
73 17         36 $label = "xn--$label";
74              
75             # Step 8: Check size
76 17         36 return check_size($label);
77             }
78              
79             sub ToUnicode {
80 29     29 0 44 my $label = shift;
81 29 50       151 $label = nameprep($label) unless $label =~ $ASCII;
82 29 100       120 return $label unless $label =~ /^xn--/;
83 10         38 my $result = decode_punycode(substr($label, 4));
84 10         31 my $label2 = ToASCII($result);
85 10 50       26 if (lc($label) ne $label2) {
86 0         0 croak "IDNA does not round-trip: '\L$label\E' vs '$label2'";
87             }
88 10         27 return $result;
89             }
90              
91             1;