1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.client.utils;
28
29 import java.util.StringTokenizer;
30
31 import org.apache.http.annotation.Immutable;
32
33
34
35
36
37
38 @Immutable
39 public class Rfc3492Idn implements Idn {
40 private static final int base = 36;
41 private static final int tmin = 1;
42 private static final int tmax = 26;
43 private static final int skew = 38;
44 private static final int damp = 700;
45 private static final int initial_bias = 72;
46 private static final int initial_n = 128;
47 private static final char delimiter = '-';
48 private static final String ACE_PREFIX = "xn--";
49
50 private int adapt(int delta, final int numpoints, final boolean firsttime) {
51 if (firsttime) {
52 delta = delta / damp;
53 } else {
54 delta = delta / 2;
55 }
56 delta = delta + (delta / numpoints);
57 int k = 0;
58 while (delta > ((base - tmin) * tmax) / 2) {
59 delta = delta / (base - tmin);
60 k = k + base;
61 }
62 return k + (((base - tmin + 1) * delta) / (delta + skew));
63 }
64
65 private int digit(final char c) {
66 if ((c >= 'A') && (c <= 'Z')) {
67 return (c - 'A');
68 }
69 if ((c >= 'a') && (c <= 'z')) {
70 return (c - 'a');
71 }
72 if ((c >= '0') && (c <= '9')) {
73 return (c - '0') + 26;
74 }
75 throw new IllegalArgumentException("illegal digit: "+ c);
76 }
77
78 public String toUnicode(final String punycode) {
79 final StringBuilder unicode = new StringBuilder(punycode.length());
80 final StringTokenizer tok = new StringTokenizer(punycode, ".");
81 while (tok.hasMoreTokens()) {
82 String t = tok.nextToken();
83 if (unicode.length() > 0) {
84 unicode.append('.');
85 }
86 if (t.startsWith(ACE_PREFIX)) {
87 t = decode(t.substring(4));
88 }
89 unicode.append(t);
90 }
91 return unicode.toString();
92 }
93
94 protected String decode(String input) {
95 int n = initial_n;
96 int i = 0;
97 int bias = initial_bias;
98 final StringBuilder output = new StringBuilder(input.length());
99 final int lastdelim = input.lastIndexOf(delimiter);
100 if (lastdelim != -1) {
101 output.append(input.subSequence(0, lastdelim));
102 input = input.substring(lastdelim + 1);
103 }
104
105 while (input.length() > 0) {
106 final int oldi = i;
107 int w = 1;
108 for (int k = base;; k += base) {
109 if (input.length() == 0) {
110 break;
111 }
112 final char c = input.charAt(0);
113 input = input.substring(1);
114 final int digit = digit(c);
115 i = i + digit * w;
116 int t;
117 if (k <= bias + tmin) {
118 t = tmin;
119 } else if (k >= bias + tmax) {
120 t = tmax;
121 } else {
122 t = k - bias;
123 }
124 if (digit < t) {
125 break;
126 }
127 w = w * (base - t);
128 }
129 bias = adapt(i - oldi, output.length() + 1, (oldi == 0));
130 n = n + i / (output.length() + 1);
131 i = i % (output.length() + 1);
132
133 output.insert(i, (char) n);
134 i++;
135 }
136 return output.toString();
137 }
138
139 }