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