Skip to content

Commit 4ed1cf9

Browse files
committed
open for different alphabets - add calculating of decode table for custom encode table
1 parent 31ece68 commit 4ed1cf9

1 file changed

Lines changed: 39 additions & 10 deletions

File tree

  • src/main/java/org/apache/commons/codec/binary

src/main/java/org/apache/commons/codec/binary/Base64.java

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public class Base64 extends BaseNCodec {
111111
* Thanks to "commons" project in ws.apache.org for this code.
112112
* http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
113113
*/
114-
private static final byte[] DECODE_TABLE = {
114+
private static final byte[] DEFAULT_DECODE_TABLE = {
115115
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
116116
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
117117
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f
@@ -134,14 +134,18 @@ public class Base64 extends BaseNCodec {
134134
// some state be preserved between calls of encode() and decode().
135135

136136
/**
137-
* Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
138-
* to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
139-
* between the two modes.
137+
* Encode table to use: either STANDARD or URL_SAFE or custom.
138+
* Note: the DEFAULT_DECODE_TABLE above remains static for STANDARD and URL_SAFA
139+
* because it is able to decode both STANDARD and URL_SAFE streams,
140+
* but the encodeTable must be a member variable so we can switch
141+
* between modes.
140142
*/
141143
private final byte[] encodeTable;
142144

143-
// Only one decode table currently; keep for consistency with Base32 code
144-
private final byte[] decodeTable = DECODE_TABLE;
145+
/**
146+
* Decode table to use
147+
*/
148+
private final byte[] decodeTable;
145149

146150
/**
147151
* Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
@@ -300,6 +304,15 @@ public Base64(final int lineLength, final byte[] lineSeparator, byte[] encodeTab
300304
super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK,
301305
lineLength,
302306
lineSeparator == null ? 0 : lineSeparator.length);
307+
308+
this.encodeTable = encodeTable;
309+
310+
if (encodeTable == STANDARD_ENCODE_TABLE || encodeTable == URL_SAFE_ENCODE_TABLE) {
311+
decodeTable = DEFAULT_DECODE_TABLE;
312+
} else {
313+
decodeTable = calculateDecodeTable(encodeTable);
314+
}
315+
303316
// TODO could be simplified if there is no requirement to reject invalid line sep when length <=0
304317
// @see test case Base64Test.testConstructors()
305318
if (lineSeparator != null) {
@@ -320,7 +333,23 @@ public Base64(final int lineLength, final byte[] lineSeparator, byte[] encodeTab
320333
this.lineSeparator = null;
321334
}
322335
this.decodeSize = this.encodeSize - 1;
323-
this.encodeTable = encodeTable;
336+
}
337+
338+
/**
339+
* calculates a decode table for a given encode table
340+
*
341+
* @param encodeTable
342+
* @return decodeTable
343+
*/
344+
private byte[] calculateDecodeTable(byte[] encodeTable) {
345+
byte[] decodeTable = new byte[256];
346+
for (int i=0; i < 256; i++) {
347+
decodeTable[i] = -1;
348+
}
349+
for (int i=0; i < encodeTable.length; i++) {
350+
decodeTable[(int) encodeTable[i]] = (byte) i;
351+
}
352+
return decodeTable;
324353
}
325354

326355
/**
@@ -467,8 +496,8 @@ void decode(final byte[] in, int inPos, final int inAvail, final Context context
467496
context.eof = true;
468497
break;
469498
}
470-
if (b >= 0 && b < DECODE_TABLE.length) {
471-
final int result = DECODE_TABLE[b];
499+
if (b >= 0 && b < decodeTable.length) {
500+
final int result = decodeTable[b];
472501
if (result >= 0) {
473502
context.modulus = (context.modulus+1) % BYTES_PER_ENCODED_BLOCK;
474503
context.ibitWorkArea = (context.ibitWorkArea << BITS_PER_ENCODED_BYTE) + result;
@@ -535,7 +564,7 @@ public static boolean isArrayByteBase64(final byte[] arrayOctet) {
535564
* @since 1.4
536565
*/
537566
public static boolean isBase64(final byte octet) {
538-
return octet == PAD_DEFAULT || (octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1);
567+
return octet == PAD_DEFAULT || (octet >= 0 && octet < DEFAULT_DECODE_TABLE.length && DEFAULT_DECODE_TABLE[octet] != -1);
539568
}
540569

541570
/**

0 commit comments

Comments
 (0)