| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Net::IDN::PP 0.02; |
|
2
|
|
|
|
|
|
|
# ABSTRACT: A pure-Perl implementation of the Punycode algorithm for encoding internationalized domain names (IDNs) |
|
3
|
1
|
|
|
1
|
|
309409
|
use common::sense; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
sub encode { |
|
7
|
9
|
|
|
9
|
0
|
8447
|
my $name = pop; |
|
8
|
9
|
|
|
|
|
58
|
return join('.', map { encode_label($_) } split(/\./, $name)); |
|
|
11
|
|
|
|
|
25
|
|
|
9
|
|
|
|
|
|
|
} |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
sub decode { |
|
12
|
9
|
|
|
9
|
0
|
8661
|
my $name = pop; |
|
13
|
9
|
|
|
|
|
40
|
return join('.', map { decode_label($_) } split(/\./, $name)); |
|
|
11
|
|
|
|
|
28
|
|
|
14
|
|
|
|
|
|
|
} |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub encode_label { |
|
17
|
11
|
|
|
11
|
0
|
51
|
my $label = lc(pop); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# if ASCII-only: return as-is |
|
20
|
11
|
100
|
|
|
|
83
|
return $label if ($label =~ /^[\x00-\x7F]+$/); |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# extract code points |
|
23
|
8
|
|
|
|
|
38
|
my @cps = unpack("U*", $label); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# Initialize @output with only the ASCII code points |
|
26
|
8
|
|
|
|
|
16
|
my @output = map { chr($_) } grep { $_ < 0x80 } @cps; |
|
|
23
|
|
|
|
|
63
|
|
|
|
34
|
|
|
|
|
90
|
|
|
27
|
|
|
|
|
|
|
|
|
28
|
8
|
|
|
|
|
15
|
my $basic_length = scalar(@output); |
|
29
|
8
|
|
|
|
|
19
|
my $output_str = join('', @output); |
|
30
|
8
|
100
|
|
|
|
27
|
$output_str .= '-' if ($basic_length > 0); |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# Punycode parameters |
|
33
|
8
|
|
|
|
|
13
|
my $n = 128; |
|
34
|
8
|
|
|
|
|
12
|
my $delta = 0; |
|
35
|
8
|
|
|
|
|
11
|
my $bias = 72; |
|
36
|
8
|
|
|
|
|
16
|
my $h = $basic_length; |
|
37
|
8
|
|
|
|
|
15
|
my $len = scalar(@cps); |
|
38
|
|
|
|
|
|
|
|
|
39
|
8
|
|
|
|
|
20
|
while ($h < $len) { |
|
40
|
|
|
|
|
|
|
# Find the minimum code point >= n |
|
41
|
11
|
|
|
|
|
16
|
my $m = 0x10FFFF; |
|
42
|
|
|
|
|
|
|
|
|
43
|
11
|
|
|
|
|
23
|
for my $cp (@cps) { |
|
44
|
55
|
100
|
100
|
|
|
154
|
$m = $cp if $cp >= $n && $cp < $m; |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
|
|
47
|
11
|
|
|
|
|
23
|
my $inc = ($m - $n) * ($h + 1); |
|
48
|
11
|
|
|
|
|
15
|
$delta += $inc; |
|
49
|
11
|
|
|
|
|
18
|
$n = $m; |
|
50
|
|
|
|
|
|
|
|
|
51
|
11
|
|
|
|
|
19
|
for my $cp (@cps) { |
|
52
|
55
|
100
|
|
|
|
112
|
if ($cp < $n) { |
|
|
|
100
|
|
|
|
|
|
|
53
|
38
|
|
|
|
|
85
|
$delta++; |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
} elsif ($cp == $n) { |
|
56
|
11
|
|
|
|
|
14
|
my $q = $delta; |
|
57
|
|
|
|
|
|
|
|
|
58
|
11
|
|
|
|
|
21
|
for (my $k = 36; ; $k += 36) { |
|
59
|
30
|
|
|
|
|
34
|
my $t; |
|
60
|
|
|
|
|
|
|
|
|
61
|
30
|
100
|
|
|
|
68
|
if ($k <= $bias) { |
|
|
|
100
|
|
|
|
|
|
|
62
|
16
|
|
|
|
|
23
|
$t = 1; |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
} elsif ($k >= $bias + 26) { |
|
65
|
13
|
|
|
|
|
22
|
$t = 26; |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
} else { |
|
68
|
1
|
|
|
|
|
4
|
$t = $k - $bias; |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
|
|
72
|
30
|
100
|
|
|
|
91
|
last if ($q < $t); |
|
73
|
|
|
|
|
|
|
|
|
74
|
19
|
|
|
|
|
36
|
my $code = $t + (($q - $t) % (36 - $t)); |
|
75
|
19
|
|
|
|
|
40
|
$output_str .= encode_digit($code); |
|
76
|
19
|
|
|
|
|
53
|
$q = int(($q - $t) / (36 - $t)); |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
|
|
79
|
11
|
|
|
|
|
23
|
$output_str .= encode_digit($q); |
|
80
|
11
|
|
|
|
|
27
|
$bias = adapt($delta, $h + 1, $h == $basic_length); |
|
81
|
11
|
|
|
|
|
19
|
$delta = 0; |
|
82
|
11
|
|
|
|
|
20
|
$h++; |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
11
|
|
|
|
|
15
|
$delta++; |
|
87
|
11
|
|
|
|
|
48
|
$n++; |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
|
|
90
|
8
|
|
|
|
|
66
|
return q{xn--}.$output_str; |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub encode_digit { |
|
94
|
30
|
|
|
30
|
0
|
43
|
my $d = shift; |
|
95
|
30
|
|
|
|
|
79
|
return chr($d + 22 + 75 * ($d < 26)); # 0..25 = a..z, 26..35 = 0..9 |
|
96
|
|
|
|
|
|
|
} |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub decode_digit { |
|
99
|
33
|
|
|
33
|
0
|
59
|
my $ch = lc(shift); |
|
100
|
33
|
|
|
|
|
48
|
my $cp = ord($ch); |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# 'a'..'z' => 0..25 |
|
103
|
33
|
100
|
66
|
|
|
127
|
return $cp - 97 if ($cp >= 97 && $cp <= 122); |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# '0'..'9' => 26..35 |
|
106
|
|
|
|
|
|
|
|
|
107
|
4
|
50
|
33
|
|
|
24
|
return $cp - 22 if ($cp >= 48 && $cp <= 57); |
|
108
|
|
|
|
|
|
|
|
|
109
|
0
|
|
|
|
|
0
|
return 36; # invalid |
|
110
|
|
|
|
|
|
|
} |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub adapt { |
|
113
|
23
|
|
|
23
|
0
|
56
|
my ($delta, $numpoints, $first_time) = @_; |
|
114
|
23
|
100
|
|
|
|
66
|
$delta = int($first_time ? $delta / 700 : $delta / 2); |
|
115
|
23
|
|
|
|
|
39
|
$delta += int($delta / $numpoints); |
|
116
|
|
|
|
|
|
|
|
|
117
|
23
|
|
|
|
|
41
|
my $k = 0; |
|
118
|
|
|
|
|
|
|
|
|
119
|
23
|
|
|
|
|
55
|
while ($delta > 455) { |
|
120
|
0
|
|
|
|
|
0
|
$delta = int($delta / 35); |
|
121
|
0
|
|
|
|
|
0
|
$k += 36; |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
23
|
|
|
|
|
65
|
return $k + int((36 * $delta) / ($delta + 38)); |
|
125
|
|
|
|
|
|
|
} |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
sub decode_label { |
|
128
|
11
|
|
|
11
|
0
|
23
|
my $label = shift; |
|
129
|
|
|
|
|
|
|
|
|
130
|
11
|
100
|
|
|
|
74
|
return $label unless ($label =~ /^xn--/i); |
|
131
|
|
|
|
|
|
|
|
|
132
|
9
|
|
|
|
|
27
|
my $input = lc(substr($label, 4)); |
|
133
|
|
|
|
|
|
|
|
|
134
|
9
|
|
|
|
|
14
|
my @output; |
|
135
|
9
|
|
|
|
|
23
|
my $dash_pos = rindex($input, '-'); |
|
136
|
9
|
100
|
|
|
|
25
|
if ($dash_pos != -1) { |
|
137
|
8
|
|
|
|
|
14
|
my $basic = substr($input, 0, $dash_pos); |
|
138
|
8
|
|
|
|
|
24
|
@output = map { ord($_) } split(//, $basic); |
|
|
28
|
|
|
|
|
58
|
|
|
139
|
8
|
|
|
|
|
24
|
$input = substr($input, $dash_pos + 1); |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
|
|
142
|
9
|
|
|
|
|
12
|
my $n = 128; |
|
143
|
9
|
|
|
|
|
16
|
my $i = 0; |
|
144
|
9
|
|
|
|
|
11
|
my $bias = 72; |
|
145
|
|
|
|
|
|
|
|
|
146
|
9
|
|
|
|
|
32
|
my $in_idx = 0; |
|
147
|
9
|
|
|
|
|
13
|
my $in_len = length($input); |
|
148
|
|
|
|
|
|
|
|
|
149
|
9
|
|
|
|
|
26
|
while ($in_idx < $in_len) { |
|
150
|
12
|
|
|
|
|
20
|
my $oldi = $i; |
|
151
|
12
|
|
|
|
|
16
|
my $w = 1; |
|
152
|
|
|
|
|
|
|
|
|
153
|
12
|
|
|
|
|
23
|
for (my $k = 36; ; $k += 36) { |
|
154
|
33
|
50
|
|
|
|
69
|
last if ($in_idx >= $in_len); |
|
155
|
|
|
|
|
|
|
|
|
156
|
33
|
|
|
|
|
63
|
my $c = substr($input, $in_idx++, 1); |
|
157
|
33
|
|
|
|
|
63
|
my $d = decode_digit($c); |
|
158
|
|
|
|
|
|
|
|
|
159
|
33
|
|
|
|
|
62
|
$i += $d * $w; |
|
160
|
|
|
|
|
|
|
|
|
161
|
33
|
|
|
|
|
78
|
my $t; |
|
162
|
33
|
100
|
|
|
|
73
|
if ($k <= $bias) { |
|
|
|
100
|
|
|
|
|
|
|
163
|
18
|
|
|
|
|
32
|
$t = 1; |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
} elsif ($k >= $bias + 26) { |
|
166
|
14
|
|
|
|
|
20
|
$t = 26; |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
} else { |
|
169
|
1
|
|
|
|
|
4
|
$t = $k - $bias; |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
|
|
173
|
33
|
100
|
|
|
|
69
|
last if ($d < $t); |
|
174
|
21
|
|
|
|
|
41
|
$w *= (36 - $t); |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
|
|
177
|
12
|
|
|
|
|
25
|
my $out_len_plus_1 = scalar(@output) + 1; |
|
178
|
|
|
|
|
|
|
|
|
179
|
12
|
|
|
|
|
28
|
$bias = adapt($i - $oldi, $out_len_plus_1, $oldi == 0); |
|
180
|
|
|
|
|
|
|
|
|
181
|
12
|
|
|
|
|
24
|
my $q = int($i / $out_len_plus_1); |
|
182
|
|
|
|
|
|
|
|
|
183
|
12
|
|
|
|
|
18
|
$n += $q; |
|
184
|
|
|
|
|
|
|
|
|
185
|
12
|
|
|
|
|
20
|
$i = $i % $out_len_plus_1; |
|
186
|
|
|
|
|
|
|
|
|
187
|
12
|
|
|
|
|
25
|
splice(@output, $i, 0, $n); |
|
188
|
|
|
|
|
|
|
|
|
189
|
12
|
|
|
|
|
49
|
$i++; |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
|
|
192
|
9
|
|
|
|
|
18
|
return join('', map { chr($_) } @output); |
|
|
40
|
|
|
|
|
177
|
|
|
193
|
|
|
|
|
|
|
} |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
1; |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
__END__ |