1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.codec.binary;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class Base32 extends BaseNCodec {
45
46
47
48
49
50
51 private static final int BITS_PER_ENCODED_BYTE = 5;
52 private static final int BYTES_PER_ENCODED_BLOCK = 8;
53 private static final int BYTES_PER_UNENCODED_BLOCK = 5;
54
55
56
57
58
59
60 private static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
61
62
63
64
65
66
67 private static final byte[] DECODE_TABLE = {
68
69 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
70 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 63,
72 -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1,
73 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
74 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
75 };
76
77
78
79
80
81 private static final byte[] ENCODE_TABLE = {
82 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
83 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
84 '2', '3', '4', '5', '6', '7',
85 };
86
87
88
89
90
91
92 private static final byte[] HEX_DECODE_TABLE = {
93
94 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
95 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
96 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 63,
97 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
98 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
99 25, 26, 27, 28, 29, 30, 31, 32,
100 };
101
102
103
104
105
106 private static final byte[] HEX_ENCODE_TABLE = {
107 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
108 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
109 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
110 };
111
112
113 private static final int MASK_5BITS = 0x1f;
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 private final int decodeSize;
129
130
131
132
133 private final byte[] decodeTable;
134
135
136
137
138
139 private final int encodeSize;
140
141
142
143
144 private final byte[] encodeTable;
145
146
147
148
149 private final byte[] lineSeparator;
150
151
152
153
154
155
156
157
158 public Base32() {
159 this(false);
160 }
161
162
163
164
165
166
167
168
169 public Base32(boolean useHex) {
170 this(0, null, useHex);
171 }
172
173
174
175
176
177
178
179
180
181
182
183
184 public Base32(int lineLength) {
185 this(lineLength, CHUNK_SEPARATOR);
186 }
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206 public Base32(int lineLength, byte[] lineSeparator) {
207 this(lineLength, lineSeparator, false);
208 }
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231 public Base32(int lineLength, byte[] lineSeparator, boolean useHex) {
232 super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK,
233 lineLength,
234 lineSeparator == null ? 0 : lineSeparator.length);
235 if (useHex){
236 this.encodeTable = HEX_ENCODE_TABLE;
237 this.decodeTable = HEX_DECODE_TABLE;
238 } else {
239 this.encodeTable = ENCODE_TABLE;
240 this.decodeTable = DECODE_TABLE;
241 }
242 if (lineLength > 0) {
243 if (lineSeparator == null) {
244 throw new IllegalArgumentException("lineLength "+lineLength+" > 0, but lineSeparator is null");
245 }
246
247 if (containsAlphabetOrPad(lineSeparator)) {
248 String sep = StringUtils.newStringUtf8(lineSeparator);
249 throw new IllegalArgumentException("lineSeparator must not contain Base32 characters: [" + sep + "]");
250 }
251 this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;
252 this.lineSeparator = new byte[lineSeparator.length];
253 System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
254 } else {
255 this.encodeSize = BYTES_PER_ENCODED_BLOCK;
256 this.lineSeparator = null;
257 }
258 this.decodeSize = this.encodeSize - 1;
259 }
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283 @Override
284 void decode(byte[] in, int inPos, int inAvail, Context context) {
285 if (context.eof) {
286 return;
287 }
288 if (inAvail < 0) {
289 context.eof = true;
290 }
291 for (int i = 0; i < inAvail; i++) {
292 final byte b = in[inPos++];
293 if (b == PAD) {
294
295 context.eof = true;
296 break;
297 } else {
298 final byte[] buffer = ensureBufferSize(decodeSize, context);
299 if (b >= 0 && b < this.decodeTable.length) {
300 final int result = this.decodeTable[b];
301 if (result >= 0) {
302 context.modulus = (context.modulus+1) % BYTES_PER_ENCODED_BLOCK;
303
304 context.lbitWorkArea = (context.lbitWorkArea << BITS_PER_ENCODED_BYTE) + result;
305 if (context.modulus == 0) {
306 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 32) & MASK_8BITS);
307 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 24) & MASK_8BITS);
308 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS);
309 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS);
310 buffer[context.pos++] = (byte) (context.lbitWorkArea & MASK_8BITS);
311 }
312 }
313 }
314 }
315 }
316
317
318
319
320 if (context.eof && context.modulus >= 2) {
321 final byte[] buffer = ensureBufferSize(decodeSize, context);
322
323
324 switch (context.modulus) {
325 case 2 :
326 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 2) & MASK_8BITS);
327 break;
328 case 3 :
329 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 7) & MASK_8BITS);
330 break;
331 case 4 :
332 context.lbitWorkArea = context.lbitWorkArea >> 4;
333 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS);
334 buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS);
335 break;
336 case 5 :
337 context.lbitWorkArea = context.lbitWorkArea >> 1;
338 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS);
339 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS);
340 buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS);
341 break;
342 case 6 :
343 context.lbitWorkArea = context.lbitWorkArea >> 6;
344 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS);
345 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS);
346 buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS);
347 break;
348 case 7 :
349 context.lbitWorkArea = context.lbitWorkArea >> 3;
350 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 24) & MASK_8BITS);
351 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS);
352 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS);
353 buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS);
354 break;
355 default:
356
357 throw new IllegalStateException("Impossible modulus "+context.modulus);
358 }
359 }
360 }
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377 @Override
378 void encode(byte[] in, int inPos, int inAvail, Context context) {
379 if (context.eof) {
380 return;
381 }
382
383
384 if (inAvail < 0) {
385 context.eof = true;
386 if (0 == context.modulus && lineLength == 0) {
387 return;
388 }
389 final byte[] buffer = ensureBufferSize(encodeSize, context);
390 final int savedPos = context.pos;
391 switch (context.modulus) {
392 case 0 :
393 break;
394 case 1 :
395 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 3) & MASK_5BITS];
396 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 2) & MASK_5BITS];
397 buffer[context.pos++] = PAD;
398 buffer[context.pos++] = PAD;
399 buffer[context.pos++] = PAD;
400 buffer[context.pos++] = PAD;
401 buffer[context.pos++] = PAD;
402 buffer[context.pos++] = PAD;
403 break;
404 case 2 :
405 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 11) & MASK_5BITS];
406 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 6) & MASK_5BITS];
407 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 1) & MASK_5BITS];
408 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 4) & MASK_5BITS];
409 buffer[context.pos++] = PAD;
410 buffer[context.pos++] = PAD;
411 buffer[context.pos++] = PAD;
412 buffer[context.pos++] = PAD;
413 break;
414 case 3 :
415 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 19) & MASK_5BITS];
416 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 14) & MASK_5BITS];
417 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 9) & MASK_5BITS];
418 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 4) & MASK_5BITS];
419 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 1) & MASK_5BITS];
420 buffer[context.pos++] = PAD;
421 buffer[context.pos++] = PAD;
422 buffer[context.pos++] = PAD;
423 break;
424 case 4 :
425 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 27) & MASK_5BITS];
426 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 22) & MASK_5BITS];
427 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 17) & MASK_5BITS];
428 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 12) & MASK_5BITS];
429 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 7) & MASK_5BITS];
430 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 2) & MASK_5BITS];
431 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 3) & MASK_5BITS];
432 buffer[context.pos++] = PAD;
433 break;
434 default:
435 throw new IllegalStateException("Impossible modulus "+context.modulus);
436 }
437 context.currentLinePos += context.pos - savedPos;
438
439 if (lineLength > 0 && context.currentLinePos > 0){
440 System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
441 context.pos += lineSeparator.length;
442 }
443 } else {
444 for (int i = 0; i < inAvail; i++) {
445 final byte[] buffer = ensureBufferSize(encodeSize, context);
446 context.modulus = (context.modulus+1) % BYTES_PER_UNENCODED_BLOCK;
447 int b = in[inPos++];
448 if (b < 0) {
449 b += 256;
450 }
451 context.lbitWorkArea = (context.lbitWorkArea << 8) + b;
452 if (0 == context.modulus) {
453 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 35) & MASK_5BITS];
454 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 30) & MASK_5BITS];
455 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 25) & MASK_5BITS];
456 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 20) & MASK_5BITS];
457 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 15) & MASK_5BITS];
458 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 10) & MASK_5BITS];
459 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 5) & MASK_5BITS];
460 buffer[context.pos++] = encodeTable[(int)context.lbitWorkArea & MASK_5BITS];
461 context.currentLinePos += BYTES_PER_ENCODED_BLOCK;
462 if (lineLength > 0 && lineLength <= context.currentLinePos) {
463 System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
464 context.pos += lineSeparator.length;
465 context.currentLinePos = 0;
466 }
467 }
468 }
469 }
470 }
471
472
473
474
475
476
477
478
479 @Override
480 public boolean isInAlphabet(byte octet) {
481 return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
482 }
483 }