You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2014/02/24 20:38:15 UTC
svn commit: r1571406 - in /commons/proper/codec/trunk/src: changes/
main/java/org/apache/commons/codec/binary/
test/java/org/apache/commons/codec/binary/
Author: ggregory
Date: Mon Feb 24 19:38:15 2014
New Revision: 1571406
URL: http://svn.apache.org/r1571406
Log:
<action dev="ggregory" type="add" issue="CODEC-181" due-to="Ivan Martinez-Ortiz">Make possible to provide padding byte to BaseNCodec in constructor</action>
Modified:
commons/proper/codec/trunk/src/changes/changes.xml
commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/Base32.java
commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/Base64.java
commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java
commons/proper/codec/trunk/src/test/java/org/apache/commons/codec/binary/Base32Test.java
commons/proper/codec/trunk/src/test/java/org/apache/commons/codec/binary/BaseNCodecTest.java
Modified: commons/proper/codec/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/changes/changes.xml?rev=1571406&r1=1571405&r2=1571406&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/changes/changes.xml (original)
+++ commons/proper/codec/trunk/src/changes/changes.xml Mon Feb 24 19:38:15 2014
@@ -43,6 +43,7 @@ The <action> type attribute can be add,u
</properties>
<body>
<release version="1.10" date="DD Mmmm 2014" description="Feature and fix release.">
+ <action dev="ggregory" type="add" issue="CODEC-181" due-to="Ivan Martinez-Ortiz">Make possible to provide padding byte to BaseNCodec in constructor</action>
<action dev="ggregory" type="fix" issue="CODEC-180" due-to="Ville Skyttä">Fix Javadoc 1.8.0 errors</action>
<action dev="ggregory" type="update" issue="CODEC-178">Deprecate Charsets Charset constants in favor of Java 7's java.nio.charset.StandardCharsets</action>
</release>
Modified: commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/Base32.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/Base32.java?rev=1571406&r1=1571405&r2=1571406&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/Base32.java (original)
+++ commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/Base32.java Mon Feb 24 19:38:15 2014
@@ -164,10 +164,33 @@ public class Base32 extends BaseNCodec {
* <p>
* When encoding the line length is 0 (no chunking).
* </p>
+ * @param pad byte used as padding byte.
+ */
+ public Base32(final byte pad) {
+ this(false, pad);
+ }
+
+ /**
+ * Creates a Base32 codec used for decoding and encoding.
+ * <p>
+ * When encoding the line length is 0 (no chunking).
+ * </p>
* @param useHex if {@code true} then use Base32 Hex alphabet
*/
public Base32(final boolean useHex) {
- this(0, null, useHex);
+ this(0, null, useHex, PAD_DEFAULT);
+ }
+
+ /**
+ * Creates a Base32 codec used for decoding and encoding.
+ * <p>
+ * When encoding the line length is 0 (no chunking).
+ * </p>
+ * @param useHex if {@code true} then use Base32 Hex alphabet
+ * @param pad byte used as padding byte.
+ */
+ public Base32(final boolean useHex, final byte pad) {
+ this(0, null, useHex, pad);
}
/**
@@ -204,7 +227,7 @@ public class Base32 extends BaseNCodec {
* The provided lineSeparator included some Base32 characters. That's not going to work!
*/
public Base32(final int lineLength, final byte[] lineSeparator) {
- this(lineLength, lineSeparator, false);
+ this(lineLength, lineSeparator, false, PAD_DEFAULT);
}
/**
@@ -229,10 +252,35 @@ public class Base32 extends BaseNCodec {
* lineLength > 0 and lineSeparator is null.
*/
public Base32(final int lineLength, final byte[] lineSeparator, final boolean useHex) {
- super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK,
- lineLength,
- lineSeparator == null ? 0 : lineSeparator.length);
- if (useHex){
+ this(lineLength, lineSeparator, useHex, PAD_DEFAULT);
+ }
+
+ /**
+ * Creates a Base32 / Base32 Hex codec used for decoding and encoding.
+ * <p>
+ * When encoding the line length and line separator are given in the constructor.
+ * </p>
+ * <p>
+ * Line lengths that aren't multiples of 8 will still essentially end up being multiples of 8 in the encoded data.
+ * </p>
+ *
+ * @param lineLength
+ * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of
+ * 8). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
+ * decoding.
+ * @param lineSeparator
+ * Each line of encoded data will end with this sequence of bytes.
+ * @param useHex
+ * if {@code true}, then use Base32 Hex alphabet, otherwise use Base32 alphabet
+ * @param pad byte used as padding byte.
+ * @throws IllegalArgumentException
+ * The provided lineSeparator included some Base32 characters. That's not going to work! Or the
+ * lineLength > 0 and lineSeparator is null.
+ */
+ public Base32(final int lineLength, final byte[] lineSeparator, final boolean useHex, final byte pad) {
+ super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength,
+ lineSeparator == null ? 0 : lineSeparator.length, pad);
+ if (useHex) {
this.encodeTable = HEX_ENCODE_TABLE;
this.decodeTable = HEX_DECODE_TABLE;
} else {
@@ -241,7 +289,7 @@ public class Base32 extends BaseNCodec {
}
if (lineLength > 0) {
if (lineSeparator == null) {
- throw new IllegalArgumentException("lineLength "+lineLength+" > 0, but lineSeparator is null");
+ throw new IllegalArgumentException("lineLength " + lineLength + " > 0, but lineSeparator is null");
}
// Must be done after initializing the tables
if (containsAlphabetOrPad(lineSeparator)) {
@@ -256,6 +304,10 @@ public class Base32 extends BaseNCodec {
this.lineSeparator = null;
}
this.decodeSize = this.encodeSize - 1;
+
+ if (isInAlphabet(pad) || isWhiteSpace(pad)) {
+ throw new IllegalArgumentException("pad must not be in alphabet or whitespace");
+ }
}
/**
@@ -292,7 +344,7 @@ public class Base32 extends BaseNCodec {
}
for (int i = 0; i < inAvail; i++) {
final byte b = in[inPos++];
- if (b == PAD) {
+ if (b == pad) {
// We're done.
context.eof = true;
break;
@@ -398,22 +450,22 @@ public class Base32 extends BaseNCodec {
case 1 : // Only 1 octet; take top 5 bits then remainder
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 3) & MASK_5BITS]; // 8-1*5 = 3
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 2) & MASK_5BITS]; // 5-3=2
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
break;
case 2 : // 2 octets = 16 bits to use
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 11) & MASK_5BITS]; // 16-1*5 = 11
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 6) & MASK_5BITS]; // 16-2*5 = 6
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 1) & MASK_5BITS]; // 16-3*5 = 1
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 4) & MASK_5BITS]; // 5-1 = 4
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
break;
case 3 : // 3 octets = 24 bits to use
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 19) & MASK_5BITS]; // 24-1*5 = 19
@@ -421,9 +473,9 @@ public class Base32 extends BaseNCodec {
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 9) & MASK_5BITS]; // 24-3*5 = 9
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 4) & MASK_5BITS]; // 24-4*5 = 4
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 1) & MASK_5BITS]; // 5-4 = 1
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
break;
case 4 : // 4 octets = 32 bits to use
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 27) & MASK_5BITS]; // 32-1*5 = 27
@@ -433,7 +485,7 @@ public class Base32 extends BaseNCodec {
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 7) & MASK_5BITS]; // 32-5*5 = 7
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea >> 2) & MASK_5BITS]; // 32-6*5 = 2
buffer[context.pos++] = encodeTable[(int)(context.lbitWorkArea << 3) & MASK_5BITS]; // 5-2 = 3
- buffer[context.pos++] = PAD;
+ buffer[context.pos++] = pad;
break;
default:
throw new IllegalStateException("Impossible modulus "+context.modulus);
Modified: commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/Base64.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/Base64.java?rev=1571406&r1=1571405&r2=1571406&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/Base64.java (original)
+++ commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/Base64.java Mon Feb 24 19:38:15 2014
@@ -348,8 +348,8 @@ public class Base64 extends BaseNCodec {
buffer[context.pos++] = encodeTable[(context.ibitWorkArea << 4) & MASK_6BITS];
// URL-SAFE skips the padding to further reduce size.
if (encodeTable == STANDARD_ENCODE_TABLE) {
- buffer[context.pos++] = PAD;
- buffer[context.pos++] = PAD;
+ buffer[context.pos++] = pad;
+ buffer[context.pos++] = pad;
}
break;
@@ -359,7 +359,7 @@ public class Base64 extends BaseNCodec {
buffer[context.pos++] = encodeTable[(context.ibitWorkArea << 2) & MASK_6BITS];
// URL-SAFE skips the padding to further reduce size.
if (encodeTable == STANDARD_ENCODE_TABLE) {
- buffer[context.pos++] = PAD;
+ buffer[context.pos++] = pad;
}
break;
default:
@@ -432,7 +432,7 @@ public class Base64 extends BaseNCodec {
for (int i = 0; i < inAvail; i++) {
final byte[] buffer = ensureBufferSize(decodeSize, context);
final byte b = in[inPos++];
- if (b == PAD) {
+ if (b == pad) {
// We're done.
context.eof = true;
break;
Modified: commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java?rev=1571406&r1=1571405&r2=1571406&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java (original)
+++ commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java Mon Feb 24 19:38:15 2014
@@ -153,8 +153,14 @@ public abstract class BaseNCodec impleme
*/
protected static final byte PAD_DEFAULT = '='; // Allow static access to default
+ /**
+ * @deprecated Use {@link #pad}. Will be removed in 2.0.
+ */
+ @Deprecated
protected final byte PAD = PAD_DEFAULT; // instance variable just in case it needs to vary later
+ protected final byte pad; // instance variable just in case it needs to vary later
+
/** Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32 */
private final int unencodedBlockSize;
@@ -183,11 +189,27 @@ public abstract class BaseNCodec impleme
*/
protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize,
final int lineLength, final int chunkSeparatorLength) {
+ this(unencodedBlockSize, encodedBlockSize, lineLength, chunkSeparatorLength, PAD_DEFAULT);
+ }
+
+ /**
+ * Note <code>lineLength</code> is rounded down to the nearest multiple of {@link #encodedBlockSize}
+ * If <code>chunkSeparatorLength</code> is zero, then chunking is disabled.
+ * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3)
+ * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4)
+ * @param lineLength if > 0, use chunking with a length <code>lineLength</code>
+ * @param chunkSeparatorLength the chunk separator length, if relevant
+ * @param pad byte used as padding byte.
+ */
+ protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize,
+ final int lineLength, final int chunkSeparatorLength, final byte pad) {
this.unencodedBlockSize = unencodedBlockSize;
this.encodedBlockSize = encodedBlockSize;
final boolean useChunking = lineLength > 0 && chunkSeparatorLength > 0;
this.lineLength = useChunking ? (lineLength / encodedBlockSize) * encodedBlockSize : 0;
this.chunkSeparatorLength = chunkSeparatorLength;
+
+ this.pad = pad;
}
/**
@@ -440,7 +462,7 @@ public abstract class BaseNCodec impleme
public boolean isInAlphabet(final byte[] arrayOctet, final boolean allowWSPad) {
for (int i = 0; i < arrayOctet.length; i++) {
if (!isInAlphabet(arrayOctet[i]) &&
- (!allowWSPad || (arrayOctet[i] != PAD) && !isWhiteSpace(arrayOctet[i]))) {
+ (!allowWSPad || (arrayOctet[i] != pad) && !isWhiteSpace(arrayOctet[i]))) {
return false;
}
}
@@ -474,7 +496,7 @@ public abstract class BaseNCodec impleme
return false;
}
for (final byte element : arrayOctet) {
- if (PAD == element || isInAlphabet(element)) {
+ if (pad == element || isInAlphabet(element)) {
return true;
}
}
Modified: commons/proper/codec/trunk/src/test/java/org/apache/commons/codec/binary/Base32Test.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/test/java/org/apache/commons/codec/binary/Base32Test.java?rev=1571406&r1=1571405&r2=1571406&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/test/java/org/apache/commons/codec/binary/Base32Test.java (original)
+++ commons/proper/codec/trunk/src/test/java/org/apache/commons/codec/binary/Base32Test.java Mon Feb 24 19:38:15 2014
@@ -59,6 +59,16 @@ public class Base32Test {
{"foobar" ,"MZXW6YTBOI======\r\n"},
};
+ private static final String [][] BASE32_PAD_TEST_CASES = { // RFC 4648
+ {"" ,""},
+ {"f" ,"MY%%%%%%"},
+ {"fo" ,"MZXQ%%%%"},
+ {"foo" ,"MZXW6%%%"},
+ {"foob" ,"MZXW6YQ%"},
+ {"fooba" ,"MZXW6YTB"},
+ {"foobar" ,"MZXW6YTBOI%%%%%%"},
+ };
+
@Test
public void testBase32Samples() throws Exception {
final Base32 codec = new Base32();
@@ -132,4 +142,13 @@ public class Base32Test {
//assertEquals(b[0],codec.decode(b[1]));
}
}
+
+ @Test
+ public void testBase32SamplesNonDefaultPadding() throws Exception {
+ final Base32 codec = new Base32((byte)0x25); // '%' <=> 0x25
+
+ for (final String[] element : BASE32_PAD_TEST_CASES) {
+ assertEquals(element[1], codec.encodeAsString(element[0].getBytes(Charsets.UTF_8)));
+ }
+ }
}
Modified: commons/proper/codec/trunk/src/test/java/org/apache/commons/codec/binary/BaseNCodecTest.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/test/java/org/apache/commons/codec/binary/BaseNCodecTest.java?rev=1571406&r1=1571405&r2=1571406&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/test/java/org/apache/commons/codec/binary/BaseNCodecTest.java (original)
+++ commons/proper/codec/trunk/src/test/java/org/apache/commons/codec/binary/BaseNCodecTest.java Mon Feb 24 19:38:15 2014
@@ -21,6 +21,7 @@ package org.apache.commons.codec.binary;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
@@ -158,11 +159,36 @@ public class BaseNCodecTest {
assertTrue(codec.containsAlphabetOrPad("OK".getBytes()));
assertTrue(codec.containsAlphabetOrPad("OK ".getBytes()));
assertFalse(codec.containsAlphabetOrPad("ok ".getBytes()));
- assertTrue(codec.containsAlphabetOrPad(new byte[]{codec.PAD}));
+ assertTrue(codec.containsAlphabetOrPad(new byte[]{codec.pad}));
}
// @Test
// public void testGetEncodedLength() {
// fail("Not yet implemented");
// }
+
+ @Test
+ public void testProvidePaddingByte() {
+ // Given
+ codec = new BaseNCodec(0, 0, 0, 0, (byte)0x25) {
+ @Override
+ protected boolean isInAlphabet(final byte b) {
+ return b=='O' || b == 'K'; // allow OK
+ }
+
+ @Override
+ void encode(final byte[] pArray, final int i, final int length, final Context context) {
+ }
+
+ @Override
+ void decode(final byte[] pArray, final int i, final int length, final Context context) {
+ }
+ };
+
+ // When
+ byte actualPaddingByte = codec.pad;
+
+ // Then
+ assertEquals(0x25, actualPaddingByte);
+ }
}