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