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