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 };
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, -1,
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(final boolean useHex) {
170 this(0, null, useHex);
171 }
172
173
174
175
176
177
178
179
180
181
182
183
184 public Base32(final 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(final int lineLength, final 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(final int lineLength, final byte[] lineSeparator, final 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 final 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(final byte[] in, int inPos, final int inAvail, final Context context) {
285
286
287 if (context.eof) {
288 return;
289 }
290 if (inAvail < 0) {
291 context.eof = true;
292 }
293 for (int i = 0; i < inAvail; i++) {
294 final byte b = in[inPos++];
295 if (b == PAD) {
296
297 context.eof = true;
298 break;
299 } else {
300 final byte[] buffer = ensureBufferSize(decodeSize, context);
301 if (b >= 0 && b < this.decodeTable.length) {
302 final int result = this.decodeTable[b];
303 if (result >= 0) {
304 context.modulus = (context.modulus+1) % BYTES_PER_ENCODED_BLOCK;
305
306 context.lbitWorkArea = (context.lbitWorkArea << BITS_PER_ENCODED_BYTE) + result;
307 if (context.modulus == 0) {
308 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 32) & MASK_8BITS);
309 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 24) & MASK_8BITS);
310 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS);
311 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS);
312 buffer[context.pos++] = (byte) (context.lbitWorkArea & MASK_8BITS);
313 }
314 }
315 }
316 }
317 }
318
319
320
321
322 if (context.eof && context.modulus >= 2) {
323 final byte[] buffer = ensureBufferSize(decodeSize, context);
324
325
326 switch (context.modulus) {
327 case 2 :
328 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 2) & MASK_8BITS);
329 break;
330 case 3 :
331 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 7) & MASK_8BITS);
332 break;
333 case 4 :
334 context.lbitWorkArea = context.lbitWorkArea >> 4;
335 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS);
336 buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS);
337 break;
338 case 5 :
339 context.lbitWorkArea = context.lbitWorkArea >> 1;
340 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS);
341 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS);
342 buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS);
343 break;
344 case 6 :
345 context.lbitWorkArea = context.lbitWorkArea >> 6;
346 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS);
347 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS);
348 buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS);
349 break;
350 case 7 :
351 context.lbitWorkArea = context.lbitWorkArea >> 3;
352 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 24) & MASK_8BITS);
353 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 16) & MASK_8BITS);
354 buffer[context.pos++] = (byte) ((context.lbitWorkArea >> 8) & MASK_8BITS);
355 buffer[context.pos++] = (byte) ((context.lbitWorkArea) & MASK_8BITS);
356 break;
357 default:
358
359 throw new IllegalStateException("Impossible modulus "+context.modulus);
360 }
361 }
362 }
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379 @Override
380 void encode(final byte[] in, int inPos, final int inAvail, final Context context) {
381
382
383 if (context.eof) {
384 return;
385 }
386
387
388 if (inAvail < 0) {
389 context.eof = true;
390 if (0 == context.modulus && lineLength == 0) {
391 return;
392 }
393 final byte[] buffer = ensureBufferSize(encodeSize, context);
394 final int savedPos = context.pos;
395 switch (context.modulus) {
396 case 0 :
397 break;
398 case 1 :
399 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 3) & MASK_5BITS];
400 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 2) & MASK_5BITS];
401 buffer[context.pos++] = PAD;
402 buffer[context.pos++] = PAD;
403 buffer[context.pos++] = PAD;
404 buffer[context.pos++] = PAD;
405 buffer[context.pos++] = PAD;
406 buffer[context.pos++] = PAD;
407 break;
408 case 2 :
409 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 11) & MASK_5BITS];
410 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 6) & MASK_5BITS];
411 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 1) & MASK_5BITS];
412 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 4) & MASK_5BITS];
413 buffer[context.pos++] = PAD;
414 buffer[context.pos++] = PAD;
415 buffer[context.pos++] = PAD;
416 buffer[context.pos++] = PAD;
417 break;
418 case 3 :
419 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 19) & MASK_5BITS];
420 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 14) & MASK_5BITS];
421 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 9) & MASK_5BITS];
422 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 4) & MASK_5BITS];
423 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 1) & MASK_5BITS];
424 buffer[context.pos++] = PAD;
425 buffer[context.pos++] = PAD;
426 buffer[context.pos++] = PAD;
427 break;
428 case 4 :
429 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 27) & MASK_5BITS];
430 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 22) & MASK_5BITS];
431 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 17) & MASK_5BITS];
432 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 12) & MASK_5BITS];
433 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 7) & MASK_5BITS];
434 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 2) & MASK_5BITS];
435 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 3) & MASK_5BITS];
436 buffer[context.pos++] = PAD;
437 break;
438 default:
439 throw new IllegalStateException("Impossible modulus "+context.modulus);
440 }
441 context.currentLinePos += context.pos - savedPos;
442
443 if (lineLength > 0 && context.currentLinePos > 0){
444 System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
445 context.pos += lineSeparator.length;
446 }
447 } else {
448 for (int i = 0; i < inAvail; i++) {
449 final byte[] buffer = ensureBufferSize(encodeSize, context);
450 context.modulus = (context.modulus+1) % BYTES_PER_UNENCODED_BLOCK;
451 int b = in[inPos++];
452 if (b < 0) {
453 b += 256;
454 }
455 context.lbitWorkArea = (context.lbitWorkArea << 8) + b;
456 if (0 == context.modulus) {
457 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 35) & MASK_5BITS];
458 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 30) & MASK_5BITS];
459 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 25) & MASK_5BITS];
460 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 20) & MASK_5BITS];
461 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 15) & MASK_5BITS];
462 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 10) & MASK_5BITS];
463 buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 5) & MASK_5BITS];
464 buffer[context.pos++] = encodeTable[(int)context.lbitWorkArea & MASK_5BITS];
465 context.currentLinePos += BYTES_PER_ENCODED_BLOCK;
466 if (lineLength > 0 && lineLength <= context.currentLinePos) {
467 System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
468 context.pos += lineSeparator.length;
469 context.currentLinePos = 0;
470 }
471 }
472 }
473 }
474 }
475
476
477
478
479
480
481
482
483 @Override
484 public boolean isInAlphabet(final byte octet) {
485 return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
486 }
487 }