1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.jboss.netty.handler.codec.base64;
21
22 import org.jboss.netty.buffer.ChannelBuffer;
23 import org.jboss.netty.buffer.ChannelBufferFactory;
24 import org.jboss.netty.buffer.HeapChannelBufferFactory;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public class Base64 {
42
43
44 private static final int MAX_LINE_LENGTH = 76;
45
46
47 private static final byte EQUALS_SIGN = (byte) '=';
48
49
50 private static final byte NEW_LINE = (byte) '\n';
51
52 private static final byte WHITE_SPACE_ENC = -5;
53
54 private static final byte EQUALS_SIGN_ENC = -1;
55
56 private static final byte[] alphabet(Base64Dialect dialect) {
57 if (dialect == null) {
58 throw new NullPointerException("dialect");
59 }
60 return dialect.alphabet;
61 }
62
63 private static final byte[] decodabet(Base64Dialect dialect) {
64 if (dialect == null) {
65 throw new NullPointerException("dialect");
66 }
67 return dialect.decodabet;
68 }
69
70 private static final boolean breakLines(Base64Dialect dialect) {
71 if (dialect == null) {
72 throw new NullPointerException("dialect");
73 }
74 return dialect.breakLinesByDefault;
75 }
76
77 public static ChannelBuffer encode(ChannelBuffer src) {
78 return encode(src, Base64Dialect.STANDARD);
79 }
80
81 public static ChannelBuffer encode(ChannelBuffer src, Base64Dialect dialect) {
82 return encode(src, breakLines(dialect), dialect);
83 }
84
85 public static ChannelBuffer encode(
86 ChannelBuffer src, ChannelBufferFactory bufferFactory) {
87 return encode(src, Base64Dialect.STANDARD, bufferFactory);
88 }
89
90 public static ChannelBuffer encode(
91 ChannelBuffer src, Base64Dialect dialect, ChannelBufferFactory bufferFactory) {
92 return encode(src, breakLines(dialect), dialect, bufferFactory);
93 }
94
95 public static ChannelBuffer encode(ChannelBuffer src, boolean breakLines) {
96 return encode(src, breakLines, Base64Dialect.STANDARD);
97 }
98
99 public static ChannelBuffer encode(
100 ChannelBuffer src, boolean breakLines, Base64Dialect dialect) {
101 return encode(src, breakLines, dialect, HeapChannelBufferFactory.getInstance());
102 }
103
104 public static ChannelBuffer encode(
105 ChannelBuffer src, boolean breakLines, ChannelBufferFactory bufferFactory) {
106 return encode(src, breakLines, Base64Dialect.STANDARD, bufferFactory);
107 }
108
109 public static ChannelBuffer encode(
110 ChannelBuffer src, boolean breakLines, Base64Dialect dialect, ChannelBufferFactory bufferFactory) {
111
112 if (src == null) {
113 throw new NullPointerException("src");
114 }
115
116 ChannelBuffer dest = encode(
117 src, src.readerIndex(), src.readableBytes(), breakLines, dialect, bufferFactory);
118 src.readerIndex(src.writerIndex());
119 return dest;
120 }
121
122 public static ChannelBuffer encode(ChannelBuffer src, int off, int len) {
123 return encode(src, off, len, Base64Dialect.STANDARD);
124 }
125
126 public static ChannelBuffer encode(ChannelBuffer src, int off, int len, Base64Dialect dialect) {
127 return encode(src, off, len, breakLines(dialect), dialect);
128 }
129
130 public static ChannelBuffer encode(ChannelBuffer src, int off, int len, ChannelBufferFactory bufferFactory) {
131 return encode(src, off, len, Base64Dialect.STANDARD, bufferFactory);
132 }
133
134 public static ChannelBuffer encode(ChannelBuffer src, int off, int len, Base64Dialect dialect, ChannelBufferFactory bufferFactory) {
135 return encode(src, off, len, breakLines(dialect), dialect, bufferFactory);
136 }
137
138 public static ChannelBuffer encode(
139 ChannelBuffer src, int off, int len, boolean breakLines) {
140 return encode(src, off, len, breakLines, Base64Dialect.STANDARD);
141 }
142
143 public static ChannelBuffer encode(
144 ChannelBuffer src, int off, int len,
145 boolean breakLines, Base64Dialect dialect) {
146 return encode(src, off, len, breakLines, dialect, HeapChannelBufferFactory.getInstance());
147 }
148
149 public static ChannelBuffer encode(
150 ChannelBuffer src, int off, int len,
151 boolean breakLines, ChannelBufferFactory bufferFactory) {
152 return encode(src, off, len, breakLines, Base64Dialect.STANDARD, bufferFactory);
153 }
154
155 public static ChannelBuffer encode(
156 ChannelBuffer src, int off, int len,
157 boolean breakLines, Base64Dialect dialect, ChannelBufferFactory bufferFactory) {
158
159 if (src == null) {
160 throw new NullPointerException("src");
161 }
162 if (dialect == null) {
163 throw new NullPointerException("dialect");
164 }
165 if (bufferFactory == null) {
166 throw new NullPointerException("bufferFactory");
167 }
168
169 int len43 = len * 4 / 3;
170 ChannelBuffer dest = bufferFactory.getBuffer(
171 src.order(),
172 len43 +
173 (len % 3 > 0? 4 : 0) +
174 (breakLines? len43 / MAX_LINE_LENGTH : 0));
175 int d = 0;
176 int e = 0;
177 int len2 = len - 2;
178 int lineLength = 0;
179 for (; d < len2; d += 3, e += 4) {
180 encode3to4(src, d + off, 3, dest, e, dialect);
181
182 lineLength += 4;
183 if (breakLines && lineLength == MAX_LINE_LENGTH) {
184 dest.setByte(e + 4, NEW_LINE);
185 e ++;
186 lineLength = 0;
187 }
188 }
189
190 if (d < len) {
191 encode3to4(src, d + off, len - d, dest, e, dialect);
192 e += 4;
193 }
194
195 return dest.slice(0, e);
196 }
197
198 private static void encode3to4(
199 ChannelBuffer src, int srcOffset, int numSigBytes,
200 ChannelBuffer dest, int destOffset, Base64Dialect dialect) {
201
202 byte[] ALPHABET = alphabet(dialect);
203
204
205
206
207
208
209
210
211
212
213
214
215 int inBuff =
216 (numSigBytes > 0? src.getByte(srcOffset ) << 24 >>> 8 : 0) |
217 (numSigBytes > 1? src.getByte(srcOffset + 1) << 24 >>> 16 : 0) |
218 (numSigBytes > 2? src.getByte(srcOffset + 2) << 24 >>> 24 : 0);
219
220 switch (numSigBytes) {
221 case 3:
222 dest.setByte(destOffset , ALPHABET[inBuff >>> 18 ]);
223 dest.setByte(destOffset + 1, ALPHABET[inBuff >>> 12 & 0x3f]);
224 dest.setByte(destOffset + 2, ALPHABET[inBuff >>> 6 & 0x3f]);
225 dest.setByte(destOffset + 3, ALPHABET[inBuff & 0x3f]);
226 break;
227 case 2:
228 dest.setByte(destOffset , ALPHABET[inBuff >>> 18 ]);
229 dest.setByte(destOffset + 1, ALPHABET[inBuff >>> 12 & 0x3f]);
230 dest.setByte(destOffset + 2, ALPHABET[inBuff >>> 6 & 0x3f]);
231 dest.setByte(destOffset + 3, EQUALS_SIGN);
232 break;
233 case 1:
234 dest.setByte(destOffset , ALPHABET[inBuff >>> 18 ]);
235 dest.setByte(destOffset + 1, ALPHABET[inBuff >>> 12 & 0x3f]);
236 dest.setByte(destOffset + 2, EQUALS_SIGN);
237 dest.setByte(destOffset + 3, EQUALS_SIGN);
238 break;
239 }
240 }
241
242 public static ChannelBuffer decode(ChannelBuffer src) {
243 return decode(src, Base64Dialect.STANDARD);
244 }
245
246 public static ChannelBuffer decode(ChannelBuffer src, Base64Dialect dialect) {
247 return decode(src, dialect, HeapChannelBufferFactory.getInstance());
248 }
249
250 public static ChannelBuffer decode(ChannelBuffer src, ChannelBufferFactory bufferFactory) {
251 return decode(src, Base64Dialect.STANDARD, bufferFactory);
252 }
253
254 public static ChannelBuffer decode(ChannelBuffer src, Base64Dialect dialect, ChannelBufferFactory bufferFactory) {
255
256 if (src == null) {
257 throw new NullPointerException("src");
258 }
259
260 ChannelBuffer dest = decode(src, src.readerIndex(), src.readableBytes(), dialect, bufferFactory);
261 src.readerIndex(src.writerIndex());
262 return dest;
263 }
264
265 public static ChannelBuffer decode(
266 ChannelBuffer src, int off, int len) {
267 return decode(src, off, len, Base64Dialect.STANDARD);
268 }
269
270 public static ChannelBuffer decode(
271 ChannelBuffer src, int off, int len, Base64Dialect dialect) {
272 return decode(src, off, len, dialect, HeapChannelBufferFactory.getInstance());
273 }
274
275 public static ChannelBuffer decode(
276 ChannelBuffer src, int off, int len, ChannelBufferFactory bufferFactory) {
277 return decode(src, off, len, Base64Dialect.STANDARD, bufferFactory);
278 }
279
280 public static ChannelBuffer decode(
281 ChannelBuffer src, int off, int len, Base64Dialect dialect,
282 ChannelBufferFactory bufferFactory) {
283
284 if (src == null) {
285 throw new NullPointerException("src");
286 }
287 if (dialect == null) {
288 throw new NullPointerException("dialect");
289 }
290 if (bufferFactory == null) {
291 throw new NullPointerException("bufferFactory");
292 }
293
294 byte[] DECODABET = decodabet(dialect);
295
296 int len34 = len * 3 / 4;
297 ChannelBuffer dest = bufferFactory.getBuffer(src.order(), len34);
298 int outBuffPosn = 0;
299
300 byte[] b4 = new byte[4];
301 int b4Posn = 0;
302 int i = 0;
303 byte sbiCrop = 0;
304 byte sbiDecode = 0;
305 for (i = off; i < off + len; i ++) {
306 sbiCrop = (byte) (src.getByte(i) & 0x7f);
307 sbiDecode = DECODABET[sbiCrop];
308
309 if (sbiDecode >= WHITE_SPACE_ENC) {
310 if (sbiDecode >= EQUALS_SIGN_ENC) {
311 b4[b4Posn ++] = sbiCrop;
312 if (b4Posn > 3) {
313 outBuffPosn += decode4to3(
314 b4, 0, dest, outBuffPosn, dialect);
315 b4Posn = 0;
316
317
318 if (sbiCrop == EQUALS_SIGN) {
319 break;
320 }
321 }
322 }
323 }
324 else {
325 throw new IllegalArgumentException(
326 "bad Base64 input character at " + i + ": " +
327 src.getUnsignedByte(i) + " (decimal)");
328 }
329 }
330
331 return dest.slice(0, outBuffPosn);
332 }
333
334 private static int decode4to3(
335 byte[] src, int srcOffset,
336 ChannelBuffer dest, int destOffset, Base64Dialect dialect) {
337
338 byte[] DECODABET = decodabet(dialect);
339
340
341 if (src[srcOffset + 2] == EQUALS_SIGN) {
342 int outBuff =
343 (DECODABET[src[srcOffset ]] & 0xFF) << 18 |
344 (DECODABET[src[srcOffset + 1]] & 0xFF) << 12;
345
346 dest.setByte(destOffset, (byte) (outBuff >>> 16));
347 return 1;
348 }
349
350
351 else if (src[srcOffset + 3] == EQUALS_SIGN) {
352 int outBuff =
353 (DECODABET[src[srcOffset ]] & 0xFF) << 18 |
354 (DECODABET[src[srcOffset + 1]] & 0xFF) << 12 |
355 (DECODABET[src[srcOffset + 2]] & 0xFF) << 6;
356
357 dest.setByte(destOffset , (byte) (outBuff >>> 16));
358 dest.setByte(destOffset + 1, (byte) (outBuff >>> 8));
359 return 2;
360 }
361
362
363 else {
364 int outBuff;
365 try {
366 outBuff =
367 (DECODABET[src[srcOffset ]] & 0xFF) << 18 |
368 (DECODABET[src[srcOffset + 1]] & 0xFF) << 12 |
369 (DECODABET[src[srcOffset + 2]] & 0xFF) << 6 |
370 DECODABET[src[srcOffset + 3]] & 0xFF;
371 } catch (IndexOutOfBoundsException e) {
372 throw new IllegalArgumentException("not encoded in Base64");
373 }
374
375 dest.setByte(destOffset , (byte) (outBuff >> 16));
376 dest.setByte(destOffset + 1, (byte) (outBuff >> 8));
377 dest.setByte(destOffset + 2, (byte) outBuff);
378 return 3;
379 }
380 }
381
382 private Base64() {
383
384 }
385 }