1
2
3
4
5 package cookiejar
6
7
8
9 import (
10 "fmt"
11 "net/http/internal/ascii"
12 "strings"
13 "unicode/utf8"
14 )
15
16
17
18
19
20 const (
21 base int32 = 36
22 damp int32 = 700
23 initialBias int32 = 72
24 initialN int32 = 128
25 skew int32 = 38
26 tmax int32 = 26
27 tmin int32 = 1
28 )
29
30
31
32
33
34
35 func encode(prefix, s string) (string, error) {
36 output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
37 copy(output, prefix)
38 delta, n, bias := int32(0), initialN, initialBias
39 b, remaining := int32(0), int32(0)
40 for _, r := range s {
41 if r < utf8.RuneSelf {
42 b++
43 output = append(output, byte(r))
44 } else {
45 remaining++
46 }
47 }
48 h := b
49 if b > 0 {
50 output = append(output, '-')
51 }
52 for remaining != 0 {
53 m := int32(0x7fffffff)
54 for _, r := range s {
55 if m > r && r >= n {
56 m = r
57 }
58 }
59 delta += (m - n) * (h + 1)
60 if delta < 0 {
61 return "", fmt.Errorf("cookiejar: invalid label %q", s)
62 }
63 n = m
64 for _, r := range s {
65 if r < n {
66 delta++
67 if delta < 0 {
68 return "", fmt.Errorf("cookiejar: invalid label %q", s)
69 }
70 continue
71 }
72 if r > n {
73 continue
74 }
75 q := delta
76 for k := base; ; k += base {
77 t := k - bias
78 if t < tmin {
79 t = tmin
80 } else if t > tmax {
81 t = tmax
82 }
83 if q < t {
84 break
85 }
86 output = append(output, encodeDigit(t+(q-t)%(base-t)))
87 q = (q - t) / (base - t)
88 }
89 output = append(output, encodeDigit(q))
90 bias = adapt(delta, h+1, h == b)
91 delta = 0
92 h++
93 remaining--
94 }
95 delta++
96 n++
97 }
98 return string(output), nil
99 }
100
101 func encodeDigit(digit int32) byte {
102 switch {
103 case 0 <= digit && digit < 26:
104 return byte(digit + 'a')
105 case 26 <= digit && digit < 36:
106 return byte(digit + ('0' - 26))
107 }
108 panic("cookiejar: internal error in punycode encoding")
109 }
110
111
112 func adapt(delta, numPoints int32, firstTime bool) int32 {
113 if firstTime {
114 delta /= damp
115 } else {
116 delta /= 2
117 }
118 delta += delta / numPoints
119 k := int32(0)
120 for delta > ((base-tmin)*tmax)/2 {
121 delta /= base - tmin
122 k += base
123 }
124 return k + (base-tmin+1)*delta/(delta+skew)
125 }
126
127
128
129
130
131 const acePrefix = "xn--"
132
133
134
135
136 func toASCII(s string) (string, error) {
137 if ascii.Is(s) {
138 return s, nil
139 }
140 labels := strings.Split(s, ".")
141 for i, label := range labels {
142 if !ascii.Is(label) {
143 a, err := encode(acePrefix, label)
144 if err != nil {
145 return "", err
146 }
147 labels[i] = a
148 }
149 }
150 return strings.Join(labels, "."), nil
151 }
152
View as plain text