19f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/*
29f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Licensed to the Apache Software Foundation (ASF) under one or more
39f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * contributor license agreements.  See the NOTICE file distributed with
49f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * this work for additional information regarding copyright ownership.
59f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * The ASF licenses this file to You under the Apache License, Version 2.0
69f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * (the "License"); you may not use this file except in compliance with
79f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * the License.  You may obtain a copy of the License at
89f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li *
99f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li *      http://www.apache.org/licenses/LICENSE-2.0
109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li *
119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Unless required by applicable law or agreed to in writing, software
129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * distributed under the License is distributed on an "AS IS" BASIS,
139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * See the License for the specific language governing permissions and
159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * limitations under the License.
169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */
179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipackage org.apache.commons.codec.binary;
199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.math.BigInteger;
219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.apache.commons.codec.BinaryDecoder;
239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.apache.commons.codec.BinaryEncoder;
249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.apache.commons.codec.DecoderException;
259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.apache.commons.codec.EncoderException;
269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/**
289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Provides Base64 encoding and decoding as defined by RFC 2045.
299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li *
309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <p>
319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * </p>
349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <p>
359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * The class can be parameterized in the following manner with various constructors:
369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <ul>
379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <li>URL-safe mode: Default off.</li>
389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <li>Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being multiples of
399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 4 in the encoded data.
409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <li>Line separator: Default is CRLF ("\r\n")</li>
419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * </ul>
429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * </p>
439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * <p>
449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode
459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * </p>
479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li *
489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @author Apache Software Foundation
509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @since 1.0
519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @version $Id: Base64.java 801706 2009-08-06 16:27:06Z niallp $
529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */
539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipublic class Base64Codec implements BinaryEncoder, BinaryDecoder {
549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;
559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static final int DEFAULT_BUFFER_SIZE = 8192;
579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Chunk size per RFC 2045 section 6.8.
609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * equal signs.
649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    static final int CHUNK_SIZE = 76;
699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Chunk separator per RFC 2045 section 2.1.
729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * N.B. The next major release may break compatibility and make this field private.
759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet"
839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * equivalents as specified in Table 1 of RFC 2045.
849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Thanks to "commons" project in ws.apache.org for this code.
869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static final byte[] STANDARD_ENCODE_TABLE = {
899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    };
959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and /
989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * changed to - and _ to make the encoded Base64 results more URL-SAFE.
999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * This table is only used when the Base64's mode is set to URL-SAFE.
1009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static final byte[] URL_SAFE_ENCODE_TABLE = {
1029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
1039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
1049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
1059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
1069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
1079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    };
1089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Byte used to pad output.
1119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static final byte PAD = '=';
1139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified in
1169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64
1179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * alphabet but fall within the bounds of the array are translated to -1.
1189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
1199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both
1209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).
1219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
1229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Thanks to "commons" project in ws.apache.org for this code.
1239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
1249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static final byte[] DECODE_TABLE = {
1269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54,
1299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
1309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
1329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
1339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    };
1349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /** Mask used to extract 6 bits, used when encoding */
1369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static final int MASK_6BITS = 0x3f;
1379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /** Mask used to extract 8 bits, used in decoding base64 bytes */
1399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static final int MASK_8BITS = 0xff;
1409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    // The static final fields above are used for the original static byte[] methods on Base64.
1429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    // The private member fields below are used with the new streaming approach, which requires
1439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    // some state be preserved between calls of encode() and decode().
1449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
1479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
1489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * between the two modes.
1499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private final byte[] encodeTable;
1519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Line length for encoding. Not used when decoding. A value of zero or less implies no chunking of the base64
1549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * encoded data.
1559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private final int lineLength;
1579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
1609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private final byte[] lineSeparator;
1629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
1659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <code>decodeSize = 3 + lineSeparator.length;</code>
1669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private final int decodeSize;
1689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
1719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <code>encodeSize = 4 + lineSeparator.length;</code>
1729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private final int encodeSize;
1749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Buffer for streaming.
1779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private byte[] buffer;
1799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Position where next character should be written in the buffer.
1829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private int pos;
1849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Position where next character should be read from the buffer.
1879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private int readPos;
1899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Variable tracks how many characters have been written to the current line. Only used when encoding. We use it to
1929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * make sure each encoded line never goes beyond lineLength (if lineLength > 0).
1939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private int currentLinePos;
1959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
1979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Writes to the buffer only occur after every 3 reads when encoding, an every 4 reads when decoding. This variable
1989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * helps track that.
1999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
2009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private int modulus;
2019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
2039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this Base64 object becomes useless,
2049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * and must be thrown away.
2059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
2069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private boolean eof;
2079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
2099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Place holder for the 3 bytes we're dealing with for our base64 logic. Bitwise operations store and extract the
2109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * base64 encoding or decoding from this variable.
2119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
2129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private int x;
2139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
2159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
2169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
2189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
2199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
2209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * When decoding all variants are supported.
2229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
2239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
2249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public Base64Codec() {
2259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        this(false);
2269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
2279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
2299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Creates a Base64 codec used for decoding (all modes) and encoding in the given URL-safe mode.
2309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
2329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
2339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
2349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * When decoding all variants are supported.
2369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
2379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
2389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param urlSafe
2399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            if <code>true</code>, URL-safe encoding is used. In most cases this should be set to
2409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            <code>false</code>.
2419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
2429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
2439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public Base64Codec(boolean urlSafe) {
2449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        this(CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe);
2459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
2469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
2489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
2499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * When encoding the line length is given in the constructor, the line separator is CRLF, and the encoding table is
2519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * STANDARD_ENCODE_TABLE.
2529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
2539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
2559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
2569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * When decoding all variants are supported.
2589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
2599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
2609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param lineLength
2619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
2629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
2639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
2649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
2659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public Base64Codec(int lineLength) {
2669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        this(lineLength, CHUNK_SEPARATOR);
2679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
2689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
2709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
2719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * When encoding the line length and line separator are given in the constructor, and the encoding table is
2739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * STANDARD_ENCODE_TABLE.
2749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
2759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
2779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
2789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * When decoding all variants are supported.
2809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
2819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
2829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param lineLength
2839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
2849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
2859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param lineSeparator
2869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Each line of encoded data will end with this sequence of bytes.
2879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @throws IllegalArgumentException
2889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *             Thrown when the provided lineSeparator included some base64 characters.
2899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
2909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
2919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public Base64Codec(int lineLength, byte[] lineSeparator) {
2929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        this(lineLength, lineSeparator, false);
2939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
2949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
2969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
2979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
2989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * When encoding the line length and line separator are given in the constructor, and the encoding table is
2999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * STANDARD_ENCODE_TABLE.
3009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
3019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
3029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
3039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
3049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
3059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * When decoding all variants are supported.
3069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
3079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
3089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param lineLength
3099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
3109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
3119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param lineSeparator
3129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Each line of encoded data will end with this sequence of bytes.
3139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param urlSafe
3149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode
3159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            operations. Decoding seamlessly handles both modes.
3169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @throws IllegalArgumentException
3179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *             The provided lineSeparator included some base64 characters. That's not going to work!
3189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
3199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
3209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public Base64Codec(int lineLength, byte[] lineSeparator, boolean urlSafe) {
3219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (lineSeparator == null) {
3229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            lineLength = 0;  // disable chunk-separating
3239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            lineSeparator = CHUNK_SEPARATOR;  // this just gets ignored
3249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
3259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        this.lineLength = lineLength > 0 ? (lineLength / 4) * 4 : 0;
3269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        this.lineSeparator = new byte[lineSeparator.length];
3279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
3289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (lineLength > 0) {
3299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            this.encodeSize = 4 + lineSeparator.length;
3309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        } else {
3319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            this.encodeSize = 4;
3329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
3339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        this.decodeSize = this.encodeSize - 1;
3349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (containsBase64Byte(lineSeparator)) {
3359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            String sep = StringUtils.newStringUtf8(lineSeparator);
3369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            throw new IllegalArgumentException("lineSeperator must not contain base64 characters: [" + sep + "]");
3379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
3389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;
3399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
3409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
3419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
3429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Returns our current encode mode. True if we're URL-SAFE, false otherwise.
3439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
3449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return true if we're in URL-SAFE mode, false otherwise.
3459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
3469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
3479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public boolean isUrlSafe() {
3489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return this.encodeTable == URL_SAFE_ENCODE_TABLE;
3499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
3509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
3519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
3529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Returns true if this Base64 object has buffered data for reading.
3539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
3549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return true if there is Base64 object still available for reading.
3559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
3569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    boolean hasData() {
3579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return this.buffer != null;
3589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
3599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
3609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
3619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Returns the amount of buffered data available for reading.
3629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
3639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return The amount of buffered data available for reading.
3649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
3659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    int avail() {
3669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return buffer != null ? pos - readPos : 0;
3679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
3689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
3699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /** Doubles our buffer. */
3709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private void resizeBuffer() {
3719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (buffer == null) {
3729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            buffer = new byte[DEFAULT_BUFFER_SIZE];
3739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            pos = 0;
3749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            readPos = 0;
3759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        } else {
3769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            byte[] b = new byte[buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR];
3779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            System.arraycopy(buffer, 0, b, 0, buffer.length);
3789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            buffer = b;
3799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
3809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
3819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
3829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
3839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail
3849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * bytes. Returns how many bytes were actually extracted.
3859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
3869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param b
3879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            byte[] array to extract the buffered data into.
3889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param bPos
3899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            position in byte[] array to start extraction at.
3909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param bAvail
3919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            amount of bytes we're allowed to extract. We may extract fewer (if fewer are available).
3929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return The number of bytes successfully extracted into the provided byte[] array.
3939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
3949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    int readResults(byte[] b, int bPos, int bAvail) {
3959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (buffer != null) {
3969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            int len = Math.min(avail(), bAvail);
3979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            if (buffer != b) {
3989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                System.arraycopy(buffer, readPos, b, bPos, len);
3999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                readPos += len;
4009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                if (readPos >= pos) {
4019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer = null;
4029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                }
4039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            } else {
4049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                // Re-using the original consumer's output array is only
4059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                // allowed for one round.
4069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                buffer = null;
4079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
4089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return len;
4099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
4109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return eof ? -1 : 0;
4119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
4129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
4139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
4149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Sets the streaming buffer. This is a small optimization where we try to buffer directly to the consumer's output
4159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * array for one round (if the consumer calls this method first) instead of starting our own buffer.
4169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
4179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param out
4189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            byte[] array to buffer directly to.
4199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param outPos
4209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Position to start buffering into.
4219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param outAvail
4229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Amount of bytes available for direct buffering.
4239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
4249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    void setInitialBuffer(byte[] out, int outPos, int outAvail) {
4259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // We can re-use consumer's original output array under
4269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // special circumstances, saving on some System.arraycopy().
4279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (out != null && out.length == outAvail) {
4289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            buffer = out;
4299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            pos = outPos;
4309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            readPos = outPos;
4319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
4329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
4339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
4349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
4359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
4369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with
4379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, so flush last
4389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * remaining bytes (if not multiple of 3).
4399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
4409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
4419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
4429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
4439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
4449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
4459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param in
4469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            byte[] array of binary data to base64 encode.
4479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param inPos
4489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Position to start reading data from.
4499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param inAvail
4509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Amount of bytes available from input for encoding.
4519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
4529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    void encode(byte[] in, int inPos, int inAvail) {
4539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (eof) {
4549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return;
4559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
4569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // inAvail < 0 is how we're informed of EOF in the underlying data we're
4579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // encoding.
4589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (inAvail < 0) {
4599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            eof = true;
4609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            if (buffer == null || buffer.length - pos < encodeSize) {
4619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                resizeBuffer();
4629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
4639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            switch (modulus) {
4649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                case 1 :
4659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = encodeTable[(x >> 2) & MASK_6BITS];
4669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = encodeTable[(x << 4) & MASK_6BITS];
4679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    // URL-SAFE skips the padding to further reduce size.
4689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    if (encodeTable == STANDARD_ENCODE_TABLE) {
4699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                        buffer[pos++] = PAD;
4709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                        buffer[pos++] = PAD;
4719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    }
4729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    break;
4739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
4749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                case 2 :
4759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = encodeTable[(x >> 10) & MASK_6BITS];
4769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = encodeTable[(x >> 4) & MASK_6BITS];
4779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = encodeTable[(x << 2) & MASK_6BITS];
4789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    // URL-SAFE skips the padding to further reduce size.
4799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    if (encodeTable == STANDARD_ENCODE_TABLE) {
4809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                        buffer[pos++] = PAD;
4819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    }
4829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    break;
4839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
4849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            if (lineLength > 0 && pos > 0) {
4859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
4869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                pos += lineSeparator.length;
4879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
4889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        } else {
4899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            for (int i = 0; i < inAvail; i++) {
4909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                if (buffer == null || buffer.length - pos < encodeSize) {
4919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    resizeBuffer();
4929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                }
4939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                modulus = (++modulus) % 3;
4949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                int b = in[inPos++];
4959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                if (b < 0) {
4969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    b += 256;
4979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                }
4989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                x = (x << 8) + b;
4999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                if (0 == modulus) {
5009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = encodeTable[(x >> 18) & MASK_6BITS];
5019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = encodeTable[(x >> 12) & MASK_6BITS];
5029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = encodeTable[(x >> 6) & MASK_6BITS];
5039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = encodeTable[x & MASK_6BITS];
5049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    currentLinePos += 4;
5059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    if (lineLength > 0 && lineLength <= currentLinePos) {
5069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                        System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
5079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                        pos += lineSeparator.length;
5089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                        currentLinePos = 0;
5099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    }
5109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                }
5119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
5129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
5139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
5149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
5159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
5169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
5179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once
5189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1"
5199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * call is not necessary when decoding, but it doesn't hurt, either.
5209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
5219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
5229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Ignores all non-base64 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are
5239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in,
5249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * garbage-out philosophy: it will not check the provided data for validity.
5259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
5269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * <p>
5279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
5289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
5299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * </p>
5309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
5319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param in
5329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            byte[] array of ascii data to base64 decode.
5339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param inPos
5349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Position to start reading data from.
5359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param inAvail
5369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Amount of bytes available from input for encoding.
5379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
5389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    void decode(byte[] in, int inPos, int inAvail) {
5399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (eof) {
5409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return;
5419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
5429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (inAvail < 0) {
5439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            eof = true;
5449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
5459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        for (int i = 0; i < inAvail; i++) {
5469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            if (buffer == null || buffer.length - pos < decodeSize) {
5479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                resizeBuffer();
5489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
5499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            byte b = in[inPos++];
5509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            if (b == PAD) {
5519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                // We're done.
5529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                eof = true;
5539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                break;
5549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            } else {
5559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                if (b >= 0 && b < DECODE_TABLE.length) {
5569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    int result = DECODE_TABLE[b];
5579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    if (result >= 0) {
5589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                        modulus = (++modulus) % 4;
5599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                        x = (x << 6) + result;
5609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                        if (modulus == 0) {
5619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                            buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS);
5629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                            buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS);
5639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                            buffer[pos++] = (byte) (x & MASK_8BITS);
5649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                        }
5659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    }
5669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                }
5679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
5689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
5699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
5709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // Two forms of EOF as far as base64 decoder is concerned: actual
5719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // EOF (-1) and first time '=' character is encountered in stream.
5729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // This approach makes the '=' padding characters completely optional.
5739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (eof && modulus != 0) {
5749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            x = x << 6;
5759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            switch (modulus) {
5769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                case 2 :
5779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    x = x << 6;
5789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS);
5799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    break;
5809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                case 3 :
5819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS);
5829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS);
5839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    break;
5849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
5859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
5869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
5879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
5889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
5899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Returns whether or not the <code>octet</code> is in the base 64 alphabet.
5909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
5919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param octet
5929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            The value to test
5939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return <code>true</code> if the value is defined in the the base 64 alphabet, <code>false</code> otherwise.
5949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
5959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
5969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static boolean isBase64(byte octet) {
5979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return octet == PAD || (octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1);
5989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
5999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
6009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
6019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
6029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * method treats whitespace as valid.
6039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
6049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param arrayOctet
6059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            byte array to test
6069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return <code>true</code> if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
6079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *         false, otherwise
6089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
6099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static boolean isArrayByteBase64(byte[] arrayOctet) {
6109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        for (int i = 0; i < arrayOctet.length; i++) {
6119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) {
6129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                return false;
6139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
6149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
6159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return true;
6169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
6179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
6189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
6199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet.
6209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
6219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param arrayOctet
6229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            byte array to test
6239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return <code>true</code> if any byte is a valid character in the Base64 alphabet; false herwise
6249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
6259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static boolean containsBase64Byte(byte[] arrayOctet) {
6269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        for (int i = 0; i < arrayOctet.length; i++) {
6279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            if (isBase64(arrayOctet[i])) {
6289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                return true;
6299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
6309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
6319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return false;
6329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
6339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
6349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
6359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes binary data using the base64 algorithm but does not chunk the output.
6369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
6379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param binaryData
6389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            binary data to encode
6399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return byte[] containing Base64 characters in their UTF-8 representation.
6409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
6419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static byte[] encodeBase64(byte[] binaryData) {
6429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return encodeBase64(binaryData, false);
6439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
6449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
6459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
6469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes binary data using the base64 algorithm into 76 character blocks separated by CRLF.
6479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
6489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param binaryData
6499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            binary data to encode
6509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return String containing Base64 characters.
6519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
6529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
6539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static String encodeBase64String(byte[] binaryData) {
6549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return StringUtils.newStringUtf8(encodeBase64(binaryData, true));
6559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
6569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
6579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
6589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
6599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * url-safe variation emits - and _ instead of + and / characters.
6609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
6619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param binaryData
6629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            binary data to encode
6639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return byte[] containing Base64 characters in their UTF-8 representation.
6649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
6659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
6669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static byte[] encodeBase64URLSafe(byte[] binaryData) {
6679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return encodeBase64(binaryData, false, true);
6689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
6699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
6709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
6719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
6729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * url-safe variation emits - and _ instead of + and / characters.
6739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
6749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param binaryData
6759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            binary data to encode
6769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return String containing Base64 characters
6779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
6789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
6799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static String encodeBase64URLSafeString(byte[] binaryData) {
6809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return StringUtils.newStringUtf8(encodeBase64(binaryData, false, true));
6819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
6829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
6839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
6849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks
6859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
6869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param binaryData
6879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            binary data to encode
6889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return Base64 characters chunked in 76 character blocks
6899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
6909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static byte[] encodeBase64Chunked(byte[] binaryData) {
6919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return encodeBase64(binaryData, true);
6929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
6939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
6949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
6959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Decodes an Object using the base64 algorithm. This method is provided in order to satisfy the requirements of the
6969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Decoder interface, and will throw a DecoderException if the supplied object is not of type byte[] or String.
6979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
6989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param pObject
6999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Object to decode
7009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return An object (of type byte[]) containing the binary data which corresponds to the byte[] or String supplied.
7019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @throws DecoderException
7029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *             if the parameter supplied is not of type byte[]
7039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
7049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public Object decode(Object pObject) throws DecoderException {
7059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (pObject instanceof byte[]) {
7069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return decode((byte[]) pObject);
7079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        } else if (pObject instanceof String) {
7089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return decode((String) pObject);
7099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        } else {
7109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            throw new DecoderException("Parameter supplied to Base64 decode is not a byte[] or a String");
7119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
7129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
7139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
7149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
7159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Decodes a String containing containing characters in the Base64 alphabet.
7169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
7179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param pArray
7189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            A String containing Base64 character data
7199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return a byte array containing binary data
7209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
7219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
7229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public byte[] decode(String pArray) {
7239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return decode(StringUtils.getBytesUtf8(pArray));
7249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
7259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
7269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
7279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Decodes a byte[] containing containing characters in the Base64 alphabet.
7289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
7299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param pArray
7309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            A byte array containing Base64 character data
7319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return a byte array containing binary data
7329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
7339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public byte[] decode(byte[] pArray) {
7349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        reset();
7359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (pArray == null || pArray.length == 0) {
7369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return pArray;
7379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
7389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        long len = (pArray.length * 3) / 4;
7399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        byte[] buf = new byte[(int) len];
7409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        setInitialBuffer(buf, 0, buf.length);
7419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        decode(pArray, 0, pArray.length);
7429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        decode(pArray, 0, -1); // Notify decoder of EOF.
7439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
7449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // Would be nice to just return buf (like we sometimes do in the encode
7459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // logic), but we have no idea what the line-length was (could even be
7469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // variable).  So we cannot determine ahead of time exactly how big an
7479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // array is necessary.  Hence the need to construct a 2nd byte array to
7489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // hold the final result:
7499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
7509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        byte[] result = new byte[pos];
7519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        readResults(result, 0, result.length);
7529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return result;
7539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
7549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
7559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
7569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
7579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
7589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param binaryData
7599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Array containing binary data to encode.
7609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param isChunked
7619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
7629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return Base64-encoded data.
7639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @throws IllegalArgumentException
7649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *             Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
7659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
7669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
7679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return encodeBase64(binaryData, isChunked, false);
7689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
7699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
7709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
7719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
7729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
7739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param binaryData
7749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Array containing binary data to encode.
7759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param isChunked
7769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
7779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param urlSafe
7789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            if <code>true</code> this encoder will emit - and _ instead of the usual + and / characters.
7799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return Base64-encoded data.
7809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @throws IllegalArgumentException
7819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *             Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
7829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
7839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
7849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe) {
7859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE);
7869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
7879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
7889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
7899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
7909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
7919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param binaryData
7929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Array containing binary data to encode.
7939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param isChunked
7949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
7959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param urlSafe
7969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            if <code>true</code> this encoder will emit - and _ instead of the usual + and / characters.
7979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param maxResultSize
7989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            The maximum result size to accept.
7999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return Base64-encoded data.
8009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @throws IllegalArgumentException
8019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *             Thrown when the input array needs an output array bigger than maxResultSize
8029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
8039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
8049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe, int maxResultSize) {
8059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (binaryData == null || binaryData.length == 0) {
8069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return binaryData;
8079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
8089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
8099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        long len = getEncodeLength(binaryData, CHUNK_SIZE, CHUNK_SEPARATOR);
8109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (len > maxResultSize) {
8119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
8129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                len +
8139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                ") than the specified maxium size of " +
8149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                maxResultSize);
8159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
8169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
8179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        Base64Codec b64 = isChunked ? new Base64Codec(urlSafe) : new Base64Codec(0, CHUNK_SEPARATOR, urlSafe);
8189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return b64.encode(binaryData);
8199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
8209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
8219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
8229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Decodes a Base64 String into octets
8239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
8249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param base64String
8259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            String containing Base64 data
8269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return Array containing decoded data.
8279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
8289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
8299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static byte[] decodeBase64(String base64String) {
8309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return new Base64Codec().decode(base64String);
8319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
8329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
8339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
8349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Decodes Base64 data into octets
8359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
8369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param base64Data
8379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Byte array containing Base64 data
8389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return Array containing decoded data.
8399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
8409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static byte[] decodeBase64(byte[] base64Data) {
8419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return new Base64Codec().decode(base64Data);
8429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
8439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
8449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
8459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Discards any whitespace from a base-64 encoded block.
8469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
8479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param data
8489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            The base-64 encoded data to discard the whitespace from.
8499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return The data, less whitespace (see RFC 2045).
8509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @deprecated This method is no longer needed
8519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
8529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    static byte[] discardWhitespace(byte[] data) {
8539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        byte groomedData[] = new byte[data.length];
8549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        int bytesCopied = 0;
8559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        for (int i = 0; i < data.length; i++) {
8569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            switch (data[i]) {
8579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                case ' ' :
8589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                case '\n' :
8599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                case '\r' :
8609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                case '\t' :
8619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    break;
8629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                default :
8639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                    groomedData[bytesCopied++] = data[i];
8649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
8659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
8669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        byte packedData[] = new byte[bytesCopied];
8679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
8689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return packedData;
8699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
8709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
8719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
8729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Checks if a byte value is whitespace or not.
8739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
8749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param byteToCheck
8759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            the byte to check
8769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return true if byte is whitespace, false otherwise
8779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
8789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static boolean isWhiteSpace(byte byteToCheck) {
8799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        switch (byteToCheck) {
8809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            case ' ' :
8819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            case '\n' :
8829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            case '\r' :
8839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            case '\t' :
8849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                return true;
8859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            default :
8869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                return false;
8879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
8889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
8899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
8909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    // Implementation of the Encoder Interface
8919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
8929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
8939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes an Object using the base64 algorithm. This method is provided in order to satisfy the requirements of the
8949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encoder interface, and will throw an EncoderException if the supplied object is not of type byte[].
8959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
8969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param pObject
8979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            Object to encode
8989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return An object (of type byte[]) containing the base64 encoded data which corresponds to the byte[] supplied.
8999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @throws EncoderException
9009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *             if the parameter supplied is not of type byte[]
9019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
9029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public Object encode(Object pObject) throws EncoderException {
9039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (!(pObject instanceof byte[])) {
9049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            throw new EncoderException("Parameter supplied to Base64 encode is not a byte[]");
9059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
9069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return encode((byte[]) pObject);
9079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
9089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
9099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
9109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes a byte[] containing binary data, into a String containing characters in the Base64 alphabet.
9119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
9129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param pArray
9139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            a byte array containing binary data
9149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return A String containing only Base64 character data
9159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
9169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
9179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public String encodeToString(byte[] pArray) {
9189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return StringUtils.newStringUtf8(encode(pArray));
9199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
9209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
9219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
9229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes a byte[] containing binary data, into a byte[] containing characters in the Base64 alphabet.
9239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
9249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param pArray
9259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            a byte array containing binary data
9269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return A byte array containing only Base64 character data
9279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
9289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public byte[] encode(byte[] pArray) {
9299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        reset();
9309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (pArray == null || pArray.length == 0) {
9319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return pArray;
9329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
9339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        long len = getEncodeLength(pArray, lineLength, lineSeparator);
9349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        byte[] buf = new byte[(int) len];
9359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        setInitialBuffer(buf, 0, buf.length);
9369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        encode(pArray, 0, pArray.length);
9379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        encode(pArray, 0, -1); // Notify encoder of EOF.
9389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // Encoder might have resized, even though it was unnecessary.
9399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (buffer != buf) {
9409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            readResults(buf, 0, buf.length);
9419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
9429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // In URL-SAFE mode we skip the padding characters, so sometimes our
9439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // final length is a bit smaller.
9449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (isUrlSafe() && pos < buf.length) {
9459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            byte[] smallerBuf = new byte[pos];
9469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            System.arraycopy(buf, 0, smallerBuf, 0, pos);
9479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            buf = smallerBuf;
9489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
9499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return buf;
9509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
9519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
9529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
9539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Pre-calculates the amount of space needed to base64-encode the supplied array.
9549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
9559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param pArray byte[] array which will later be encoded
9569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param chunkSize line-length of the output (<= 0 means no chunking) between each
9579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *        chunkSeparator (e.g. CRLF).
9589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param chunkSeparator the sequence of bytes used to separate chunks of output (e.g. CRLF).
9599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
9609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return amount of space needed to encoded the supplied array.  Returns
9619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *         a long since a max-len array will require Integer.MAX_VALUE + 33%.
9629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
9639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private static long getEncodeLength(byte[] pArray, int chunkSize, byte[] chunkSeparator) {
9649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // base64 always encodes to multiples of 4.
9659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        chunkSize = (chunkSize / 4) * 4;
9669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
9679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        long len = (pArray.length * 4) / 3;
9689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        long mod = len % 4;
9699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (mod != 0) {
9709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            len += 4 - mod;
9719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
9729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (chunkSize > 0) {
9739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            boolean lenChunksPerfectly = len % chunkSize == 0;
9749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            len += (len / chunkSize) * chunkSeparator.length;
9759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            if (!lenChunksPerfectly) {
9769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                len += chunkSeparator.length;
9779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
9789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
9799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return len;
9809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
9819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
9829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    // Implementation of integer encoding used for crypto
9839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
9849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Decodes a byte64-encoded integer according to crypto standards such as W3C's XML-Signature
9859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
9869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param pArray
9879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            a byte array containing base64 character data
9889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return A BigInteger
9899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
9909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
9919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static BigInteger decodeInteger(byte[] pArray) {
9929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return new BigInteger(1, decodeBase64(pArray));
9939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
9949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
9959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
9969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Encodes to a byte64-encoded integer according to crypto standards such as W3C's XML-Signature
9979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
9989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param bigInt
9999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            a BigInteger
10009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return A byte array containing base64 character data
10019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @throws NullPointerException
10029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *             if null is passed in
10039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @since 1.4
10049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
10059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public static byte[] encodeInteger(BigInteger bigInt) {
10069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (bigInt == null) {
10079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            throw new NullPointerException("encodeInteger called with null parameter");
10089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
10099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return encodeBase64(toIntegerBytes(bigInt), false);
10109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
10119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
10129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
10139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Returns a byte-array representation of a <code>BigInteger</code> without sign bit.
10149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
10159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param bigInt
10169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *            <code>BigInteger</code> to be converted
10179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return a byte array representation of the BigInteger parameter
10189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
10199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    static byte[] toIntegerBytes(BigInteger bigInt) {
10209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        int bitlen = bigInt.bitLength();
10219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // round bitlen
10229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        bitlen = ((bitlen + 7) >> 3) << 3;
10239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        byte[] bigBytes = bigInt.toByteArray();
10249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
10259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (((bigInt.bitLength() % 8) != 0) && (((bigInt.bitLength() / 8) + 1) == (bitlen / 8))) {
10269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return bigBytes;
10279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
10289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // set up params for copying everything but sign bit
10299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        int startSrc = 0;
10309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        int len = bigBytes.length;
10319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
10329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        // if bigInt is exactly byte-aligned, just skip signbit in copy
10339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if ((bigInt.bitLength() % 8) == 0) {
10349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            startSrc = 1;
10359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            len--;
10369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
10379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        int startDst = bitlen / 8 - len; // to pad w/ nulls as per spec
10389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        byte[] resizedBytes = new byte[bitlen / 8];
10399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, len);
10409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return resizedBytes;
10419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
10429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
10439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
10449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Resets this Base64 object to its initial newly constructed state.
10459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
10469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private void reset() {
10479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        buffer = null;
10489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        pos = 0;
10499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        readPos = 0;
10509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        currentLinePos = 0;
10519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        modulus = 0;
10529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        eof = false;
10539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
10549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
10559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li}
1056