src/share/classes/java/util/Base64.java
Print this page
*** 48,58 ****
* character. The decoder rejects data that contains characters
* outside the base64 alphabet.</p></li>
*
* <li><a name="url"><b>URL and Filename safe</b></a>
* <p> Uses the "URL and Filename safe Base64 Alphabet" as specified
! * in Table 2 of RFC 4648 for encoding and decoding. The
* encoder does not add any line feed (line separator) character.
* The decoder rejects data that contains characters outside the
* base64 alphabet.</p></li>
*
* <li><a name="mime"><b>MIME</b></a>
--- 48,58 ----
* character. The decoder rejects data that contains characters
* outside the base64 alphabet.</p></li>
*
* <li><a name="url"><b>URL and Filename safe</b></a>
* <p> Uses the "URL and Filename safe Base64 Alphabet" as specified
! * in Table 2 of RFC 4648 for encoding and decoding. The
* encoder does not add any line feed (line separator) character.
* The decoder rejects data that contains characters outside the
* base64 alphabet.</p></li>
*
* <li><a name="mime"><b>MIME</b></a>
*** 136,146 ****
"Illegal base64 line separator character 0x" + Integer.toString(b, 16));
}
if (lineLength <= 0) {
return Encoder.RFC4648;
}
! return new Encoder(false, lineSeparator, lineLength >> 2 << 2);
}
/**
* Returns a {@link Decoder} that decodes using the
* <a href="#basic">Basic</a> type base64 encoding scheme.
--- 136,146 ----
"Illegal base64 line separator character 0x" + Integer.toString(b, 16));
}
if (lineLength <= 0) {
return Encoder.RFC4648;
}
! return new Encoder(false, lineSeparator, lineLength >> 2 << 2, true);
}
/**
* Returns a {@link Decoder} that decodes using the
* <a href="#basic">Basic</a> type base64 encoding scheme.
*** 190,204 ****
public static class Encoder {
private final byte[] newline;
private final int linemax;
private final boolean isURL;
! private Encoder(boolean isURL, byte[] newline, int linemax) {
this.isURL = isURL;
this.newline = newline;
this.linemax = linemax;
}
/**
* This array is a lookup table that translates 6-bit positive integer
* index values into their "Base64 Alphabet" equivalents as specified
--- 190,206 ----
public static class Encoder {
private final byte[] newline;
private final int linemax;
private final boolean isURL;
+ private final boolean doPadding;
! private Encoder(boolean isURL, byte[] newline, int linemax, boolean doPadding) {
this.isURL = isURL;
this.newline = newline;
this.linemax = linemax;
+ this.doPadding = doPadding;
}
/**
* This array is a lookup table that translates 6-bit positive integer
* index values into their "Base64 Alphabet" equivalents as specified
*** 226,238 ****
};
private static final int MIMELINEMAX = 76;
private static final byte[] CRLF = new byte[] {'\r', '\n'};
! static final Encoder RFC4648 = new Encoder(false, null, -1);
! static final Encoder RFC4648_URLSAFE = new Encoder(true, null, -1);
! static final Encoder RFC2045 = new Encoder(false, CRLF, MIMELINEMAX);
/**
* Encodes all bytes from the specified byte array into a newly-allocated
* byte array using the {@link Base64} encoding scheme. The returned byte
* array is of the length of the resulting bytes.
--- 228,253 ----
};
private static final int MIMELINEMAX = 76;
private static final byte[] CRLF = new byte[] {'\r', '\n'};
! static final Encoder RFC4648 = new Encoder(false, null, -1, true);
! static final Encoder RFC4648_URLSAFE = new Encoder(true, null, -1, true);
! static final Encoder RFC2045 = new Encoder(false, CRLF, MIMELINEMAX, true);
!
! private final int outLength(int srclen) {
! int len = 0;
! if (doPadding) {
! len = 4 * ((srclen + 2) / 3);
! } else {
! int n = srclen % 3;
! len = 4 * (srclen / 3) + (n == 0 ? 0 : n + 1);
! }
! if (linemax > 0) // line separators
! len += (len - 1) / linemax * newline.length;
! return len;
! }
/**
* Encodes all bytes from the specified byte array into a newly-allocated
* byte array using the {@link Base64} encoding scheme. The returned byte
* array is of the length of the resulting bytes.
*** 241,253 ****
* the byte array to encode
* @return A newly-allocated byte array containing the resulting
* encoded bytes.
*/
public byte[] encode(byte[] src) {
! int len = 4 * ((src.length + 2) / 3); // dst array size
! if (linemax > 0) // line separators
! len += (len - 1) / linemax * newline.length;
byte[] dst = new byte[len];
int ret = encode0(src, 0, src.length, dst);
if (ret != dst.length)
return Arrays.copyOf(dst, ret);
return dst;
--- 256,266 ----
* the byte array to encode
* @return A newly-allocated byte array containing the resulting
* encoded bytes.
*/
public byte[] encode(byte[] src) {
! int len = outLength(src.length); // dst array size
byte[] dst = new byte[len];
int ret = encode0(src, 0, src.length, dst);
if (ret != dst.length)
return Arrays.copyOf(dst, ret);
return dst;
*** 271,284 ****
*
* @throws IllegalArgumentException if {@code dst} does not have enough
* space for encoding all input bytes.
*/
public int encode(byte[] src, byte[] dst) {
! int len = 4 * ((src.length + 2) / 3); // dst array size
! if (linemax > 0) {
! len += (len - 1) / linemax * newline.length;
! }
if (dst.length < len)
throw new IllegalArgumentException(
"Output byte array is too small for encoding all input bytes");
return encode0(src, 0, src.length, dst);
}
--- 284,294 ----
*
* @throws IllegalArgumentException if {@code dst} does not have enough
* space for encoding all input bytes.
*/
public int encode(byte[] src, byte[] dst) {
! int len = outLength(src.length); // dst array size
if (dst.length < len)
throw new IllegalArgumentException(
"Output byte array is too small for encoding all input bytes");
return encode0(src, 0, src.length, dst);
}
*** 319,331 ****
* @param buffer
* the source ByteBuffer to encode
* @return A newly-allocated byte buffer containing the encoded bytes.
*/
public ByteBuffer encode(ByteBuffer buffer) {
! int len = 4 * ((buffer.remaining() + 2) / 3);
! if (linemax > 0)
! len += (len - 1) / linemax * newline.length;
byte[] dst = new byte[len];
int ret = 0;
if (buffer.hasArray()) {
ret = encode0(buffer.array(),
buffer.arrayOffset() + buffer.position(),
--- 329,339 ----
* @param buffer
* the source ByteBuffer to encode
* @return A newly-allocated byte buffer containing the encoded bytes.
*/
public ByteBuffer encode(ByteBuffer buffer) {
! int len = outLength(buffer.remaining());
byte[] dst = new byte[len];
int ret = 0;
if (buffer.hasArray()) {
ret = encode0(buffer.array(),
buffer.arrayOffset() + buffer.position(),
*** 413,423 ****
* specified Base64 encoded format
*/
public OutputStream wrap(OutputStream os) {
Objects.requireNonNull(os);
return new EncOutputStream(os, isURL ? toBase64URL : toBase64,
! newline, linemax);
}
private int encodeArray(ByteBuffer src, ByteBuffer dst, int bytesOut) {
char[] base64 = isURL? toBase64URL : toBase64;
byte[] sa = src.array();
--- 421,449 ----
* specified Base64 encoded format
*/
public OutputStream wrap(OutputStream os) {
Objects.requireNonNull(os);
return new EncOutputStream(os, isURL ? toBase64URL : toBase64,
! newline, linemax, doPadding);
! }
!
! /**
! * Returns an encoder instance that encodes equivalently to this one,
! * but without adding any padding character at the end of the encoded
! * byte data.
! *
! * <p> The encoding scheme of this encoder instance is unaffected by
! * this invocation. The returned encoder instance should be used for
! * non-padding encoding operation.
! *
! * @return an equivalent encoder that encodes without adding any
! * padding character at the end
! */
! public Encoder withoutPadding() {
! if (!doPadding)
! return this;
! return new Encoder(isURL, newline, linemax, false);
}
private int encodeArray(ByteBuffer src, ByteBuffer dst, int bytesOut) {
char[] base64 = isURL? toBase64URL : toBase64;
byte[] sa = src.array();
*** 474,492 ****
--- 500,522 ----
if (sp < sl && dl >= dp + 4) { // 1 or 2 leftover bytes
int b0 = sa[sp++] & 0xff;
da[dp++] = (byte)base64[b0 >> 2];
if (sp == sl) {
da[dp++] = (byte)base64[(b0 << 4) & 0x3f];
+ if (doPadding) {
da[dp++] = '=';
da[dp++] = '=';
+ }
} else {
int b1 = sa[sp++] & 0xff;
da[dp++] = (byte)base64[(b0 << 4) & 0x3f | (b1 >> 4)];
da[dp++] = (byte)base64[(b1 << 2) & 0x3f];
+ if (doPadding) {
da[dp++] = '=';
}
}
+ }
return dp - dp00 + bytesOut;
} finally {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
*** 546,564 ****
--- 576,598 ----
if (sp < src.limit() && dl >= dp + 4) { // 1 or 2 leftover bytes
int b0 = src.get(sp++) & 0xff;
dst.put(dp++, (byte)base64[b0 >> 2]);
if (sp == src.limit()) {
dst.put(dp++, (byte)base64[(b0 << 4) & 0x3f]);
+ if (doPadding) {
dst.put(dp++, (byte)'=');
dst.put(dp++, (byte)'=');
+ }
} else {
int b1 = src.get(sp++) & 0xff;
dst.put(dp++, (byte)base64[(b0 << 4) & 0x3f | (b1 >> 4)]);
dst.put(dp++, (byte)base64[(b1 << 2) & 0x3f]);
+ if (doPadding) {
dst.put(dp++, (byte)'=');
}
}
+ }
return dp - dp00 + bytesOut;
} finally {
src.position(sp);
dst.position(dp);
}
*** 595,613 ****
--- 629,651 ----
if (sp < end) { // 1 or 2 leftover bytes
int b0 = src[sp++] & 0xff;
dst[dp++] = (byte)base64[b0 >> 2];
if (sp == end) {
dst[dp++] = (byte)base64[(b0 << 4) & 0x3f];
+ if (doPadding) {
dst[dp++] = '=';
dst[dp++] = '=';
+ }
} else {
int b1 = src[sp++] & 0xff;
dst[dp++] = (byte)base64[(b0 << 4) & 0x3f | (b1 >> 4)];
dst[dp++] = (byte)base64[(b1 << 2) & 0x3f];
+ if (doPadding) {
dst[dp++] = '=';
}
}
+ }
return dp;
}
}
/**
*** 1147,1164 ****
private boolean closed = false;
private final char[] base64; // byte->base64 mapping
private final byte[] newline; // line separator, if needed
private final int linemax;
private int linepos = 0;
! EncOutputStream(OutputStream os,
! char[] base64, byte[] newline, int linemax) {
super(os);
this.base64 = base64;
this.newline = newline;
this.linemax = linemax;
}
@Override
public void write(int b) throws IOException {
byte[] buf = new byte[1];
--- 1185,1204 ----
private boolean closed = false;
private final char[] base64; // byte->base64 mapping
private final byte[] newline; // line separator, if needed
private final int linemax;
+ private final boolean doPadding;// whether or not to pad
private int linepos = 0;
! EncOutputStream(OutputStream os, char[] base64,
! byte[] newline, int linemax, boolean doPadding) {
super(os);
this.base64 = base64;
this.newline = newline;
this.linemax = linemax;
+ this.doPadding = doPadding;
}
@Override
public void write(int b) throws IOException {
byte[] buf = new byte[1];
*** 1226,1244 ****
--- 1266,1288 ----
closed = true;
if (leftover == 1) {
checkNewline();
out.write(base64[b0 >> 2]);
out.write(base64[(b0 << 4) & 0x3f]);
+ if (doPadding) {
out.write('=');
out.write('=');
+ }
} else if (leftover == 2) {
checkNewline();
out.write(base64[b0 >> 2]);
out.write(base64[(b0 << 4) & 0x3f | (b1 >> 4)]);
out.write(base64[(b1 << 2) & 0x3f]);
+ if (doPadding) {
out.write('=');
}
+ }
leftover = 0;
out.close();
}
}
}