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(); } } }