1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.codec.net;
19
20 import java.io.ByteArrayOutputStream;
21 import java.io.UnsupportedEncodingException;
22 import java.util.BitSet;
23
24 import org.apache.commons.codec.BinaryDecoder;
25 import org.apache.commons.codec.BinaryEncoder;
26 import org.apache.commons.codec.CharEncoding;
27 import org.apache.commons.codec.DecoderException;
28 import org.apache.commons.codec.EncoderException;
29 import org.apache.commons.codec.StringDecoder;
30 import org.apache.commons.codec.StringEncoder;
31 import org.apache.commons.codec.binary.StringUtils;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public class URLCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, StringDecoder {
49
50
51
52
53 static final int RADIX = 16;
54
55
56
57
58
59
60 @Deprecated
61 protected String charset;
62
63
64
65
66 protected static final byte ESCAPE_CHAR = '%';
67
68
69
70 protected static final BitSet WWW_FORM_URL = new BitSet(256);
71
72
73 static {
74
75 for (int i = 'a'; i <= 'z'; i++) {
76 WWW_FORM_URL.set(i);
77 }
78 for (int i = 'A'; i <= 'Z'; i++) {
79 WWW_FORM_URL.set(i);
80 }
81
82 for (int i = '0'; i <= '9'; i++) {
83 WWW_FORM_URL.set(i);
84 }
85
86 WWW_FORM_URL.set('-');
87 WWW_FORM_URL.set('_');
88 WWW_FORM_URL.set('.');
89 WWW_FORM_URL.set('*');
90
91 WWW_FORM_URL.set(' ');
92 }
93
94
95
96
97
98 public URLCodec() {
99 this(CharEncoding.UTF_8);
100 }
101
102
103
104
105
106
107 public URLCodec(String charset) {
108 super();
109 this.charset = charset;
110 }
111
112
113
114
115
116
117
118
119
120
121 public static final byte[] encodeUrl(BitSet urlsafe, byte[] bytes) {
122 if (bytes == null) {
123 return null;
124 }
125 if (urlsafe == null) {
126 urlsafe = WWW_FORM_URL;
127 }
128
129 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
130 for (byte c : bytes) {
131 int b = c;
132 if (b < 0) {
133 b = 256 + b;
134 }
135 if (urlsafe.get(b)) {
136 if (b == ' ') {
137 b = '+';
138 }
139 buffer.write(b);
140 } else {
141 buffer.write(ESCAPE_CHAR);
142 char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, RADIX));
143 char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, RADIX));
144 buffer.write(hex1);
145 buffer.write(hex2);
146 }
147 }
148 return buffer.toByteArray();
149 }
150
151
152
153
154
155
156
157
158
159
160
161 public static final byte[] decodeUrl(byte[] bytes) throws DecoderException {
162 if (bytes == null) {
163 return null;
164 }
165 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
166 for (int i = 0; i < bytes.length; i++) {
167 int b = bytes[i];
168 if (b == '+') {
169 buffer.write(' ');
170 } else if (b == ESCAPE_CHAR) {
171 try {
172 int u = Utils.digit16(bytes[++i]);
173 int l = Utils.digit16(bytes[++i]);
174 buffer.write((char) ((u << 4) + l));
175 } catch (ArrayIndexOutOfBoundsException e) {
176 throw new DecoderException("Invalid URL encoding: ", e);
177 }
178 } else {
179 buffer.write(b);
180 }
181 }
182 return buffer.toByteArray();
183 }
184
185
186
187
188
189
190
191
192 @Override
193 public byte[] encode(byte[] bytes) {
194 return encodeUrl(WWW_FORM_URL, bytes);
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208 @Override
209 public byte[] decode(byte[] bytes) throws DecoderException {
210 return decodeUrl(bytes);
211 }
212
213
214
215
216
217
218
219
220
221
222
223
224 public String encode(String str, String charset) throws UnsupportedEncodingException {
225 if (str == null) {
226 return null;
227 }
228 return StringUtils.newStringUsAscii(encode(str.getBytes(charset)));
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242 @Override
243 public String encode(String str) throws EncoderException {
244 if (str == null) {
245 return null;
246 }
247 try {
248 return encode(str, getDefaultCharset());
249 } catch (UnsupportedEncodingException e) {
250 throw new EncoderException(e.getMessage(), e);
251 }
252 }
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 public String decode(String str, String charset) throws DecoderException, UnsupportedEncodingException {
270 if (str == null) {
271 return null;
272 }
273 return new String(decode(StringUtils.getBytesUsAscii(str)), charset);
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287 @Override
288 public String decode(String str) throws DecoderException {
289 if (str == null) {
290 return null;
291 }
292 try {
293 return decode(str, getDefaultCharset());
294 } catch (UnsupportedEncodingException e) {
295 throw new DecoderException(e.getMessage(), e);
296 }
297 }
298
299
300
301
302
303
304
305
306
307
308 @Override
309 public Object encode(Object obj) throws EncoderException {
310 if (obj == null) {
311 return null;
312 } else if (obj instanceof byte[]) {
313 return encode((byte[])obj);
314 } else if (obj instanceof String) {
315 return encode((String)obj);
316 } else {
317 throw new EncoderException("Objects of type " + obj.getClass().getName() + " cannot be URL encoded");
318
319 }
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333 @Override
334 public Object decode(Object obj) throws DecoderException {
335 if (obj == null) {
336 return null;
337 } else if (obj instanceof byte[]) {
338 return decode((byte[]) obj);
339 } else if (obj instanceof String) {
340 return decode((String) obj);
341 } else {
342 throw new DecoderException("Objects of type " + obj.getClass().getName() + " cannot be URL decoded");
343
344 }
345 }
346
347
348
349
350
351
352 public String getDefaultCharset() {
353 return this.charset;
354 }
355
356
357
358
359
360
361
362
363 @Deprecated
364 public String getEncoding() {
365 return this.charset;
366 }
367
368 }