1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package davmail.http;
21
22 import org.apache.commons.codec.DecoderException;
23 import org.apache.commons.codec.net.URLCodec;
24 import org.apache.http.Consts;
25
26 import java.io.IOException;
27 import java.util.BitSet;
28
29
30
31
32 public class URIUtil {
33
34
35
36
37
38
39 protected static final BitSet percent = new BitSet(256);
40
41 static {
42 percent.set('%');
43 }
44
45
46
47
48
49
50
51
52
53 protected static final BitSet digit = new BitSet(256);
54
55 static {
56 for (int i = '0'; i <= '9'; i++) {
57 digit.set(i);
58 }
59 }
60
61
62
63
64
65
66
67
68 protected static final BitSet alpha = new BitSet(256);
69
70 static {
71 for (int i = 'a'; i <= 'z'; i++) {
72 alpha.set(i);
73 }
74 for (int i = 'A'; i <= 'Z'; i++) {
75 alpha.set(i);
76 }
77 }
78
79
80
81
82
83
84
85
86 protected static final BitSet alphanum = new BitSet(256);
87
88 static {
89 alphanum.or(alpha);
90 alphanum.or(digit);
91 }
92
93
94
95
96
97
98
99
100
101 protected static final BitSet hex = new BitSet(256);
102
103 static {
104 hex.or(digit);
105 for (int i = 'a'; i <= 'f'; i++) {
106 hex.set(i);
107 }
108 for (int i = 'A'; i <= 'F'; i++) {
109 hex.set(i);
110 }
111 }
112
113
114
115
116
117
118
119
120 protected static final BitSet escaped = new BitSet(256);
121
122 static {
123 escaped.or(percent);
124 escaped.or(hex);
125 }
126
127
128
129
130
131
132
133
134
135 protected static final BitSet mark = new BitSet(256);
136
137 static {
138 mark.set('-');
139 mark.set('_');
140 mark.set('.');
141 mark.set('!');
142 mark.set('~');
143 mark.set('*');
144 mark.set('\'');
145 mark.set('(');
146 mark.set(')');
147 }
148
149
150
151
152
153
154
155
156
157 protected static final BitSet unreserved = new BitSet(256);
158
159 static {
160 unreserved.or(alphanum);
161 unreserved.or(mark);
162 }
163
164
165
166
167
168
169
170
171
172 protected static final BitSet reserved = new BitSet(256);
173
174 static {
175 reserved.set(';');
176 reserved.set('/');
177 reserved.set('?');
178 reserved.set(':');
179 reserved.set('@');
180 reserved.set('&');
181 reserved.set('=');
182 reserved.set('+');
183 reserved.set('$');
184 reserved.set(',');
185 }
186
187
188
189
190
191
192
193
194 protected static final BitSet uric = new BitSet(256);
195
196 static {
197 uric.or(reserved);
198 uric.or(unreserved);
199 uric.or(escaped);
200 }
201
202
203
204
205
206
207
208
209 protected static final BitSet pchar = new BitSet(256);
210
211 static {
212 pchar.or(unreserved);
213 pchar.or(escaped);
214 pchar.set(':');
215 pchar.set('@');
216 pchar.set('&');
217 pchar.set('=');
218 pchar.set('+');
219 pchar.set('$');
220 pchar.set(',');
221 }
222
223
224
225
226
227
228
229
230 protected static final BitSet param = pchar;
231
232
233
234
235
236
237
238
239 protected static final BitSet segment = new BitSet(256);
240
241 static {
242 segment.or(pchar);
243 segment.set(';');
244 segment.or(param);
245 }
246
247
248
249
250
251
252
253
254 protected static final BitSet path_segments = new BitSet(256);
255
256 static {
257 path_segments.set('/');
258 path_segments.or(segment);
259 }
260
261
262
263
264
265
266
267 protected static final BitSet abs_path = new BitSet(256);
268
269 static {
270 abs_path.set('/');
271 abs_path.or(path_segments);
272 }
273
274
275
276
277 public static final BitSet allowed_abs_path = new BitSet(256);
278 static {
279 allowed_abs_path.or(abs_path);
280
281 allowed_abs_path.andNot(percent);
282 allowed_abs_path.clear('+');
283 }
284
285
286
287
288 public static final BitSet allowed_query = new BitSet(256);
289
290 static {
291 allowed_query.or(uric);
292 allowed_query.clear('%');
293 }
294
295
296
297
298 public static final BitSet allowed_within_query = new BitSet(256);
299
300 static {
301 allowed_within_query.or(allowed_query);
302 allowed_within_query.andNot(reserved);
303 }
304
305
306
307
308
309
310
311 public static String decode(String escaped) throws IOException {
312 try {
313 return getString(URLCodec.decodeUrl(getAsciiBytes(escaped)));
314 } catch (DecoderException e) {
315 throw new IOException(e.getMessage());
316 }
317 }
318
319
320
321
322
323
324 public static String encodePath(String unescaped) {
325 return encode(unescaped, allowed_abs_path);
326 }
327
328
329
330
331
332
333
334 public static String encode(String unescaped, BitSet allowed) {
335 return getAsciiString(URLCodec.encodeUrl(allowed, getBytes(unescaped)));
336 }
337
338
339
340
341
342
343 public static String encodeWithinQuery(String unescaped) {
344 return encode(unescaped, allowed_within_query);
345 }
346
347
348
349
350
351
352 public static String encodePathQuery(String unescaped){
353 int at = unescaped.indexOf('?');
354 if (at < 0) {
355 return encode(unescaped, allowed_abs_path);
356 } else {
357 return encode(unescaped.substring(0, at), allowed_abs_path)
358 + '?' + encode(unescaped.substring(at + 1), allowed_query);
359 }
360 }
361
362 public static byte[] getBytes(final String value) {
363 if (value == null) {
364 throw new IllegalArgumentException("Parameter may not be null");
365 }
366
367 return value.getBytes(Consts.UTF_8);
368 }
369
370 public static byte[] getAsciiBytes(final String value) {
371 if (value == null) {
372 throw new IllegalArgumentException("Parameter may not be null");
373 }
374
375 return value.getBytes(Consts.ASCII);
376 }
377
378
379
380
381
382
383 public static String getAsciiString(final byte[] bytes) {
384 if (bytes == null) {
385 throw new IllegalArgumentException("Parameter may not be null");
386 }
387
388 return new String(bytes, Consts.ASCII);
389 }
390
391
392
393
394
395
396 public static String getString(final byte[] bytes) {
397 if (bytes == null) {
398 throw new IllegalArgumentException("Parameter may not be null");
399 }
400
401 return new String(bytes, Consts.UTF_8);
402 }
403 }