# HG changeset patch # User sherman # Date 1354082831 28800 # Node ID be67058c3dc7bc770659f44418c8297519a899ce # Parent 9ed95934188b5c42046e0fd4678e997fce019230 8004088: hg push for bug#4235519 failed to push all files Summary: pushed all base64 files Reviewed-by: alanb, mduigou diff -r 9ed95934188b -r be67058c3dc7 jdk/src/share/classes/java/util/Base64.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/util/Base64.java Tue Nov 27 22:07:11 2012 -0800 @@ -0,0 +1,1316 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util; + +import java.io.FilterOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +/** + * This class consists exclusively of static methods for obtaining + * encoders and decoders for the Base64 encoding scheme. The + * implementation of this class supports the following types of Base64 + * as specified in + * RFC 4648 and + * RFC 2045. + * + *

+ *

+ * + *

Unless otherwise noted, passing a {@code null} argument to a + * method of this class will cause a {@link java.lang.NullPointerException + * NullPointerException} to be thrown. + * + * @author Xueming Shen + * @since 1.8 + */ + +public class Base64 { + + private Base64() {} + + /** + * Returns a {@link Encoder} that encodes using the + * Basic type base64 encoding scheme. + * + * @return A Base64 encoder. + */ + public static Encoder getEncoder() { + return Encoder.RFC4648; + } + + /** + * Returns a {@link Encoder} that encodes using the + * URL and Filename safe type base64 + * encoding scheme. + * + * @return A Base64 encoder. + */ + public static Encoder getUrlEncoder() { + return Encoder.RFC4648_URLSAFE; + } + + /** + * Returns a {@link Encoder} that encodes using the + * MIME type base64 encoding scheme. + * + * @return A Base64 encoder. + */ + public static Encoder getMimeEncoder() { + return Encoder.RFC2045; + } + + /** + * Returns a {@link Encoder} that encodes using the + * MIME type base64 encoding scheme + * with specified line length and line separators. + * + * @param lineLength + * the length of each output line (rounded down to nearest multiple + * of 4). If {@code lineLength <= 0} the output will not be separated + * in lines + * @param lineSeparator + * the line separator for each output line + * + * @return A Base64 encoder. + * + * @throws IllegalArgumentException if {@code lineSeparator} includes any + * character of "The Base64 Alphabet" as specified in Table 1 of + * RFC 2045. + */ + public static Encoder getEncoder(int lineLength, byte[] lineSeparator) { + Objects.requireNonNull(lineSeparator); + int[] base64 = Decoder.fromBase64; + for (byte b : lineSeparator) { + if (base64[b & 0xff] != -1) + throw new IllegalArgumentException( + "Illegal base64 line separator character 0x" + Integer.toString(b, 16)); + } + return new Encoder(false, lineSeparator, lineLength >> 2 << 2); + } + + /** + * Returns a {@link Decoder} that decodes using the + * Basic type base64 encoding scheme. + * + * @return A Base64 decoder. + */ + public static Decoder getDecoder() { + return Decoder.RFC4648; + } + + /** + * Returns a {@link Decoder} that decodes using the + * URL and Filename safe type base64 + * encoding scheme. + * + * @return A Base64 decoder. + */ + public static Decoder getUrlDecoder() { + return Decoder.RFC4648_URLSAFE; + } + + /** + * Returns a {@link Decoder} that decodes using the + * MIME type base64 decoding scheme. + * + * @return A Base64 decoder. + */ + public static Decoder getMimeDecoder() { + return Decoder.RFC2045; + } + + /** + * This class implements an encoder for encoding byte data using + * the Base64 encoding scheme as specified in RFC 4648 and RFC 2045. + * + *

Instances of {@link Encoder} class are safe for use by + * multiple concurrent threads. + * + *

Unless otherwise noted, passing a {@code null} argument to + * a method of this class will cause a + * {@link java.lang.NullPointerException NullPointerException} to + * be thrown. + * + * @see Decoder + * @since 1.8 + */ + 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 + * in "Table 1: The Base64 Alphabet" of RFC 2045 (and RFC 4648). + */ + private static final char[] toBase64 = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' + }; + + /** + * It's the lookup table for "URL and Filename safe Base64" as specified + * in Table 2 of the RFC 4648, with the '+' and '/' changed to '-' and + * '_'. This table is used when BASE64_URL is specified. + */ + private static final char[] toBase64URL = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' + }; + + 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. + * + * @param src + * 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; + } + + /** + * Encodes all bytes from the specified byte array using the + * {@link Base64} encoding scheme, writing the resulting bytes to the + * given output byte array, starting at offset 0. + * + *

It is the responsibility of the invoker of this method to make + * sure the output byte array {@code dst} has enough space for encoding + * all bytes from the input byte array. No bytes will be written to the + * output byte array if the output byte array is not big enough. + * + * @param src + * the byte array to encode + * @param dst + * the output byte array + * @return The number of bytes written to the output byte array + * + * @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); + } + + /** + * Encodes the specified byte array into a String using the {@link Base64} + * encoding scheme. + * + *

This method first encodes all input bytes into a base64 encoded + * byte array and then constructs a new String by using the encoded byte + * array and the {@link java.nio.charset.StandardCharsets.ISO_8859_1 ISO-8859-1} + * charset. + * + *

In other words, an invocation of this method has exactly the same + * effect as invoking + * {@code new String(encode(src), StandardCharsets.ISO_8859_1)}. + * + * @param src + * the byte array to encode + * @return A String containing the resulting Base64 encoded characters + */ + @SuppressWarnings("deprecation") + public String encodeToString(byte[] src) { + byte[] encoded = encode(src); + return new String(encoded, 0, 0, encoded.length); + } + + /** + * Encodes all remaining bytes from the specified byte buffer into + * a newly-allocated ByteBuffer using the {@link Base64} encoding + * scheme. + * + * Upon return, the source buffer's position will be updated to + * its limit; its limit will not have been changed. The returned + * output buffer's position will be zero and its limit will be the + * number of resulting encoded bytes. + * + * @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(), + buffer.arrayOffset() + buffer.limit(), + dst); + buffer.position(buffer.limit()); + } else { + byte[] src = new byte[buffer.remaining()]; + buffer.get(src); + ret = encode0(src, 0, src.length, dst); + } + if (ret != dst.length) + dst = Arrays.copyOf(dst, ret); + return ByteBuffer.wrap(dst); + } + + /** + * Encodes as many bytes as possible from the input byte buffer + * using the {@link Base64} encoding scheme, writing the resulting + * bytes to the given output byte buffer. + * + *

The buffers are read from, and written to, starting at their + * current positions. Upon return, the input and output buffers' + * positions will be advanced to reflect the bytes read and written, + * but their limits will not be modified. + * + *

The encoding operation will stop and return if either all + * remaining bytes in the input buffer have been encoded and written + * to the output buffer, or the output buffer has insufficient space + * to encode any more input bytes. The encoding operation can be + * continued, if there is more bytes in input buffer to be encoded, + * by invoking this method again with an output buffer that has more + * {@linkplain Buffer#remaining remaining} bytes. This is typically + * done by draining any encoded bytes from the output buffer. The + * value returned from last invocation needs to be passed in as the + * third parameter {@code bytesOut} if it is to continue an unfinished + * encoding, 0 otherwise. + * + *

Recommended Usage Example + *

+         *    ByteBuffer src = ...;
+         *    ByteBuffer dst = ...;
+         *    Base64.Encoder enc = Base64.getMimeDecoder();
+         *
+         *    int bytesOut = 0;
+         *    while (src.hasRemaining()) {
+         *        // clear output buffer for decoding
+         *        dst.clear();
+         *        bytesOut = enc.encode(src, dst, bytesOut);
+         *
+         *        // read encoded bytes out of "dst"
+         *        dst.flip();
+         *        ...
+         *    }
+         * 
+ * + * @param src + * the input byte buffer to encode + * @param dst + * the output byte buffer + * @param bytesOut + * the return value of last invocation if this is to continue + * an unfinished encoding operation, 0 otherwise + * @return The sum total of {@code bytesOut} and the number of bytes + * written to the output ByteBuffer during this invocation. + */ + public int encode(ByteBuffer src, ByteBuffer dst, int bytesOut) { + if (src.hasArray() && dst.hasArray()) + return encodeArray(src, dst, bytesOut); + return encodeBuffer(src, dst, bytesOut); + } + + /** + * Wraps an output stream for encoding byte data using the {@link Base64} + * encoding scheme. + * + *

It is recommended to promptly close the returned output stream after + * use, during which it will flush all possible leftover bytes to the underlying + * output stream. Closing the returned output stream will close the underlying + * output stream. + * + * @param os + * the output stream. + * @return the output stream for encoding the byte data into the + * specified Base64 encoded format + */ + public OutputStream wrap(OutputStream 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(); + int sp = src.arrayOffset() + src.position(); + int sl = src.arrayOffset() + src.limit(); + byte[] da = dst.array(); + int dp = dst.arrayOffset() + dst.position(); + int dl = dst.arrayOffset() + dst.limit(); + int dp00 = dp; + int dpos = 0; // dp of each line + if (linemax > 0 && bytesOut > 0) + dpos = bytesOut % (linemax + newline.length); + try { + if (dpos == linemax && sp < src.limit()) { + if (dp + newline.length > dl) + return dp - dp00 + bytesOut; + for (byte b : newline){ + dst.put(dp++, b); + } + dpos = 0; + } + sl = sp + (sl - sp) / 3 * 3; + while (sp < sl) { + int slen = (linemax > 0) ? (linemax - dpos) / 4 * 3 + : sl - sp; + int sl0 = Math.min(sp + slen, sl); + for (int sp0 = sp, dp0 = dp ; sp0 < sl0; ) { + if (dp0 + 4 > dl) { + sp = sp0; dp = dp0; + return dp0 - dp00 + bytesOut; + } + int bits = (sa[sp0++] & 0xff) << 16 | + (sa[sp0++] & 0xff) << 8 | + (sa[sp0++] & 0xff); + da[dp0++] = (byte)base64[(bits >>> 18) & 0x3f]; + da[dp0++] = (byte)base64[(bits >>> 12) & 0x3f]; + da[dp0++] = (byte)base64[(bits >>> 6) & 0x3f]; + da[dp0++] = (byte)base64[bits & 0x3f]; + } + int n = (sl0 - sp) / 3 * 4; + dpos += n; + dp += n; + sp = sl0; + if (dpos == linemax && sp < src.limit()) { + if (dp + newline.length > dl) + return dp - dp00 + bytesOut; + for (byte b : newline){ + da[dp++] = b; + } + dpos = 0; + } + } + sl = src.arrayOffset() + src.limit(); + 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]; + 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]; + da[dp++] = '='; + } + } + return dp - dp00 + bytesOut; + } finally { + src.position(sp - src.arrayOffset()); + dst.position(dp - dst.arrayOffset()); + } + } + + private int encodeBuffer(ByteBuffer src, ByteBuffer dst, int bytesOut) { + char[] base64 = isURL? toBase64URL : toBase64; + int sp = src.position(); + int sl = src.limit(); + int dp = dst.position(); + int dl = dst.limit(); + int dp00 = dp; + + int dpos = 0; // dp of each line + if (linemax > 0 && bytesOut > 0) + dpos = bytesOut % (linemax + newline.length); + try { + if (dpos == linemax && sp < src.limit()) { + if (dp + newline.length > dl) + return dp - dp00 + bytesOut; + for (byte b : newline){ + dst.put(dp++, b); + } + dpos = 0; + } + sl = sp + (sl - sp) / 3 * 3; + while (sp < sl) { + int slen = (linemax > 0) ? (linemax - dpos) / 4 * 3 + : sl - sp; + int sl0 = Math.min(sp + slen, sl); + for (int sp0 = sp, dp0 = dp ; sp0 < sl0; ) { + if (dp0 + 4 > dl) { + sp = sp0; dp = dp0; + return dp0 - dp00 + bytesOut; + } + int bits = (src.get(sp0++) & 0xff) << 16 | + (src.get(sp0++) & 0xff) << 8 | + (src.get(sp0++) & 0xff); + dst.put(dp0++, (byte)base64[(bits >>> 18) & 0x3f]); + dst.put(dp0++, (byte)base64[(bits >>> 12) & 0x3f]); + dst.put(dp0++, (byte)base64[(bits >>> 6) & 0x3f]); + dst.put(dp0++, (byte)base64[bits & 0x3f]); + } + int n = (sl0 - sp) / 3 * 4; + dpos += n; + dp += n; + sp = sl0; + if (dpos == linemax && sp < src.limit()) { + if (dp + newline.length > dl) + return dp - dp00 + bytesOut; + for (byte b : newline){ + dst.put(dp++, b); + } + dpos = 0; + } + } + 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]); + 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]); + dst.put(dp++, (byte)'='); + } + } + return dp - dp00 + bytesOut; + } finally { + src.position(sp); + dst.position(dp); + } + } + + private int encode0(byte[] src, int off, int end, byte[] dst) { + char[] base64 = isURL ? toBase64URL : toBase64; + int sp = off; + int slen = (end - off) / 3 * 3; + int sl = off + slen; + if (linemax > 0 && slen > linemax / 4 * 3) + slen = linemax / 4 * 3; + int dp = 0; + while (sp < sl) { + int sl0 = Math.min(sp + slen, sl); + for (int sp0 = sp, dp0 = dp ; sp0 < sl0; ) { + int bits = (src[sp0++] & 0xff) << 16 | + (src[sp0++] & 0xff) << 8 | + (src[sp0++] & 0xff); + dst[dp0++] = (byte)base64[(bits >>> 18) & 0x3f]; + dst[dp0++] = (byte)base64[(bits >>> 12) & 0x3f]; + dst[dp0++] = (byte)base64[(bits >>> 6) & 0x3f]; + dst[dp0++] = (byte)base64[bits & 0x3f]; + } + int dlen = (sl0 - sp) / 3 * 4; + dp += dlen; + sp = sl0; + if (dlen == linemax && sp < end) { + for (byte b : newline){ + dst[dp++] = b; + } + } + } + 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]; + 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]; + dst[dp++] = '='; + } + } + return dp; + } + } + + /** + * This class implements a decoder for decoding byte data using the + * Base64 encoding scheme as specified in RFC 4648 and RFC 2045. + * + *

Instances of {@link Decoder} class are safe for use by + * multiple concurrent threads. + * + *

Unless otherwise noted, passing a {@code null} argument to + * a method of this class will cause a + * {@link java.lang.NullPointerException NullPointerException} to + * be thrown. + * + * @see Encoder + * @since 1.8 + */ + public static class Decoder { + + private final boolean isURL; + private final boolean isMIME; + + private Decoder(boolean isURL, boolean isMIME) { + this.isURL = isURL; + this.isMIME = isMIME; + } + + /** + * Lookup table for decoding unicode characters drawn from the + * "Base64 Alphabet" (as specified in Table 1 of RFC 2045) into + * their 6-bit positive integer equivalents. Characters that + * are not in the Base64 alphabet but fall within the bounds of + * the array are encoded to -1. + * + */ + private static final int[] fromBase64 = new int[256]; + static { + Arrays.fill(fromBase64, -1); + for (int i = 0; i < Encoder.toBase64.length; i++) + fromBase64[Encoder.toBase64[i]] = i; + fromBase64['='] = -2; + } + + /** + * Lookup table for decoding "URL and Filename safe Base64 Alphabet" + * as specified in Table2 of the RFC 4648. + */ + private static final int[] fromBase64URL = new int[256]; + + static { + Arrays.fill(fromBase64URL, -1); + for (int i = 0; i < Encoder.toBase64URL.length; i++) + fromBase64URL[Encoder.toBase64URL[i]] = i; + fromBase64URL['='] = -2; + } + + static final Decoder RFC4648 = new Decoder(false, false); + static final Decoder RFC4648_URLSAFE = new Decoder(true, false); + static final Decoder RFC2045 = new Decoder(false, true); + + /** + * Decodes all bytes from the input byte array using the {@link Base64} + * encoding scheme, writing the results into a newly-allocated output + * byte array. The returned byte array is of the length of the resulting + * bytes. + * + * @param src + * the byte array to decode + * + * @return A newly-allocated byte array containing the decoded bytes. + * + * @throws IllegalArgumentException + * if {@code src} is not in valid Base64 scheme + */ + public byte[] decode(byte[] src) { + byte[] dst = new byte[outLength(src, 0, src.length)]; + int ret = decode0(src, 0, src.length, dst); + if (ret != dst.length) { + dst = Arrays.copyOf(dst, ret); + } + return dst; + } + + /** + * Decodes a Base64 encoded String into a newly-allocated byte array + * using the {@link Base64} encoding scheme. + * + *

An invocation of this method has exactly the same effect as invoking + * {@code return decode(src.getBytes(StandardCharsets.ISO_8859_1))} + * + * @param src + * the string to decode + * + * @return A newly-allocated byte array containing the decoded bytes. + * + * @throws IllegalArgumentException + * if {@code src} is not in valid Base64 scheme + */ + public byte[] decode(String src) { + return decode(src.getBytes(StandardCharsets.ISO_8859_1)); + } + + /** + * Decodes all bytes from the input byte array using the {@link Base64} + * encoding scheme, writing the results into the given output byte array, + * starting at offset 0. + * + *

It is the responsibility of the invoker of this method to make + * sure the output byte array {@code dst} has enough space for decoding + * all bytes from the input byte array. No bytes will be be written to + * the output byte array if the output byte array is not big enough. + * + *

If the input byte array is not in valid Base64 encoding scheme + * then some bytes may have been written to the output byte array before + * IllegalargumentException is thrown. + * + * @param src + * the byte array to decode + * @param dst + * the output byte array + * + * @return The number of bytes written to the output byte array + * + * @throws IllegalArgumentException + * if {@code src} is not in valid Base64 scheme, or {@code dst} + * does not have enough space for decoding all input bytes. + */ + public int decode(byte[] src, byte[] dst) { + int len = outLength(src, 0, src.length); + if (dst.length < len) + throw new IllegalArgumentException( + "Output byte array is too small for decoding all input bytes"); + return decode0(src, 0, src.length, dst); + } + + /** + * Decodes all bytes from the input byte buffer using the {@link Base64} + * encoding scheme, writing the results into a newly-allocated ByteBuffer. + * + *

Upon return, the source buffer's position will be updated to + * its limit; its limit will not have been changed. The returned + * output buffer's position will be zero and its limit will be the + * number of resulting decoded bytes + * + * @param buffer + * the ByteBuffer to decode + * + * @return A newly-allocated byte buffer containing the decoded bytes + * + * @throws IllegalArgumentException + * if {@code src} is not in valid Base64 scheme. + */ + public ByteBuffer decode(ByteBuffer buffer) { + int pos0 = buffer.position(); + try { + byte[] src; + int sp, sl; + if (buffer.hasArray()) { + src = buffer.array(); + sp = buffer.arrayOffset() + buffer.position(); + sl = buffer.arrayOffset() + buffer.limit(); + buffer.position(buffer.limit()); + } else { + src = new byte[buffer.remaining()]; + buffer.get(src); + sp = 0; + sl = src.length; + } + byte[] dst = new byte[outLength(src, sp, sl)]; + return ByteBuffer.wrap(dst, 0, decode0(src, sp, sl, dst)); + } catch (IllegalArgumentException iae) { + buffer.position(pos0); + throw iae; + } + } + + /** + * Decodes as many bytes as possible from the input byte buffer + * using the {@link Base64} encoding scheme, writing the resulting + * bytes to the given output byte buffer. + * + *

The buffers are read from, and written to, starting at their + * current positions. Upon return, the input and output buffers' + * positions will be advanced to reflect the bytes read and written, + * but their limits will not be modified. + * + *

If the input buffer is not in valid Base64 encoding scheme + * then some bytes may have been written to the output buffer + * before IllegalArgumentException is thrown. The positions of + * both input and output buffer will not be advanced in this case. + * + *

The decoding operation will end and return if all remaining + * bytes in the input buffer have been decoded and written to the + * output buffer. + * + *

The decoding operation will stop and return if the output + * buffer has insufficient space to decode any more input bytes. + * The decoding operation can be continued, if there is more bytes + * in input buffer to be decoded, by invoking this method again with + * an output buffer that has more {@linkplain Buffer#remaining remaining} + * bytes.This is typically done by draining any decoded bytes from the + * output buffer. + * + *

Recommended Usage Example + *

+         *    ByteBuffer src = ...;
+         *    ByteBuffer dst = ...;
+         *    Base64.Decoder dec = Base64.getDecoder();
+         *
+         *    while (src.hasRemaining()) {
+         *
+         *        // prepare the output byte buffer
+         *        dst.clear();
+         *        dec.decode(src, dst);
+         *
+         *        // read bytes from the output buffer
+         *        dst.flip();
+         *        ...
+         *    }
+         * 
+ * + * @param src + * the input byte buffer to decode + * @param dst + * the output byte buffer + * + * @return The number of bytes written to the output byte buffer during + * this decoding invocation + * + * @throws IllegalArgumentException + * if {@code src} is not in valid Base64 scheme. + */ + public int decode(ByteBuffer src, ByteBuffer dst) { + int sp0 = src.position(); + int dp0 = dst.position(); + try { + if (src.hasArray() && dst.hasArray()) + return decodeArray(src, dst); + return decodeBuffer(src, dst); + } catch (IllegalArgumentException iae) { + src.position(sp0); + dst.position(dp0); + throw iae; + } + } + + /** + * Returns an input stream for decoding {@link Base64} encoded byte stream. + * + *

Closing the returned input stream will close the underlying + * input stream. + * + * @param is + * the input stream + * + * @return the input stream for decoding the specified Base64 encoded + * byte stream + */ + public InputStream wrap(InputStream is) { + return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME); + } + + private int decodeArray(ByteBuffer src, ByteBuffer dst) { + int[] base64 = isURL ? fromBase64URL : fromBase64; + int bits = 0; + int shiftto = 18; // pos of first byte of 4-byte atom + byte[] sa = src.array(); + int sp = src.arrayOffset() + src.position(); + int sl = src.arrayOffset() + src.limit(); + byte[] da = dst.array(); + int dp = dst.arrayOffset() + dst.position(); + int dl = dst.arrayOffset() + dst.limit(); + int dp0 = dp; + int mark = sp; + boolean padding = false; + try { + while (sp < sl) { + int b = sa[sp++] & 0xff; + if ((b = base64[b]) < 0) { + if (b == -2) { // padding byte + padding = true; + break; + } + if (isMIME) // skip if for rfc2045 + continue; + else + throw new IllegalArgumentException( + "Illegal base64 character " + + Integer.toString(sa[sp - 1], 16)); + } + bits |= (b << shiftto); + shiftto -= 6; + if (shiftto < 0) { + if (dl < dp + 3) + return dp; + da[dp++] = (byte)(bits >> 16); + da[dp++] = (byte)(bits >> 8); + da[dp++] = (byte)(bits); + shiftto = 18; + bits = 0; + mark = sp; + } + } + if (shiftto == 6) { + if (dl - dp < 1) + return dp; + if (padding && (sp + 1 != sl || sa[sp++] != '=')) + throw new IllegalArgumentException( + "Input buffer has wrong 4-byte ending unit"); + da[dp++] = (byte)(bits >> 16); + mark = sp; + } else if (shiftto == 0) { + if (dl - dp < 2) + return dp; + if (padding && sp != sl) + throw new IllegalArgumentException( + "Input buffer has wrong 4-byte ending unit"); + da[dp++] = (byte)(bits >> 16); + da[dp++] = (byte)(bits >> 8); + mark = sp; + } else if (padding || shiftto != 18) { + throw new IllegalArgumentException( + "Last unit does not have enough valid bits"); + } + return dp - dp0; + } finally { + src.position(mark); + dst.position(dp); + } + } + + private int decodeBuffer(ByteBuffer src, ByteBuffer dst) { + int[] base64 = isURL ? fromBase64URL : fromBase64; + int bits = 0; + int shiftto = 18; // pos of first byte of 4-byte atom + int sp = src.position(); + int sl = src.limit(); + int dp = dst.position(); + int dl = dst.limit(); + int dp0 = dp; + int mark = sp; + boolean padding = false; + + try { + while (sp < sl) { + int b = src.get(sp++) & 0xff; + if ((b = base64[b]) < 0) { + if (b == -2) { // padding byte + padding = true; + break; + } + if (isMIME) // skip if for rfc2045 + continue; + else + throw new IllegalArgumentException( + "Illegal base64 character " + + Integer.toString(src.get(sp - 1), 16)); + } + bits |= (b << shiftto); + shiftto -= 6; + if (shiftto < 0) { + if (dl < dp + 3) + return dp; + dst.put(dp++, (byte)(bits >> 16)); + dst.put(dp++, (byte)(bits >> 8)); + dst.put(dp++, (byte)(bits)); + shiftto = 18; + bits = 0; + mark = sp; + } + } + if (shiftto == 6) { + if (dl - dp < 1) + return dp; + if (padding && (sp + 1 != sl || src.get(sp++) != '=')) + throw new IllegalArgumentException( + "Input buffer has wrong 4-byte ending unit"); + dst.put(dp++, (byte)(bits >> 16)); + mark = sp; + } else if (shiftto == 0) { + if (dl - dp < 2) + return dp; + if (padding && sp != sl) + throw new IllegalArgumentException( + "Input buffer has wrong 4-byte ending unit"); + dst.put(dp++, (byte)(bits >> 16)); + dst.put(dp++, (byte)(bits >> 8)); + mark = sp; + } else if (padding || shiftto != 18) { + throw new IllegalArgumentException( + "Last unit does not have enough valid bits"); + } + return dp - dp0; + } finally { + src.position(mark); + dst.position(dp); + } + } + + private int outLength(byte[] src, int sp, int sl) { + int[] base64 = isURL ? fromBase64URL : fromBase64; + int paddings = 0; + int len = sl - sp; + if (len == 0) + return 0; + if (len < 2) + throw new IllegalArgumentException( + "Input byte[] should at least have 2 bytes for base64 bytes"); + if (src[sl - 1] == '=') { + paddings++; + if (src[sl - 2] == '=') + paddings++; + } + if (isMIME) { + // scan all bytes to fill out all non-alphabet. a performance + // trade-off of pre-scan or Arrays.copyOf + int n = 0; + while (sp < sl) { + int b = src[sp++] & 0xff; + if (b == '=') + break; + if ((b = base64[b]) == -1) + n++; + } + len -= n; + } + if (paddings == 0 && (len & 0x3) != 0) + paddings = 4 - (len & 0x3); + return 3 * ((len + 3) / 4) - paddings; + } + + private int decode0(byte[] src, int sp, int sl, byte[] dst) { + int[] base64 = isURL ? fromBase64URL : fromBase64; + int dp = 0; + int bits = 0; + int shiftto = 18; // pos of first byte of 4-byte atom + boolean padding = false; + while (sp < sl) { + int b = src[sp++] & 0xff; + if ((b = base64[b]) < 0) { + if (b == -2) { // padding byte + padding = true; + break; + } + if (isMIME) // skip if for rfc2045 + continue; + else + throw new IllegalArgumentException( + "Illegal base64 character " + + Integer.toString(src[sp - 1], 16)); + } + bits |= (b << shiftto); + shiftto -= 6; + if (shiftto < 0) { + dst[dp++] = (byte)(bits >> 16); + dst[dp++] = (byte)(bits >> 8); + dst[dp++] = (byte)(bits); + shiftto = 18; + bits = 0; + } + } + // reach end of byte arry or hit padding '=' characters. + // if '=' presents, they must be the last one or two. + if (shiftto == 6) { // xx== + if (padding && (sp + 1 != sl || src[sp] != '=')) + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + dst[dp++] = (byte)(bits >> 16); + } else if (shiftto == 0) { // xxx= + if (padding && sp != sl) + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + dst[dp++] = (byte)(bits >> 16); + dst[dp++] = (byte)(bits >> 8); + } else if (padding || shiftto != 18) { + throw new IllegalArgumentException( + "last unit does not have enough bytes"); + } + return dp; + } + } + + /* + * An output stream for encoding bytes into the Base64. + */ + private static class EncOutputStream extends FilterOutputStream { + + private int leftover = 0; + private int b0, b1, b2; + 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]; + buf[0] = (byte)(b & 0xff); + write(buf, 0, 1); + } + + private void checkNewline() throws IOException { + if (linepos == linemax) { + out.write(newline); + linepos = 0; + } + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + if (closed) + throw new IOException("Stream is closed"); + if (off < 0 || len < 0 || off + len > b.length) + throw new ArrayIndexOutOfBoundsException(); + if (len == 0) + return; + if (leftover != 0) { + if (leftover == 1) { + b1 = b[off++] & 0xff; + len--; + if (len == 0) { + leftover++; + return; + } + } + b2 = b[off++] & 0xff; + len--; + checkNewline(); + out.write(base64[b0 >> 2]); + out.write(base64[(b0 << 4) & 0x3f | (b1 >> 4)]); + out.write(base64[(b1 << 2) & 0x3f | (b2 >> 6)]); + out.write(base64[b2 & 0x3f]); + linepos += 4; + } + int nBits24 = len / 3; + leftover = len - (nBits24 * 3); + while (nBits24-- > 0) { + checkNewline(); + int bits = (b[off++] & 0xff) << 16 | + (b[off++] & 0xff) << 8 | + (b[off++] & 0xff); + out.write(base64[(bits >>> 18) & 0x3f]); + out.write(base64[(bits >>> 12) & 0x3f]); + out.write(base64[(bits >>> 6) & 0x3f]); + out.write(base64[bits & 0x3f]); + linepos += 4; + } + if (leftover == 1) { + b0 = b[off++] & 0xff; + } else if (leftover == 2) { + b0 = b[off++] & 0xff; + b1 = b[off++] & 0xff; + } + } + + @Override + public void close() throws IOException { + if (!closed) { + closed = true; + if (leftover == 1) { + checkNewline(); + out.write(base64[b0 >> 2]); + out.write(base64[(b0 << 4) & 0x3f]); + 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]); + out.write('='); + } + leftover = 0; + out.close(); + } + } + } + + /* + * An input stream for decoding Base64 bytes + */ + private static class DecInputStream extends InputStream { + + private final InputStream is; + private final boolean isMIME; + private final int[] base64; // base64 -> byte mapping + private int bits = 0; // 24-bit buffer for decoding + private int nextin = 18; // next available "off" in "bits" for input; + // -> 18, 12, 6, 0 + private int nextout = -8; // next available "off" in "bits" for output; + // -> 8, 0, -8 (no byte for output) + private boolean eof = false; + private boolean closed = false; + + DecInputStream(InputStream is, int[] base64, boolean isMIME) { + this.is = is; + this.base64 = base64; + this.isMIME = isMIME; + } + + private byte[] sbBuf = new byte[1]; + + @Override + public int read() throws IOException { + return read(sbBuf, 0, 1) == -1 ? -1 : sbBuf[0] & 0xff; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (closed) + throw new IOException("Stream is closed"); + if (eof && nextout < 0) // eof and no leftover + return -1; + if (off < 0 || len < 0 || len > b.length - off) + throw new IndexOutOfBoundsException(); + int oldOff = off; + if (nextout >= 0) { // leftover output byte(s) in bits buf + do { + if (len == 0) + return off - oldOff; + b[off++] = (byte)(bits >> nextout); + len--; + nextout -= 8; + } while (nextout >= 0); + bits = 0; + } + while (len > 0) { + int v = is.read(); + if (v == -1) { + eof = true; + if (nextin != 18) + throw new IOException("Base64 stream has un-decoded dangling byte(s)."); + if (off == oldOff) + return -1; + else + return off - oldOff; + } + if (v == '=') { // padding byte(s) + if (nextin != 6 && nextin != 0) { + throw new IOException("Illegal base64 ending sequence:" + nextin); + } + b[off++] = (byte)(bits >> (16)); + len--; + if (nextin == 0) { // only one padding byte + if (len == 0) { // no enough output space + bits >>= 8; // shift to lowest byte + nextout = 0; + } else { + b[off++] = (byte) (bits >> 8); + } + } + eof = true; + break; + } + if ((v = base64[v]) == -1) { + if (isMIME) // skip if for rfc2045 + continue; + else + throw new IOException("Illegal base64 character " + + Integer.toString(v, 16)); + } + bits |= (v << nextin); + if (nextin == 0) { + nextin = 18; // clear for next + nextout = 16; + while (nextout >= 0) { + b[off++] = (byte)(bits >> nextout); + len--; + nextout -= 8; + if (len == 0 && nextout >= 0) { // don't clean "bits" + return off - oldOff; + } + } + bits = 0; + } else { + nextin -= 6; + } + } + return off - oldOff; + } + + @Override + public int available() throws IOException { + if (closed) + throw new IOException("Stream is closed"); + return is.available(); // TBD: + } + + @Override + public void close() throws IOException { + if (!closed) { + closed = true; + is.close(); + } + } + } +} diff -r 9ed95934188b -r be67058c3dc7 jdk/test/java/util/Base64/TestBase64.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/Base64/TestBase64.java Tue Nov 27 22:07:11 2012 -0800 @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test 4235519 + * @summary tests java.util.Base64 + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Base64; +import java.util.Random; + +public class TestBase64 { + + public static void main(String args[]) throws Throwable { + int numRuns = 10; + int numBytes = 200; + if (args.length > 1) { + numRuns = Integer.parseInt(args[0]); + numBytes = Integer.parseInt(args[1]); + } + + test(Base64.getEncoder(), Base64.getDecoder(), + numRuns, numBytes); + test(Base64.getUrlEncoder(), Base64.getUrlDecoder(), + numRuns, numBytes); + test(Base64.getMimeEncoder(), Base64.getMimeDecoder(), + numRuns, numBytes); + + Random rnd = new java.util.Random(); + byte[] nl_1 = new byte[] {'\n'}; + byte[] nl_2 = new byte[] {'\n', '\r'}; + byte[] nl_3 = new byte[] {'\n', '\r', '\n'}; + for (int i = 0; i < 10; i++) { + int len = rnd.nextInt(200) + 4; + test(Base64.getEncoder(len, nl_1), + Base64.getMimeDecoder(), + numRuns, numBytes); + test(Base64.getEncoder(len, nl_2), + Base64.getMimeDecoder(), + numRuns, numBytes); + test(Base64.getEncoder(len, nl_3), + Base64.getMimeDecoder(), + numRuns, numBytes); + } + + testNull(Base64.getEncoder()); + testNull(Base64.getUrlEncoder()); + testNull(Base64.getMimeEncoder()); + testNull(Base64.getEncoder(10, new byte[]{'\n'})); + testNull(Base64.getDecoder()); + testNull(Base64.getUrlDecoder()); + testNull(Base64.getMimeDecoder()); + checkNull(new Runnable() { public void run() { Base64.getEncoder(10, null); }}); + + testIOE(Base64.getEncoder()); + testIOE(Base64.getUrlEncoder()); + testIOE(Base64.getMimeEncoder()); + testIOE(Base64.getEncoder(10, new byte[]{'\n'})); + + byte[] src = new byte[1024]; + new Random().nextBytes(src); + final byte[] decoded = Base64.getEncoder().encode(src); + testIOE(Base64.getDecoder(), decoded); + testIOE(Base64.getMimeDecoder(), decoded); + testIOE(Base64.getUrlDecoder(), Base64.getUrlEncoder().encode(src)); + + // illegal line separator + checkIAE(new Runnable() { public void run() { Base64.getEncoder(10, new byte[]{'\r', 'N'}); }}); + + // illegal base64 character + decoded[2] = (byte)0xe0; + checkIAE(new Runnable() { + public void run() { Base64.getDecoder().decode(decoded); }}); + checkIAE(new Runnable() { + public void run() { Base64.getDecoder().decode(decoded, new byte[1024]); }}); + checkIAE(new Runnable() { public void run() { + Base64.getDecoder().decode(ByteBuffer.wrap(decoded)); }}); + checkIAE(new Runnable() { public void run() { + Base64.getDecoder().decode(ByteBuffer.wrap(decoded), ByteBuffer.allocate(1024)); }}); + checkIAE(new Runnable() { public void run() { + Base64.getDecoder().decode(ByteBuffer.wrap(decoded), ByteBuffer.allocateDirect(1024)); }}); + } + + private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder(); + + private static void test(Base64.Encoder enc, Base64.Decoder dec, + int numRuns, int numBytes) throws Throwable { + Random rnd = new java.util.Random(); + + enc.encode(new byte[0]); + dec.decode(new byte[0]); + + for (int i=0; i + * @summary tests java.util.Base64 + */ + +import java.io.BufferedReader; +import java.io.FileReader; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Base64; +import java.util.Base64.Decoder; +import java.util.Base64.Encoder; +import java.util.Objects; +import java.util.Random; + +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +public class TestBase64Golden { + + public static void main(String[] args) throws Exception { + test0(Base64Type.BASIC, Base64.getEncoder(), Base64.getDecoder(), + "plain.txt", "baseEncode.txt"); + + test0(Base64Type.URLSAFE, Base64.getUrlEncoder(), Base64.getUrlDecoder(), + "plain.txt", "urlEncode.txt"); + + test0(Base64Type.MIME, Base64.getMimeEncoder(), Base64.getMimeDecoder(), + "plain.txt", "mimeEncode.txt"); + test1(); + test2(); + } + + public static void test0(Base64Type type, Encoder encoder, Decoder decoder, + String srcFile, String encodedFile) throws Exception { + + String[] srcLns = Files.readAllLines(Paths.get(SRCDIR, srcFile), DEF_CHARSET) + .toArray(new String[0]); + String[] encodedLns = Files.readAllLines(Paths.get(SRCDIR, encodedFile), + DEF_CHARSET) + .toArray(new String[0]); + int lns = 0; + for (String srcStr : srcLns) { + String encodedStr = null; + if (type != Base64Type.MIME) { + encodedStr = encodedLns[lns++]; + } else { + while (lns < encodedLns.length) { + String s = encodedLns[lns++]; + if (s.length() == 0) + break; + if (encodedStr != null) { + encodedStr += DEFAULT_CRLF + s; + } else { + encodedStr = s; + } + } + if (encodedStr == null && srcStr.length() == 0) { + encodedStr = ""; + } + } + System.out.printf("%n src[%d]: %s%n", srcStr.length(), srcStr); + System.out.printf("encoded[%d]: %s%n", encodedStr.length(), encodedStr); + + byte[] srcArr = srcStr.getBytes(DEF_CHARSET); + byte[] encodedArr = encodedStr.getBytes(DEF_CHARSET); + + ByteBuffer srcBuf = ByteBuffer.wrap(srcArr); + ByteBuffer encodedBuf = ByteBuffer.wrap(encodedArr); + byte[] resArr = new byte[encodedArr.length]; + + // test int encode(byte[], byte[]) + int len = encoder.encode(srcArr, resArr); + assertEqual(len, encodedArr.length); + assertEqual(resArr, encodedArr); + + // test byte[] encode(byte[]) + resArr = encoder.encode(srcArr); + assertEqual(resArr, encodedArr); + + // test ByteBuffer encode(ByteBuffer) + int limit = srcBuf.limit(); + ByteBuffer resBuf = encoder.encode(srcBuf); + assertEqual(srcBuf.position(), limit); + assertEqual(srcBuf.limit(), limit); + assertEqual(resBuf, encodedBuf); + srcBuf.rewind(); // reset for next test + + // test encode(ByteBuffer, ByteBuffer, bytesOut) + resBuf.clear(); + len = encoder.encode(srcBuf, resBuf, 0); + assertEqual(len, encodedArr.length); + assertEqual(srcBuf.position(), limit); + assertEqual(srcBuf.limit(), limit); + assertEqual(resBuf.position(), len); + resBuf.flip(); + assertEqual(resBuf, encodedBuf); + srcBuf.rewind(); + + // test encode(ByteBuffer, ByteBuffer, bytesOut)[direct] + ByteBuffer resBuf_d = ByteBuffer.allocateDirect(encodedArr.length); + len = encoder.encode(srcBuf, resBuf_d, 0); + assertEqual(len, encodedArr.length); + assertEqual(srcBuf.position(), limit); + assertEqual(srcBuf.limit(), limit); + assertEqual(resBuf_d.position(), len); + resBuf_d.flip(); + assertEqual(resBuf_d, encodedBuf); + srcBuf.rewind(); + + // test String encodeToString(byte[]) + String resEncodeStr = encoder.encodeToString(srcArr); + assertEqual(resEncodeStr, encodedStr); + + // test int decode(byte[], byte[]) + resArr = new byte[srcArr.length]; + len = decoder.decode(encodedArr, resArr); + assertEqual(len, srcArr.length); + assertEqual(resArr, srcArr); + + // test byte[] decode(byte[]) + resArr = decoder.decode(encodedArr); + assertEqual(resArr, srcArr); + + // test ByteBuffer decode(ByteBuffer) + limit = encodedBuf.limit(); + resBuf = decoder.decode(encodedBuf); + assertEqual(encodedBuf.position(), limit); + assertEqual(encodedBuf.limit(), limit); + assertEqual(resBuf, srcBuf); + encodedBuf.rewind(); // reset for next test + + // test int decode(ByteBuffer, ByteBuffer) + resBuf.clear(); + len = decoder.decode(encodedBuf, resBuf); + assertEqual(len, srcArr.length); + assertEqual(encodedBuf.position(), limit); + assertEqual(encodedBuf.limit(), limit); + assertEqual(resBuf.position(), len); + resBuf.flip(); + assertEqual(resBuf, srcBuf); + encodedBuf.rewind(); // reset for next test + + // test int decode(ByteBuffer, ByteBuffer)[direct] + resBuf_d = ByteBuffer.allocateDirect(srcArr.length); + len = decoder.decode(encodedBuf, resBuf_d); + assertEqual(len, srcArr.length); + assertEqual(encodedBuf.position(), limit); + assertEqual(encodedBuf.limit(), limit); + assertEqual(resBuf_d.position(), len); + resBuf_d.flip(); + assertEqual(resBuf_d, srcBuf); + encodedBuf.rewind(); // reset for next test + + // test byte[] decode(String) + resArr = decoder.decode(encodedStr); + assertEqual(resArr, srcArr); + + // test compatible with sun.misc.Base64Encoder + if (type == Base64Type.MIME) { + sun.misc.BASE64Encoder miscEncoder = new BASE64Encoder(); + sun.misc.BASE64Decoder miscDecoder = new BASE64Decoder(); + resArr = decoder.decode(miscEncoder.encode(srcArr)); + assertEqual(resArr, srcArr); + + resArr = encoder.encode(miscDecoder.decodeBuffer(encodedStr)); + assertEqual(new String(resArr, DEF_CHARSET), encodedStr); + } + } + } + + private static void test1() throws Exception { + byte[] src = new byte[6]; + new Random().nextBytes(src); + + ByteBuffer srcBuf = ByteBuffer.allocate(10); + srcBuf.position(2); + srcBuf.mark(); + srcBuf.limit(8); + srcBuf.put(src); + srcBuf.reset(); + + ByteBuffer dstBuf = ByteBuffer.allocate((src.length + 2) / 3 * 4); + Base64.getEncoder().encode(srcBuf, dstBuf, 0); + dstBuf.rewind(); + byte[] dst = new byte[dstBuf.limit()]; + dstBuf.get(dst); + System.out.printf("%n src[%d]: %s%n", src.length, new String(src)); + System.out.printf("encoded[%d]: %s%n", dst.length, new String(dst)); + assertEqual(src, Base64.getDecoder().decode(dst)); + + dstBuf = ByteBuffer.allocateDirect((src.length + 2) / 3 * 4); + srcBuf.reset(); + Base64.getEncoder().encode(srcBuf, dstBuf, 0); + dstBuf.rewind(); + dst = new byte[dstBuf.limit()]; + dstBuf.get(dst); + assertEqual(src, Base64.getDecoder().decode(dst)); + } + + private static void test2() throws Exception { + byte[] src = new byte[] { + 46, -97, -35, -44, 127, -60, -39, -4, -112, 34, -57, 47, -14, 67, + 40, 18, 90, -59, 68, 112, 23, 121, -91, 94, 35, 49, 104, 17, 30, + -80, -104, -3, -53, 27, 38, -72, -47, 113, -52, 18, 5, -126 }; + Encoder encoder = Base64.getEncoder(49, new byte[] { 0x7e }); + byte[] encoded = encoder.encode(src); + Decoder decoder = Base64.getMimeDecoder(); + byte[] decoded = decoder.decode(encoded); + if (!Objects.deepEquals(src, decoded)) { + throw new RuntimeException(); + } + } + + // helper + enum Base64Type { + BASIC, URLSAFE, MIME + } + + private static final String SRCDIR = System.getProperty("test.src", "."); + private static final Charset DEF_CHARSET = StandardCharsets.US_ASCII; + private static final String DEF_EXCEPTION_MSG = + "Assertion failed! The result is not same as expected"; + private static final String DEFAULT_CRLF = "\r\n"; + + private static void assertEqual(Object result, Object expect) { + if (!Objects.deepEquals(result, expect)) { + String resultStr = result.toString(); + String expectStr = expect.toString(); + if (result instanceof byte[]) { + resultStr = new String((byte[]) result, DEF_CHARSET); + } + if (expect instanceof byte[]) { + expectStr = new String((byte[]) expect, DEF_CHARSET); + } + throw new RuntimeException(DEF_EXCEPTION_MSG + + " result: " + resultStr + " expected: " + expectStr); + } + } +} diff -r 9ed95934188b -r be67058c3dc7 jdk/test/java/util/Base64/baseEncode.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/Base64/baseEncode.txt Tue Nov 27 22:07:11 2012 -0800 @@ -0,0 +1,183 @@ +VGhpcyB0ZXN0IGRhdGEgaXMgcGFydCBvZiByZmMyMDQ1IHdoaWNoIGluY2x1ZGVzIGFsbCBjaGFyYWN0ZXJzIGF+eiBBflosIDB+OSBhbmQgYWxsIHN5bWJvbHMs +SXQgaXMgdXNlZCB0byB0ZXN0IGphdmEudXRpbC5CYXNlNjQuRW5jb2RlciwgYW5kIHdpbGwgYmUgZW5jb2RlZCBieSBvcmcuYXBhY2hlLmNvbW1vbnMuY29kZWMuYmluYXJ5LkJhc2U2NC5qYXZh +dG8gdGVzdCBqYXZhLnV0aWwuQmFzZTY0LkRlY29kZXI7 + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDFd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +ICAgVGhlc2UgZG9jdW1lbnRzIGFyZSByZXZpc2lvbnMgb2YgUkZDcyAxNTIxLCAxNTIyLCBhbmQgMTU5MCwgd2hpY2g= +ICAgdGhlbXNlbHZlcyB3ZXJlIHJldmlzaW9ucyBvZiBSRkNzIDEzNDEgYW5kIDEzNDIuICBBbiBhcHBlbmRpeCBpbiBSRkM= +ICAgMjA0OSBkZXNjcmliZXMgZGlmZmVyZW5jZXMgYW5kIGNoYW5nZXMgZnJvbSBwcmV2aW91cyB2ZXJzaW9ucy4= + +VGFibGUgb2YgQ29udGVudHM= + +ICAgMS4gSW50cm9kdWN0aW9uIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDM= +ICAgMi4gRGVmaW5pdGlvbnMsIENvbnZlbnRpb25zLCBhbmQgR2VuZXJpYyBCTkYgR3JhbW1hciAuLi4uICAgIDU= +ICAgMy4gTUlNRSBIZWFkZXIgRmllbGRzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg= +ICAgNC4gTUlNRS1WZXJzaW9uIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg= +ICAgNS4gQ29udGVudC1UeXBlIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMTA= +ICAgNi4gQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uICAgMTQ= +ICAgNy4gQ29udGVudC1JRCBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjY= +ICAgOC4gQ29udGVudC1EZXNjcmlwdGlvbiBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgOS4gQWRkaXRpb25hbCBNSU1FIEhlYWRlciBGaWVsZHMgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTAuIFN1bW1hcnkgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTEuIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTIuIEF1dGhvcnMnIEFkZHJlc3NlcyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjg= +ICAgQS4gQ29sbGVjdGVkIEdyYW1tYXIgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjk= + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDdd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +My4gIE1JTUUgSGVhZGVyIEZpZWxkcw== + +ICAgTUlNRSBkZWZpbmVzIGEgbnVtYmVyIG9mIG5ldyBSRkMgODIyIGhlYWRlciBmaWVsZHMgdGhhdCBhcmUgdXNlZCB0bw== +ICAgZGVzY3JpYmUgdGhlIGNvbnRlbnQgb2YgYSBNSU1FIGVudGl0eS4gIFRoZXNlIGhlYWRlciBmaWVsZHMgb2NjdXIgaW4= +ICAgYXQgbGVhc3QgdHdvIGNvbnRleHRzOg== + +ICAgICgxKSAgIEFzIHBhcnQgb2YgYSByZWd1bGFyIFJGQyA4MjIgbWVzc2FnZSBoZWFkZXIu + +ICAgICgyKSAgIEluIGEgTUlNRSBib2R5IHBhcnQgaGVhZGVyIHdpdGhpbiBhIG11bHRpcGFydA== +ICAgICAgICAgIGNvbnN0cnVjdC4= + +ICAgVGhlIGZvcm1hbCBkZWZpbml0aW9uIG9mIHRoZXNlIGhlYWRlciBmaWVsZHMgaXMgYXMgZm9sbG93czo= + +ICAgICBNSU1FLW1lc3NhZ2UtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHM= +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uIENSTEY= +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu + +ICAgICBNSU1FLXBhcnQtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== +ICAgICAgICAgICAgICAgICAgICAgICAgICBbIGZpZWxkcyBd +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IEFueSBmaWVsZCBub3QgYmVnaW5uaW5nIHdpdGg= +ICAgICAgICAgICAgICAgICAgICAgICAgICA7ICJjb250ZW50LSIgY2FuIGhhdmUgbm8gZGVmaW5lZA== +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IG1lYW5pbmcgYW5kIG1heSBiZSBpZ25vcmVkLg== +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu + +ICAgVGhlIHN5bnRheCBvZiB0aGUgdmFyaW91cyBzcGVjaWZpYyBNSU1FIGhlYWRlciBmaWVsZHMgd2lsbCBiZQ== +ICAgZGVzY3JpYmVkIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMu + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMTFd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +NS4xLiAgU3ludGF4IG9mIHRoZSBDb250ZW50LVR5cGUgSGVhZGVyIEZpZWxk + +ICAgSW4gdGhlIEF1Z21lbnRlZCBCTkYgbm90YXRpb24gb2YgUkZDIDgyMiwgYSBDb250ZW50LVR5cGUgaGVhZGVyIGZpZWxk +ICAgdmFsdWUgaXMgZGVmaW5lZCBhcyBmb2xsb3dzOg== + +ICAgICBjb250ZW50IDo9ICJDb250ZW50LVR5cGUiICI6IiB0eXBlICIvIiBzdWJ0eXBl +ICAgICAgICAgICAgICAgICooIjsiIHBhcmFtZXRlcik= +ICAgICAgICAgICAgICAgIDsgTWF0Y2hpbmcgb2YgbWVkaWEgdHlwZSBhbmQgc3VidHlwZQ== +ICAgICAgICAgICAgICAgIDsgaXMgQUxXQVlTIGNhc2UtaW5zZW5zaXRpdmUu + +ICAgICB0eXBlIDo9IGRpc2NyZXRlLXR5cGUgLyBjb21wb3NpdGUtdHlwZQ== + +ICAgICBkaXNjcmV0ZS10eXBlIDo9ICJ0ZXh0IiAvICJpbWFnZSIgLyAiYXVkaW8iIC8gInZpZGVvIiAv +ICAgICAgICAgICAgICAgICAgICAgICJhcHBsaWNhdGlvbiIgLyBleHRlbnNpb24tdG9rZW4= + +ICAgICBjb21wb3NpdGUtdHlwZSA6PSAibWVzc2FnZSIgLyAibXVsdGlwYXJ0IiAvIGV4dGVuc2lvbi10b2tlbg== + +ICAgICBleHRlbnNpb24tdG9rZW4gOj0gaWV0Zi10b2tlbiAvIHgtdG9rZW4= + +ICAgICBpZXRmLXRva2VuIDo9IDxBbiBleHRlbnNpb24gdG9rZW4gZGVmaW5lZCBieSBh +ICAgICAgICAgICAgICAgICAgICBzdGFuZGFyZHMtdHJhY2sgUkZDIGFuZCByZWdpc3RlcmVk +ICAgICAgICAgICAgICAgICAgICB3aXRoIElBTkEuPg== + +ICAgICB4LXRva2VuIDo9IDxUaGUgdHdvIGNoYXJhY3RlcnMgIlgtIiBvciAieC0iIGZvbGxvd2VkLCB3aXRo +ICAgICAgICAgICAgICAgICBubyBpbnRlcnZlbmluZyB3aGl0ZSBzcGFjZSwgYnkgYW55IHRva2VuPg== + +ICAgICBzdWJ0eXBlIDo9IGV4dGVuc2lvbi10b2tlbiAvIGlhbmEtdG9rZW4= + +ICAgICBpYW5hLXRva2VuIDo9IDxBIHB1YmxpY2x5LWRlZmluZWQgZXh0ZW5zaW9uIHRva2VuLiBUb2tlbnM= +ICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGZvcm0gbXVzdCBiZSByZWdpc3RlcmVkIHdpdGggSUFOQQ== +ICAgICAgICAgICAgICAgICAgICBhcyBzcGVjaWZpZWQgaW4gUkZDIDIwNDguPg== + +ICAgICBwYXJhbWV0ZXIgOj0gYXR0cmlidXRlICI9IiB2YWx1ZQ== + +ICAgICBhdHRyaWJ1dGUgOj0gdG9rZW4= +ICAgICAgICAgICAgICAgICAgOyBNYXRjaGluZyBvZiBhdHRyaWJ1dGVz +ICAgICAgICAgICAgICAgICAgOyBpcyBBTFdBWVMgY2FzZS1pbnNlbnNpdGl2ZS4= + +ICAgICB2YWx1ZSA6PSB0b2tlbiAvIHF1b3RlZC1zdHJpbmc= + +ICAgICB0b2tlbiA6PSAxKjxhbnkgKFVTLUFTQ0lJKSBDSEFSIGV4Y2VwdCBTUEFDRSwgQ1RMcyw= +ICAgICAgICAgICAgICAgICBvciB0c3BlY2lhbHM+ + +ICAgICB0c3BlY2lhbHMgOj0gICIoIiAvICIpIiAvICI8IiAvICI+IiAvICJAIiAv +ICAgICAgICAgICAgICAgICAgICIsIiAvICI7IiAvICI6IiAvICJcIiAvIDwiPg== +ICAgICAgICAgICAgICAgICAgICIvIiAvICJbIiAvICJdIiAvICI/IiAvICI9Ig== +ICAgICAgICAgICAgICAgICAgIDsgTXVzdCBiZSBpbiBxdW90ZWQtc3RyaW5nLA== +ICAgICAgICAgICAgICAgICAgIDsgdG8gdXNlIHdpdGhpbiBwYXJhbWV0ZXIgdmFsdWVz + +ICAgICBkZXNjcmlwdGlvbiA6PSAiQ29udGVudC1EZXNjcmlwdGlvbiIgIjoiICp0ZXh0 + +ICAgICBlbmNvZGluZyA6PSAiQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyIgIjoiIG1lY2hhbmlzbQ== + +ICAgICBlbnRpdHktaGVhZGVycyA6PSBbIGNvbnRlbnQgQ1JMRiBd +ICAgICAgICAgICAgICAgICAgICBbIGVuY29kaW5nIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICBbIGlkIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICBbIGRlc2NyaXB0aW9uIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICAqKCBNSU1FLWV4dGVuc2lvbi1maWVsZCBDUkxGICk= + +ICAgICBoZXgtb2N0ZXQgOj0gIj0iIDIoRElHSVQgLyAiQSIgLyAiQiIgLyAiQyIgLyAiRCIgLyAiRSIgLyAiRiIp +ICAgICAgICAgICAgICAgOyBPY3RldCBtdXN0IGJlIHVzZWQgZm9yIGNoYXJhY3RlcnMgPiAxMjcsID0s +ICAgICAgICAgICAgICAgOyBTUEFDRXMgb3IgVEFCcyBhdCB0aGUgZW5kcyBvZiBsaW5lcywgYW5kIGlz +ICAgICAgICAgICAgICAgOyByZWNvbW1lbmRlZCBmb3IgYW55IGNoYXJhY3RlciBub3QgbGlzdGVkIGlu +ICAgICAgICAgICAgICAgOyBSRkMgMjA0OSBhcyAibWFpbC1zYWZlIi4= + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +ICAgICAgICAgIG11c3QgYmUgdXNlZC4gIEFuIGVxdWFsIHNpZ24gYXMgdGhlIGxhc3QgY2hhcmFjdGVyIG9uIGE= +ICAgICAgICAgIGVuY29kZWQgbGluZSBpbmRpY2F0ZXMgc3VjaCBhIG5vbi1zaWduaWZpY2FudCAoInNvZnQiKQ== +ICAgICAgICAgIGxpbmUgYnJlYWsgaW4gdGhlIGVuY29kZWQgdGV4dC4= + +ICAgVGh1cyBpZiB0aGUgInJhdyIgZm9ybSBvZiB0aGUgbGluZSBpcyBhIHNpbmdsZSB1bmVuY29kZWQgbGluZSB0aGF0 +ICAgc2F5czo= + +ICAgICBOb3cncyB0aGUgdGltZSBmb3IgYWxsIGZvbGsgdG8gY29tZSB0byB0aGUgYWlkIG9mIHRoZWlyIGNvdW50cnku + +ICAgVGhpcyBjYW4gYmUgcmVwcmVzZW50ZWQsIGluIHRoZSBRdW90ZWQtUHJpbnRhYmxlIGVuY29kaW5nLCBhczo= + +ICAgICBOb3cncyB0aGUgdGltZSA9 +ICAgICBmb3IgYWxsIGZvbGsgdG8gY29tZT0= +ICAgICAgdG8gdGhlIGFpZCBvZiB0aGVpciBjb3VudHJ5Lg== + +ICAgU2luY2UgdGhlIGh5cGhlbiBjaGFyYWN0ZXIgKCItIikgbWF5IGJlIHJlcHJlc2VudGVkIGFzIGl0c2VsZiBpbiB0aGU= +ICAgUXVvdGVkLVByaW50YWJsZSBlbmNvZGluZywgY2FyZSBtdXN0IGJlIHRha2VuLCB3aGVuIGVuY2Fwc3VsYXRpbmcgYQ== +ICAgcXVvdGVkLXByaW50YWJsZSBlbmNvZGVkIGJvZHkgaW5zaWRlIG9uZSBvciBtb3JlIG11bHRpcGFydCBlbnRpdGllcyw= +ICAgdG8gZW5zdXJlIHRoYXQgdGhlIGJvdW5kYXJ5IGRlbGltaXRlciBkb2VzIG5vdCBhcHBlYXIgYW55d2hlcmUgaW4gdGhl +ICAgZW5jb2RlZCBib2R5LiAgKEEgZ29vZCBzdHJhdGVneSBpcyB0byBjaG9vc2UgYSBib3VuZGFyeSB0aGF0IGluY2x1ZGVz +ICAgYSBjaGFyYWN0ZXIgc2VxdWVuY2Ugc3VjaCBhcyAiPV8iIHdoaWNoIGNhbiBuZXZlciBhcHBlYXIgaW4gYQ== +ICAgcXVvdGVkLXByaW50YWJsZSBib2R5LiAgU2VlIHRoZSBkZWZpbml0aW9uIG9mIG11bHRpcGFydCBtZXNzYWdlcyBpbg== +ICAgUkZDIDIwNDYuKQ== + +ICAgICAhIiMkQFtcXV5ge3x9fiU= + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMjRd + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + + +ICAgICAgICAgICAgICAgICAgICBUYWJsZSAxOiBUaGUgQmFzZTY0IEFscGhhYmV0 + +ICAgICBWYWx1ZSBFbmNvZGluZyAgVmFsdWUgRW5jb2RpbmcgIFZhbHVlIEVuY29kaW5nICBWYWx1ZSBFbmNvZGluZw== +ICAgICAgICAgMCBBICAgICAgICAgICAgMTcgUiAgICAgICAgICAgIDM0IGkgICAgICAgICAgICA1MSB6 +ICAgICAgICAgMSBCICAgICAgICAgICAgMTggUyAgICAgICAgICAgIDM1IGogICAgICAgICAgICA1MiAw +ICAgICAgICAgMiBDICAgICAgICAgICAgMTkgVCAgICAgICAgICAgIDM2IGsgICAgICAgICAgICA1MyAx +ICAgICAgICAgMyBEICAgICAgICAgICAgMjAgVSAgICAgICAgICAgIDM3IGwgICAgICAgICAgICA1NCAy +ICAgICAgICAgNCBFICAgICAgICAgICAgMjEgViAgICAgICAgICAgIDM4IG0gICAgICAgICAgICA1NSAz +ICAgICAgICAgNSBGICAgICAgICAgICAgMjIgVyAgICAgICAgICAgIDM5IG4gICAgICAgICAgICA1NiA0 +ICAgICAgICAgNiBHICAgICAgICAgICAgMjMgWCAgICAgICAgICAgIDQwIG8gICAgICAgICAgICA1NyA1 +ICAgICAgICAgNyBIICAgICAgICAgICAgMjQgWSAgICAgICAgICAgIDQxIHAgICAgICAgICAgICA1OCA2 +ICAgICAgICAgOCBJICAgICAgICAgICAgMjUgWiAgICAgICAgICAgIDQyIHEgICAgICAgICAgICA1OSA3 +ICAgICAgICAgOSBKICAgICAgICAgICAgMjYgYSAgICAgICAgICAgIDQzIHIgICAgICAgICAgICA2MCA4 +ICAgICAgICAxMCBLICAgICAgICAgICAgMjcgYiAgICAgICAgICAgIDQ0IHMgICAgICAgICAgICA2MSA5 +ICAgICAgICAxMSBMICAgICAgICAgICAgMjggYyAgICAgICAgICAgIDQ1IHQgICAgICAgICAgICA2MiAr +ICAgICAgICAxMiBNICAgICAgICAgICAgMjkgZCAgICAgICAgICAgIDQ2IHUgICAgICAgICAgICA2MyAv +ICAgICAgICAxMyBOICAgICAgICAgICAgMzAgZSAgICAgICAgICAgIDQ3IHY= +ICAgICAgICAxNCBPICAgICAgICAgICAgMzEgZiAgICAgICAgICAgIDQ4IHcgICAgICAgICAocGFkKSA9 +ICAgICAgICAxNSBQICAgICAgICAgICAgMzIgZyAgICAgICAgICAgIDQ5IHg= +ICAgICAgICAxNiBRICAgICAgICAgICAgMzMgaCAgICAgICAgICAgIDUwIHk= diff -r 9ed95934188b -r be67058c3dc7 jdk/test/java/util/Base64/mimeEncode.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/Base64/mimeEncode.txt Tue Nov 27 22:07:11 2012 -0800 @@ -0,0 +1,391 @@ +VGhpcyB0ZXN0IGRhdGEgaXMgcGFydCBvZiByZmMyMDQ1IHdoaWNoIGluY2x1ZGVzIGFsbCBjaGFy +YWN0ZXJzIGF+eiBBflosIDB+OSBhbmQgYWxsIHN5bWJvbHMs + +SXQgaXMgdXNlZCB0byB0ZXN0IGphdmEudXRpbC5CYXNlNjQuRW5jb2RlciwgYW5kIHdpbGwgYmUg +ZW5jb2RlZCBieSBvcmcuYXBhY2hlLmNvbW1vbnMuY29kZWMuYmluYXJ5LkJhc2U2NC5qYXZh + +dG8gdGVzdCBqYXZhLnV0aWwuQmFzZTY0LkRlY29kZXI7 + + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg +ICAgICAgIFtQYWdlIDFd + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg +ICBOb3ZlbWJlciAxOTk2 + + +ICAgVGhlc2UgZG9jdW1lbnRzIGFyZSByZXZpc2lvbnMgb2YgUkZDcyAxNTIxLCAxNTIyLCBhbmQg +MTU5MCwgd2hpY2g= + +ICAgdGhlbXNlbHZlcyB3ZXJlIHJldmlzaW9ucyBvZiBSRkNzIDEzNDEgYW5kIDEzNDIuICBBbiBh +cHBlbmRpeCBpbiBSRkM= + +ICAgMjA0OSBkZXNjcmliZXMgZGlmZmVyZW5jZXMgYW5kIGNoYW5nZXMgZnJvbSBwcmV2aW91cyB2 +ZXJzaW9ucy4= + + +VGFibGUgb2YgQ29udGVudHM= + + +ICAgMS4gSW50cm9kdWN0aW9uIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgIDM= + +ICAgMi4gRGVmaW5pdGlvbnMsIENvbnZlbnRpb25zLCBhbmQgR2VuZXJpYyBCTkYgR3JhbW1hciAu +Li4uICAgIDU= + +ICAgMy4gTUlNRSBIZWFkZXIgRmllbGRzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgIDg= + +ICAgNC4gTUlNRS1WZXJzaW9uIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgIDg= + +ICAgNS4gQ29udGVudC1UeXBlIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMTA= + +ICAgNi4gQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4u +Li4uICAgMTQ= + +ICAgNy4gQ29udGVudC1JRCBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjY= + +ICAgOC4gQ29udGVudC1EZXNjcmlwdGlvbiBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjc= + +ICAgOS4gQWRkaXRpb25hbCBNSU1FIEhlYWRlciBGaWVsZHMgLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjc= + +ICAgMTAuIFN1bW1hcnkgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjc= + +ICAgMTEuIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjc= + +ICAgMTIuIEF1dGhvcnMnIEFkZHJlc3NlcyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjg= + +ICAgQS4gQ29sbGVjdGVkIEdyYW1tYXIgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjk= + + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg +ICAgICAgIFtQYWdlIDdd + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg +ICBOb3ZlbWJlciAxOTk2 + + +My4gIE1JTUUgSGVhZGVyIEZpZWxkcw== + + +ICAgTUlNRSBkZWZpbmVzIGEgbnVtYmVyIG9mIG5ldyBSRkMgODIyIGhlYWRlciBmaWVsZHMgdGhh +dCBhcmUgdXNlZCB0bw== + +ICAgZGVzY3JpYmUgdGhlIGNvbnRlbnQgb2YgYSBNSU1FIGVudGl0eS4gIFRoZXNlIGhlYWRlciBm +aWVsZHMgb2NjdXIgaW4= + +ICAgYXQgbGVhc3QgdHdvIGNvbnRleHRzOg== + + +ICAgICgxKSAgIEFzIHBhcnQgb2YgYSByZWd1bGFyIFJGQyA4MjIgbWVzc2FnZSBoZWFkZXIu + + +ICAgICgyKSAgIEluIGEgTUlNRSBib2R5IHBhcnQgaGVhZGVyIHdpdGhpbiBhIG11bHRpcGFydA== + +ICAgICAgICAgIGNvbnN0cnVjdC4= + + +ICAgVGhlIGZvcm1hbCBkZWZpbml0aW9uIG9mIHRoZXNlIGhlYWRlciBmaWVsZHMgaXMgYXMgZm9s +bG93czo= + + +ICAgICBNSU1FLW1lc3NhZ2UtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== + +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHM= + +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uIENSTEY= + +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy + +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G + +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9y +ZWQu + + +ICAgICBNSU1FLXBhcnQtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== + +ICAgICAgICAgICAgICAgICAgICAgICAgICBbIGZpZWxkcyBd + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IEFueSBmaWVsZCBub3QgYmVnaW5uaW5nIHdpdGg= + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7ICJjb250ZW50LSIgY2FuIGhhdmUgbm8gZGVmaW5l +ZA== + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IG1lYW5pbmcgYW5kIG1heSBiZSBpZ25vcmVkLg== + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu + + +ICAgVGhlIHN5bnRheCBvZiB0aGUgdmFyaW91cyBzcGVjaWZpYyBNSU1FIGhlYWRlciBmaWVsZHMg +d2lsbCBiZQ== + +ICAgZGVzY3JpYmVkIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMu + + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg +ICAgICAgW1BhZ2UgMTFd + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg +ICBOb3ZlbWJlciAxOTk2 + + +NS4xLiAgU3ludGF4IG9mIHRoZSBDb250ZW50LVR5cGUgSGVhZGVyIEZpZWxk + + +ICAgSW4gdGhlIEF1Z21lbnRlZCBCTkYgbm90YXRpb24gb2YgUkZDIDgyMiwgYSBDb250ZW50LVR5 +cGUgaGVhZGVyIGZpZWxk + +ICAgdmFsdWUgaXMgZGVmaW5lZCBhcyBmb2xsb3dzOg== + + +ICAgICBjb250ZW50IDo9ICJDb250ZW50LVR5cGUiICI6IiB0eXBlICIvIiBzdWJ0eXBl + +ICAgICAgICAgICAgICAgICooIjsiIHBhcmFtZXRlcik= + +ICAgICAgICAgICAgICAgIDsgTWF0Y2hpbmcgb2YgbWVkaWEgdHlwZSBhbmQgc3VidHlwZQ== + +ICAgICAgICAgICAgICAgIDsgaXMgQUxXQVlTIGNhc2UtaW5zZW5zaXRpdmUu + + +ICAgICB0eXBlIDo9IGRpc2NyZXRlLXR5cGUgLyBjb21wb3NpdGUtdHlwZQ== + + +ICAgICBkaXNjcmV0ZS10eXBlIDo9ICJ0ZXh0IiAvICJpbWFnZSIgLyAiYXVkaW8iIC8gInZpZGVv +IiAv + +ICAgICAgICAgICAgICAgICAgICAgICJhcHBsaWNhdGlvbiIgLyBleHRlbnNpb24tdG9rZW4= + + +ICAgICBjb21wb3NpdGUtdHlwZSA6PSAibWVzc2FnZSIgLyAibXVsdGlwYXJ0IiAvIGV4dGVuc2lv +bi10b2tlbg== + + +ICAgICBleHRlbnNpb24tdG9rZW4gOj0gaWV0Zi10b2tlbiAvIHgtdG9rZW4= + + +ICAgICBpZXRmLXRva2VuIDo9IDxBbiBleHRlbnNpb24gdG9rZW4gZGVmaW5lZCBieSBh + +ICAgICAgICAgICAgICAgICAgICBzdGFuZGFyZHMtdHJhY2sgUkZDIGFuZCByZWdpc3RlcmVk + +ICAgICAgICAgICAgICAgICAgICB3aXRoIElBTkEuPg== + + +ICAgICB4LXRva2VuIDo9IDxUaGUgdHdvIGNoYXJhY3RlcnMgIlgtIiBvciAieC0iIGZvbGxvd2Vk +LCB3aXRo + +ICAgICAgICAgICAgICAgICBubyBpbnRlcnZlbmluZyB3aGl0ZSBzcGFjZSwgYnkgYW55IHRva2Vu +Pg== + + +ICAgICBzdWJ0eXBlIDo9IGV4dGVuc2lvbi10b2tlbiAvIGlhbmEtdG9rZW4= + + +ICAgICBpYW5hLXRva2VuIDo9IDxBIHB1YmxpY2x5LWRlZmluZWQgZXh0ZW5zaW9uIHRva2VuLiBU +b2tlbnM= + +ICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGZvcm0gbXVzdCBiZSByZWdpc3RlcmVkIHdpdGgg +SUFOQQ== + +ICAgICAgICAgICAgICAgICAgICBhcyBzcGVjaWZpZWQgaW4gUkZDIDIwNDguPg== + + +ICAgICBwYXJhbWV0ZXIgOj0gYXR0cmlidXRlICI9IiB2YWx1ZQ== + + +ICAgICBhdHRyaWJ1dGUgOj0gdG9rZW4= + +ICAgICAgICAgICAgICAgICAgOyBNYXRjaGluZyBvZiBhdHRyaWJ1dGVz + +ICAgICAgICAgICAgICAgICAgOyBpcyBBTFdBWVMgY2FzZS1pbnNlbnNpdGl2ZS4= + + +ICAgICB2YWx1ZSA6PSB0b2tlbiAvIHF1b3RlZC1zdHJpbmc= + + +ICAgICB0b2tlbiA6PSAxKjxhbnkgKFVTLUFTQ0lJKSBDSEFSIGV4Y2VwdCBTUEFDRSwgQ1RMcyw= + +ICAgICAgICAgICAgICAgICBvciB0c3BlY2lhbHM+ + + +ICAgICB0c3BlY2lhbHMgOj0gICIoIiAvICIpIiAvICI8IiAvICI+IiAvICJAIiAv + +ICAgICAgICAgICAgICAgICAgICIsIiAvICI7IiAvICI6IiAvICJcIiAvIDwiPg== + +ICAgICAgICAgICAgICAgICAgICIvIiAvICJbIiAvICJdIiAvICI/IiAvICI9Ig== + +ICAgICAgICAgICAgICAgICAgIDsgTXVzdCBiZSBpbiBxdW90ZWQtc3RyaW5nLA== + +ICAgICAgICAgICAgICAgICAgIDsgdG8gdXNlIHdpdGhpbiBwYXJhbWV0ZXIgdmFsdWVz + + +ICAgICBkZXNjcmlwdGlvbiA6PSAiQ29udGVudC1EZXNjcmlwdGlvbiIgIjoiICp0ZXh0 + + +ICAgICBlbmNvZGluZyA6PSAiQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyIgIjoiIG1lY2hhbmlz +bQ== + + +ICAgICBlbnRpdHktaGVhZGVycyA6PSBbIGNvbnRlbnQgQ1JMRiBd + +ICAgICAgICAgICAgICAgICAgICBbIGVuY29kaW5nIENSTEYgXQ== + +ICAgICAgICAgICAgICAgICAgICBbIGlkIENSTEYgXQ== + +ICAgICAgICAgICAgICAgICAgICBbIGRlc2NyaXB0aW9uIENSTEYgXQ== + +ICAgICAgICAgICAgICAgICAgICAqKCBNSU1FLWV4dGVuc2lvbi1maWVsZCBDUkxGICk= + + +ICAgICBoZXgtb2N0ZXQgOj0gIj0iIDIoRElHSVQgLyAiQSIgLyAiQiIgLyAiQyIgLyAiRCIgLyAi +RSIgLyAiRiIp + +ICAgICAgICAgICAgICAgOyBPY3RldCBtdXN0IGJlIHVzZWQgZm9yIGNoYXJhY3RlcnMgPiAxMjcs +ID0s + +ICAgICAgICAgICAgICAgOyBTUEFDRXMgb3IgVEFCcyBhdCB0aGUgZW5kcyBvZiBsaW5lcywgYW5k +IGlz + +ICAgICAgICAgICAgICAgOyByZWNvbW1lbmRlZCBmb3IgYW55IGNoYXJhY3RlciBub3QgbGlzdGVk +IGlu + +ICAgICAgICAgICAgICAgOyBSRkMgMjA0OSBhcyAibWFpbC1zYWZlIi4= + + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg +ICBOb3ZlbWJlciAxOTk2 + + +ICAgICAgICAgIG11c3QgYmUgdXNlZC4gIEFuIGVxdWFsIHNpZ24gYXMgdGhlIGxhc3QgY2hhcmFj +dGVyIG9uIGE= + +ICAgICAgICAgIGVuY29kZWQgbGluZSBpbmRpY2F0ZXMgc3VjaCBhIG5vbi1zaWduaWZpY2FudCAo +InNvZnQiKQ== + +ICAgICAgICAgIGxpbmUgYnJlYWsgaW4gdGhlIGVuY29kZWQgdGV4dC4= + + +ICAgVGh1cyBpZiB0aGUgInJhdyIgZm9ybSBvZiB0aGUgbGluZSBpcyBhIHNpbmdsZSB1bmVuY29k +ZWQgbGluZSB0aGF0 + +ICAgc2F5czo= + + +ICAgICBOb3cncyB0aGUgdGltZSBmb3IgYWxsIGZvbGsgdG8gY29tZSB0byB0aGUgYWlkIG9mIHRo +ZWlyIGNvdW50cnku + + +ICAgVGhpcyBjYW4gYmUgcmVwcmVzZW50ZWQsIGluIHRoZSBRdW90ZWQtUHJpbnRhYmxlIGVuY29k +aW5nLCBhczo= + + +ICAgICBOb3cncyB0aGUgdGltZSA9 + +ICAgICBmb3IgYWxsIGZvbGsgdG8gY29tZT0= + +ICAgICAgdG8gdGhlIGFpZCBvZiB0aGVpciBjb3VudHJ5Lg== + + +ICAgU2luY2UgdGhlIGh5cGhlbiBjaGFyYWN0ZXIgKCItIikgbWF5IGJlIHJlcHJlc2VudGVkIGFz +IGl0c2VsZiBpbiB0aGU= + +ICAgUXVvdGVkLVByaW50YWJsZSBlbmNvZGluZywgY2FyZSBtdXN0IGJlIHRha2VuLCB3aGVuIGVu +Y2Fwc3VsYXRpbmcgYQ== + +ICAgcXVvdGVkLXByaW50YWJsZSBlbmNvZGVkIGJvZHkgaW5zaWRlIG9uZSBvciBtb3JlIG11bHRp +cGFydCBlbnRpdGllcyw= + +ICAgdG8gZW5zdXJlIHRoYXQgdGhlIGJvdW5kYXJ5IGRlbGltaXRlciBkb2VzIG5vdCBhcHBlYXIg +YW55d2hlcmUgaW4gdGhl + +ICAgZW5jb2RlZCBib2R5LiAgKEEgZ29vZCBzdHJhdGVneSBpcyB0byBjaG9vc2UgYSBib3VuZGFy +eSB0aGF0IGluY2x1ZGVz + +ICAgYSBjaGFyYWN0ZXIgc2VxdWVuY2Ugc3VjaCBhcyAiPV8iIHdoaWNoIGNhbiBuZXZlciBhcHBl +YXIgaW4gYQ== + +ICAgcXVvdGVkLXByaW50YWJsZSBib2R5LiAgU2VlIHRoZSBkZWZpbml0aW9uIG9mIG11bHRpcGFy +dCBtZXNzYWdlcyBpbg== + +ICAgUkZDIDIwNDYuKQ== + + +ICAgICAhIiMkQFtcXV5ge3x9fiU= + + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg +ICAgICAgW1BhZ2UgMjRd + + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg +ICBOb3ZlbWJlciAxOTk2 + + + +ICAgICAgICAgICAgICAgICAgICBUYWJsZSAxOiBUaGUgQmFzZTY0IEFscGhhYmV0 + + +ICAgICBWYWx1ZSBFbmNvZGluZyAgVmFsdWUgRW5jb2RpbmcgIFZhbHVlIEVuY29kaW5nICBWYWx1 +ZSBFbmNvZGluZw== + +ICAgICAgICAgMCBBICAgICAgICAgICAgMTcgUiAgICAgICAgICAgIDM0IGkgICAgICAgICAgICA1 +MSB6 + +ICAgICAgICAgMSBCICAgICAgICAgICAgMTggUyAgICAgICAgICAgIDM1IGogICAgICAgICAgICA1 +MiAw + +ICAgICAgICAgMiBDICAgICAgICAgICAgMTkgVCAgICAgICAgICAgIDM2IGsgICAgICAgICAgICA1 +MyAx + +ICAgICAgICAgMyBEICAgICAgICAgICAgMjAgVSAgICAgICAgICAgIDM3IGwgICAgICAgICAgICA1 +NCAy + +ICAgICAgICAgNCBFICAgICAgICAgICAgMjEgViAgICAgICAgICAgIDM4IG0gICAgICAgICAgICA1 +NSAz + +ICAgICAgICAgNSBGICAgICAgICAgICAgMjIgVyAgICAgICAgICAgIDM5IG4gICAgICAgICAgICA1 +NiA0 + +ICAgICAgICAgNiBHICAgICAgICAgICAgMjMgWCAgICAgICAgICAgIDQwIG8gICAgICAgICAgICA1 +NyA1 + +ICAgICAgICAgNyBIICAgICAgICAgICAgMjQgWSAgICAgICAgICAgIDQxIHAgICAgICAgICAgICA1 +OCA2 + +ICAgICAgICAgOCBJICAgICAgICAgICAgMjUgWiAgICAgICAgICAgIDQyIHEgICAgICAgICAgICA1 +OSA3 + +ICAgICAgICAgOSBKICAgICAgICAgICAgMjYgYSAgICAgICAgICAgIDQzIHIgICAgICAgICAgICA2 +MCA4 + +ICAgICAgICAxMCBLICAgICAgICAgICAgMjcgYiAgICAgICAgICAgIDQ0IHMgICAgICAgICAgICA2 +MSA5 + +ICAgICAgICAxMSBMICAgICAgICAgICAgMjggYyAgICAgICAgICAgIDQ1IHQgICAgICAgICAgICA2 +MiAr + +ICAgICAgICAxMiBNICAgICAgICAgICAgMjkgZCAgICAgICAgICAgIDQ2IHUgICAgICAgICAgICA2 +MyAv + +ICAgICAgICAxMyBOICAgICAgICAgICAgMzAgZSAgICAgICAgICAgIDQ3IHY= + +ICAgICAgICAxNCBPICAgICAgICAgICAgMzEgZiAgICAgICAgICAgIDQ4IHcgICAgICAgICAocGFk +KSA9 + +ICAgICAgICAxNSBQICAgICAgICAgICAgMzIgZyAgICAgICAgICAgIDQ5IHg= + +ICAgICAgICAxNiBRICAgICAgICAgICAgMzMgaCAgICAgICAgICAgIDUwIHk= + diff -r 9ed95934188b -r be67058c3dc7 jdk/test/java/util/Base64/plain.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/Base64/plain.txt Tue Nov 27 22:07:11 2012 -0800 @@ -0,0 +1,183 @@ +This test data is part of rfc2045 which includes all characters a~z A~Z, 0~9 and all symbols, +It is used to test java.util.Base64.Encoder, and will be encoded by org.apache.commons.codec.binary.Base64.java +to test java.util.Base64.Decoder; + +Freed & Borenstein Standards Track [Page 1] +RFC 2045 Internet Message Bodies November 1996 + + These documents are revisions of RFCs 1521, 1522, and 1590, which + themselves were revisions of RFCs 1341 and 1342. An appendix in RFC + 2049 describes differences and changes from previous versions. + +Table of Contents + + 1. Introduction ......................................... 3 + 2. Definitions, Conventions, and Generic BNF Grammar .... 5 + 3. MIME Header Fields ................................... 8 + 4. MIME-Version Header Field ............................ 8 + 5. Content-Type Header Field ............................ 10 + 6. Content-Transfer-Encoding Header Field ............... 14 + 7. Content-ID Header Field .............................. 26 + 8. Content-Description Header Field ..................... 27 + 9. Additional MIME Header Fields ........................ 27 + 10. Summary ............................................. 27 + 11. Security Considerations ............................. 27 + 12. Authors' Addresses .................................. 28 + A. Collected Grammar .................................... 29 + +Freed & Borenstein Standards Track [Page 7] +RFC 2045 Internet Message Bodies November 1996 + +3. MIME Header Fields + + MIME defines a number of new RFC 822 header fields that are used to + describe the content of a MIME entity. These header fields occur in + at least two contexts: + + (1) As part of a regular RFC 822 message header. + + (2) In a MIME body part header within a multipart + construct. + + The formal definition of these header fields is as follows: + + MIME-message-headers := entity-headers + fields + version CRLF + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. + + MIME-part-headers := entity-headers + [ fields ] + ; Any field not beginning with + ; "content-" can have no defined + ; meaning and may be ignored. + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. + + The syntax of the various specific MIME header fields will be + described in the following sections. + +Freed & Borenstein Standards Track [Page 11] +RFC 2045 Internet Message Bodies November 1996 + +5.1. Syntax of the Content-Type Header Field + + In the Augmented BNF notation of RFC 822, a Content-Type header field + value is defined as follows: + + content := "Content-Type" ":" type "/" subtype + *(";" parameter) + ; Matching of media type and subtype + ; is ALWAYS case-insensitive. + + type := discrete-type / composite-type + + discrete-type := "text" / "image" / "audio" / "video" / + "application" / extension-token + + composite-type := "message" / "multipart" / extension-token + + extension-token := ietf-token / x-token + + ietf-token := + + x-token := + + subtype := extension-token / iana-token + + iana-token := + + parameter := attribute "=" value + + attribute := token + ; Matching of attributes + ; is ALWAYS case-insensitive. + + value := token / quoted-string + + token := 1* + + tspecials := "(" / ")" / "<" / ">" / "@" / + "," / ";" / ":" / "\" / <"> + "/" / "[" / "]" / "?" / "=" + ; Must be in quoted-string, + ; to use within parameter values + + description := "Content-Description" ":" *text + + encoding := "Content-Transfer-Encoding" ":" mechanism + + entity-headers := [ content CRLF ] + [ encoding CRLF ] + [ id CRLF ] + [ description CRLF ] + *( MIME-extension-field CRLF ) + + hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F") + ; Octet must be used for characters > 127, =, + ; SPACEs or TABs at the ends of lines, and is + ; recommended for any character not listed in + ; RFC 2049 as "mail-safe". + +RFC 2045 Internet Message Bodies November 1996 + + must be used. An equal sign as the last character on a + encoded line indicates such a non-significant ("soft") + line break in the encoded text. + + Thus if the "raw" form of the line is a single unencoded line that + says: + + Now's the time for all folk to come to the aid of their country. + + This can be represented, in the Quoted-Printable encoding, as: + + Now's the time = + for all folk to come= + to the aid of their country. + + Since the hyphen character ("-") may be represented as itself in the + Quoted-Printable encoding, care must be taken, when encapsulating a + quoted-printable encoded body inside one or more multipart entities, + to ensure that the boundary delimiter does not appear anywhere in the + encoded body. (A good strategy is to choose a boundary that includes + a character sequence such as "=_" which can never appear in a + quoted-printable body. See the definition of multipart messages in + RFC 2046.) + + !"#$@[\]^`{|}~% + +Freed & Borenstein Standards Track [Page 24] + +RFC 2045 Internet Message Bodies November 1996 + + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y diff -r 9ed95934188b -r be67058c3dc7 jdk/test/java/util/Base64/urlEncode.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/Base64/urlEncode.txt Tue Nov 27 22:07:11 2012 -0800 @@ -0,0 +1,183 @@ +VGhpcyB0ZXN0IGRhdGEgaXMgcGFydCBvZiByZmMyMDQ1IHdoaWNoIGluY2x1ZGVzIGFsbCBjaGFyYWN0ZXJzIGF-eiBBflosIDB-OSBhbmQgYWxsIHN5bWJvbHMs +SXQgaXMgdXNlZCB0byB0ZXN0IGphdmEudXRpbC5CYXNlNjQuRW5jb2RlciwgYW5kIHdpbGwgYmUgZW5jb2RlZCBieSBvcmcuYXBhY2hlLmNvbW1vbnMuY29kZWMuYmluYXJ5LkJhc2U2NC5qYXZh +dG8gdGVzdCBqYXZhLnV0aWwuQmFzZTY0LkRlY29kZXI7 + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDFd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +ICAgVGhlc2UgZG9jdW1lbnRzIGFyZSByZXZpc2lvbnMgb2YgUkZDcyAxNTIxLCAxNTIyLCBhbmQgMTU5MCwgd2hpY2g= +ICAgdGhlbXNlbHZlcyB3ZXJlIHJldmlzaW9ucyBvZiBSRkNzIDEzNDEgYW5kIDEzNDIuICBBbiBhcHBlbmRpeCBpbiBSRkM= +ICAgMjA0OSBkZXNjcmliZXMgZGlmZmVyZW5jZXMgYW5kIGNoYW5nZXMgZnJvbSBwcmV2aW91cyB2ZXJzaW9ucy4= + +VGFibGUgb2YgQ29udGVudHM= + +ICAgMS4gSW50cm9kdWN0aW9uIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDM= +ICAgMi4gRGVmaW5pdGlvbnMsIENvbnZlbnRpb25zLCBhbmQgR2VuZXJpYyBCTkYgR3JhbW1hciAuLi4uICAgIDU= +ICAgMy4gTUlNRSBIZWFkZXIgRmllbGRzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg= +ICAgNC4gTUlNRS1WZXJzaW9uIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg= +ICAgNS4gQ29udGVudC1UeXBlIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMTA= +ICAgNi4gQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uICAgMTQ= +ICAgNy4gQ29udGVudC1JRCBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjY= +ICAgOC4gQ29udGVudC1EZXNjcmlwdGlvbiBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgOS4gQWRkaXRpb25hbCBNSU1FIEhlYWRlciBGaWVsZHMgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTAuIFN1bW1hcnkgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTEuIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTIuIEF1dGhvcnMnIEFkZHJlc3NlcyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjg= +ICAgQS4gQ29sbGVjdGVkIEdyYW1tYXIgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjk= + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDdd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +My4gIE1JTUUgSGVhZGVyIEZpZWxkcw== + +ICAgTUlNRSBkZWZpbmVzIGEgbnVtYmVyIG9mIG5ldyBSRkMgODIyIGhlYWRlciBmaWVsZHMgdGhhdCBhcmUgdXNlZCB0bw== +ICAgZGVzY3JpYmUgdGhlIGNvbnRlbnQgb2YgYSBNSU1FIGVudGl0eS4gIFRoZXNlIGhlYWRlciBmaWVsZHMgb2NjdXIgaW4= +ICAgYXQgbGVhc3QgdHdvIGNvbnRleHRzOg== + +ICAgICgxKSAgIEFzIHBhcnQgb2YgYSByZWd1bGFyIFJGQyA4MjIgbWVzc2FnZSBoZWFkZXIu + +ICAgICgyKSAgIEluIGEgTUlNRSBib2R5IHBhcnQgaGVhZGVyIHdpdGhpbiBhIG11bHRpcGFydA== +ICAgICAgICAgIGNvbnN0cnVjdC4= + +ICAgVGhlIGZvcm1hbCBkZWZpbml0aW9uIG9mIHRoZXNlIGhlYWRlciBmaWVsZHMgaXMgYXMgZm9sbG93czo= + +ICAgICBNSU1FLW1lc3NhZ2UtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHM= +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uIENSTEY= +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu + +ICAgICBNSU1FLXBhcnQtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== +ICAgICAgICAgICAgICAgICAgICAgICAgICBbIGZpZWxkcyBd +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IEFueSBmaWVsZCBub3QgYmVnaW5uaW5nIHdpdGg= +ICAgICAgICAgICAgICAgICAgICAgICAgICA7ICJjb250ZW50LSIgY2FuIGhhdmUgbm8gZGVmaW5lZA== +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IG1lYW5pbmcgYW5kIG1heSBiZSBpZ25vcmVkLg== +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu + +ICAgVGhlIHN5bnRheCBvZiB0aGUgdmFyaW91cyBzcGVjaWZpYyBNSU1FIGhlYWRlciBmaWVsZHMgd2lsbCBiZQ== +ICAgZGVzY3JpYmVkIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMu + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMTFd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +NS4xLiAgU3ludGF4IG9mIHRoZSBDb250ZW50LVR5cGUgSGVhZGVyIEZpZWxk + +ICAgSW4gdGhlIEF1Z21lbnRlZCBCTkYgbm90YXRpb24gb2YgUkZDIDgyMiwgYSBDb250ZW50LVR5cGUgaGVhZGVyIGZpZWxk +ICAgdmFsdWUgaXMgZGVmaW5lZCBhcyBmb2xsb3dzOg== + +ICAgICBjb250ZW50IDo9ICJDb250ZW50LVR5cGUiICI6IiB0eXBlICIvIiBzdWJ0eXBl +ICAgICAgICAgICAgICAgICooIjsiIHBhcmFtZXRlcik= +ICAgICAgICAgICAgICAgIDsgTWF0Y2hpbmcgb2YgbWVkaWEgdHlwZSBhbmQgc3VidHlwZQ== +ICAgICAgICAgICAgICAgIDsgaXMgQUxXQVlTIGNhc2UtaW5zZW5zaXRpdmUu + +ICAgICB0eXBlIDo9IGRpc2NyZXRlLXR5cGUgLyBjb21wb3NpdGUtdHlwZQ== + +ICAgICBkaXNjcmV0ZS10eXBlIDo9ICJ0ZXh0IiAvICJpbWFnZSIgLyAiYXVkaW8iIC8gInZpZGVvIiAv +ICAgICAgICAgICAgICAgICAgICAgICJhcHBsaWNhdGlvbiIgLyBleHRlbnNpb24tdG9rZW4= + +ICAgICBjb21wb3NpdGUtdHlwZSA6PSAibWVzc2FnZSIgLyAibXVsdGlwYXJ0IiAvIGV4dGVuc2lvbi10b2tlbg== + +ICAgICBleHRlbnNpb24tdG9rZW4gOj0gaWV0Zi10b2tlbiAvIHgtdG9rZW4= + +ICAgICBpZXRmLXRva2VuIDo9IDxBbiBleHRlbnNpb24gdG9rZW4gZGVmaW5lZCBieSBh +ICAgICAgICAgICAgICAgICAgICBzdGFuZGFyZHMtdHJhY2sgUkZDIGFuZCByZWdpc3RlcmVk +ICAgICAgICAgICAgICAgICAgICB3aXRoIElBTkEuPg== + +ICAgICB4LXRva2VuIDo9IDxUaGUgdHdvIGNoYXJhY3RlcnMgIlgtIiBvciAieC0iIGZvbGxvd2VkLCB3aXRo +ICAgICAgICAgICAgICAgICBubyBpbnRlcnZlbmluZyB3aGl0ZSBzcGFjZSwgYnkgYW55IHRva2VuPg== + +ICAgICBzdWJ0eXBlIDo9IGV4dGVuc2lvbi10b2tlbiAvIGlhbmEtdG9rZW4= + +ICAgICBpYW5hLXRva2VuIDo9IDxBIHB1YmxpY2x5LWRlZmluZWQgZXh0ZW5zaW9uIHRva2VuLiBUb2tlbnM= +ICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGZvcm0gbXVzdCBiZSByZWdpc3RlcmVkIHdpdGggSUFOQQ== +ICAgICAgICAgICAgICAgICAgICBhcyBzcGVjaWZpZWQgaW4gUkZDIDIwNDguPg== + +ICAgICBwYXJhbWV0ZXIgOj0gYXR0cmlidXRlICI9IiB2YWx1ZQ== + +ICAgICBhdHRyaWJ1dGUgOj0gdG9rZW4= +ICAgICAgICAgICAgICAgICAgOyBNYXRjaGluZyBvZiBhdHRyaWJ1dGVz +ICAgICAgICAgICAgICAgICAgOyBpcyBBTFdBWVMgY2FzZS1pbnNlbnNpdGl2ZS4= + +ICAgICB2YWx1ZSA6PSB0b2tlbiAvIHF1b3RlZC1zdHJpbmc= + +ICAgICB0b2tlbiA6PSAxKjxhbnkgKFVTLUFTQ0lJKSBDSEFSIGV4Y2VwdCBTUEFDRSwgQ1RMcyw= +ICAgICAgICAgICAgICAgICBvciB0c3BlY2lhbHM- + +ICAgICB0c3BlY2lhbHMgOj0gICIoIiAvICIpIiAvICI8IiAvICI-IiAvICJAIiAv +ICAgICAgICAgICAgICAgICAgICIsIiAvICI7IiAvICI6IiAvICJcIiAvIDwiPg== +ICAgICAgICAgICAgICAgICAgICIvIiAvICJbIiAvICJdIiAvICI_IiAvICI9Ig== +ICAgICAgICAgICAgICAgICAgIDsgTXVzdCBiZSBpbiBxdW90ZWQtc3RyaW5nLA== +ICAgICAgICAgICAgICAgICAgIDsgdG8gdXNlIHdpdGhpbiBwYXJhbWV0ZXIgdmFsdWVz + +ICAgICBkZXNjcmlwdGlvbiA6PSAiQ29udGVudC1EZXNjcmlwdGlvbiIgIjoiICp0ZXh0 + +ICAgICBlbmNvZGluZyA6PSAiQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyIgIjoiIG1lY2hhbmlzbQ== + +ICAgICBlbnRpdHktaGVhZGVycyA6PSBbIGNvbnRlbnQgQ1JMRiBd +ICAgICAgICAgICAgICAgICAgICBbIGVuY29kaW5nIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICBbIGlkIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICBbIGRlc2NyaXB0aW9uIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICAqKCBNSU1FLWV4dGVuc2lvbi1maWVsZCBDUkxGICk= + +ICAgICBoZXgtb2N0ZXQgOj0gIj0iIDIoRElHSVQgLyAiQSIgLyAiQiIgLyAiQyIgLyAiRCIgLyAiRSIgLyAiRiIp +ICAgICAgICAgICAgICAgOyBPY3RldCBtdXN0IGJlIHVzZWQgZm9yIGNoYXJhY3RlcnMgPiAxMjcsID0s +ICAgICAgICAgICAgICAgOyBTUEFDRXMgb3IgVEFCcyBhdCB0aGUgZW5kcyBvZiBsaW5lcywgYW5kIGlz +ICAgICAgICAgICAgICAgOyByZWNvbW1lbmRlZCBmb3IgYW55IGNoYXJhY3RlciBub3QgbGlzdGVkIGlu +ICAgICAgICAgICAgICAgOyBSRkMgMjA0OSBhcyAibWFpbC1zYWZlIi4= + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +ICAgICAgICAgIG11c3QgYmUgdXNlZC4gIEFuIGVxdWFsIHNpZ24gYXMgdGhlIGxhc3QgY2hhcmFjdGVyIG9uIGE= +ICAgICAgICAgIGVuY29kZWQgbGluZSBpbmRpY2F0ZXMgc3VjaCBhIG5vbi1zaWduaWZpY2FudCAoInNvZnQiKQ== +ICAgICAgICAgIGxpbmUgYnJlYWsgaW4gdGhlIGVuY29kZWQgdGV4dC4= + +ICAgVGh1cyBpZiB0aGUgInJhdyIgZm9ybSBvZiB0aGUgbGluZSBpcyBhIHNpbmdsZSB1bmVuY29kZWQgbGluZSB0aGF0 +ICAgc2F5czo= + +ICAgICBOb3cncyB0aGUgdGltZSBmb3IgYWxsIGZvbGsgdG8gY29tZSB0byB0aGUgYWlkIG9mIHRoZWlyIGNvdW50cnku + +ICAgVGhpcyBjYW4gYmUgcmVwcmVzZW50ZWQsIGluIHRoZSBRdW90ZWQtUHJpbnRhYmxlIGVuY29kaW5nLCBhczo= + +ICAgICBOb3cncyB0aGUgdGltZSA9 +ICAgICBmb3IgYWxsIGZvbGsgdG8gY29tZT0= +ICAgICAgdG8gdGhlIGFpZCBvZiB0aGVpciBjb3VudHJ5Lg== + +ICAgU2luY2UgdGhlIGh5cGhlbiBjaGFyYWN0ZXIgKCItIikgbWF5IGJlIHJlcHJlc2VudGVkIGFzIGl0c2VsZiBpbiB0aGU= +ICAgUXVvdGVkLVByaW50YWJsZSBlbmNvZGluZywgY2FyZSBtdXN0IGJlIHRha2VuLCB3aGVuIGVuY2Fwc3VsYXRpbmcgYQ== +ICAgcXVvdGVkLXByaW50YWJsZSBlbmNvZGVkIGJvZHkgaW5zaWRlIG9uZSBvciBtb3JlIG11bHRpcGFydCBlbnRpdGllcyw= +ICAgdG8gZW5zdXJlIHRoYXQgdGhlIGJvdW5kYXJ5IGRlbGltaXRlciBkb2VzIG5vdCBhcHBlYXIgYW55d2hlcmUgaW4gdGhl +ICAgZW5jb2RlZCBib2R5LiAgKEEgZ29vZCBzdHJhdGVneSBpcyB0byBjaG9vc2UgYSBib3VuZGFyeSB0aGF0IGluY2x1ZGVz +ICAgYSBjaGFyYWN0ZXIgc2VxdWVuY2Ugc3VjaCBhcyAiPV8iIHdoaWNoIGNhbiBuZXZlciBhcHBlYXIgaW4gYQ== +ICAgcXVvdGVkLXByaW50YWJsZSBib2R5LiAgU2VlIHRoZSBkZWZpbml0aW9uIG9mIG11bHRpcGFydCBtZXNzYWdlcyBpbg== +ICAgUkZDIDIwNDYuKQ== + +ICAgICAhIiMkQFtcXV5ge3x9fiU= + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMjRd + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + + +ICAgICAgICAgICAgICAgICAgICBUYWJsZSAxOiBUaGUgQmFzZTY0IEFscGhhYmV0 + +ICAgICBWYWx1ZSBFbmNvZGluZyAgVmFsdWUgRW5jb2RpbmcgIFZhbHVlIEVuY29kaW5nICBWYWx1ZSBFbmNvZGluZw== +ICAgICAgICAgMCBBICAgICAgICAgICAgMTcgUiAgICAgICAgICAgIDM0IGkgICAgICAgICAgICA1MSB6 +ICAgICAgICAgMSBCICAgICAgICAgICAgMTggUyAgICAgICAgICAgIDM1IGogICAgICAgICAgICA1MiAw +ICAgICAgICAgMiBDICAgICAgICAgICAgMTkgVCAgICAgICAgICAgIDM2IGsgICAgICAgICAgICA1MyAx +ICAgICAgICAgMyBEICAgICAgICAgICAgMjAgVSAgICAgICAgICAgIDM3IGwgICAgICAgICAgICA1NCAy +ICAgICAgICAgNCBFICAgICAgICAgICAgMjEgViAgICAgICAgICAgIDM4IG0gICAgICAgICAgICA1NSAz +ICAgICAgICAgNSBGICAgICAgICAgICAgMjIgVyAgICAgICAgICAgIDM5IG4gICAgICAgICAgICA1NiA0 +ICAgICAgICAgNiBHICAgICAgICAgICAgMjMgWCAgICAgICAgICAgIDQwIG8gICAgICAgICAgICA1NyA1 +ICAgICAgICAgNyBIICAgICAgICAgICAgMjQgWSAgICAgICAgICAgIDQxIHAgICAgICAgICAgICA1OCA2 +ICAgICAgICAgOCBJICAgICAgICAgICAgMjUgWiAgICAgICAgICAgIDQyIHEgICAgICAgICAgICA1OSA3 +ICAgICAgICAgOSBKICAgICAgICAgICAgMjYgYSAgICAgICAgICAgIDQzIHIgICAgICAgICAgICA2MCA4 +ICAgICAgICAxMCBLICAgICAgICAgICAgMjcgYiAgICAgICAgICAgIDQ0IHMgICAgICAgICAgICA2MSA5 +ICAgICAgICAxMSBMICAgICAgICAgICAgMjggYyAgICAgICAgICAgIDQ1IHQgICAgICAgICAgICA2MiAr +ICAgICAgICAxMiBNICAgICAgICAgICAgMjkgZCAgICAgICAgICAgIDQ2IHUgICAgICAgICAgICA2MyAv +ICAgICAgICAxMyBOICAgICAgICAgICAgMzAgZSAgICAgICAgICAgIDQ3IHY= +ICAgICAgICAxNCBPICAgICAgICAgICAgMzEgZiAgICAgICAgICAgIDQ4IHcgICAgICAgICAocGFkKSA9 +ICAgICAgICAxNSBQICAgICAgICAgICAgMzIgZyAgICAgICAgICAgIDQ5IHg= +ICAgICAgICAxNiBRICAgICAgICAgICAgMzMgaCAgICAgICAgICAgIDUwIHk=