//============================================================================== // tribble/util/Base64Encoder.java //============================================================================== package tribble.util; // System imports import java.lang.String; import java.text.ParseException; // Local imports // (None) /******************************************************************************* * Base-64 encoding methods. * *

* Base-64 encoding (a.k.a. radix-64 encoding) is a form of encoding binary data * in 6-bit units. (6 bits provides 64 distinct binary values, hence the moniker * base-64 or radix-64.) Groups of three 8-bit octets (bytes), * totalling 24 bits, can be converted into four 6-bit units. Each 6-bit unit * can in turn be represented by one of 64 unique printable ASCII (8-bit) * characters. * *

* Converting straight binary data (as a sequence of 8-bit octets) into a * base-64 representation is thus simply the the process of packing groups of * three 8-bit octets into four 6-bit units, and then substituting each 6-bit * unit with its corresponding ASCII character code. * *

* Converting base-64 encoded data (as a sequence of 8-bit characters) back into * straight binary data is the reverse operation, substituting each base-64 * ASCII character code with its corresponding 6-bit unit, then unpacking groups * of four 6-bit units into three 8-bit octets. * *

* A 65th special ASCII character is used to indicate trailing padding in * base-64 encoded data. * *

* This class can be used as a simple replacement for the * {@link sun.misc.BASE64Encoder} class. * * * @version $Revision: 1.2 $ $Date: 2005/04/10 20:05:52 $ * @since 2003-02-26 * @author * David R. Tribble * (david@tribble.com). *
* * Copyright ©2003-2005 by David R. Tribble, all rights reserved. *
* Permission is granted to freely use and distribute this source * code provided that the original copyright and authorship notices * remain intact. * * @see Base64Decoder * @see sun.misc.BASE64Encoder */ public class Base64Encoder { // Identification /** Revision information. */ static final String REV = "@(#)tribble/util/Base64Encoder.java $Revision: 1.2 $ $Date: 2005/04/10 20:05:52 $\n"; /** Class revision number. */ public static final int SERIES = 102; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Public static methods /*************************************************************************** * Encode binary data as base-64 characters. * * * @param data (const) * Binary data, as an array of bytes (8-bit octets). * * @return * A printable ASCII string containing the contents of data encoded * as base-64 characters. This string will contain * data.length*4/3+p characters, where p is * 0, 1, or 2, so as to make the total output length a multiple of 4. * * @see #encodeAsString(byte[], int, int) encodeAsString() * @see Base64Decoder#decodeString(String) Base64Decoder.decodeString() * * @since 1.1, 2003-02-26 */ public static String encodeAsString(/*const*/ byte[] data) { // Encode the binary data as base-64 characters return (encodeAsString(data, 0, data.length)); } /*************************************************************************** * Encode binary data as base-64 characters. * * * @param data (const) * Binary data, as an array of bytes (8-bit octets). * * @param off * Index of the first byte (octet) within data to encode. * * @param len * Number of bytes (octets) within data to encode. * * @return * A printable ASCII string containing the contents of data encoded * as base-64 characters. This string will contain * len*4/3+p characters, where p is * 0, 1, or 2, so as to make the total output length a multiple of 4. * * @see #encodeAsBytes(byte[], int, int) encodeAsBytes() * @see Base64Decoder#decodeString(String, byte[], int) * Base64Decoder.decodeString() * * @since 1.1, 2003-02-26 */ public static String encodeAsString(/*const*/ byte[] data, int off, int len) { byte[] b; // Encode 8-bit bytes as base-64 character bytes b = encodeAsBytes(data, off, len); // Return the encoded character bytes as a string return (new String(b)); } /*************************************************************************** * Encode binary data as base-64 character octets. * * * @param data (const) * Binary data, as an array of bytes (8-bit octets). * * @return * An array of bytes containing printable ASCII characters representating the * contents of data encoded as base-64 characters. This array will * contain data.length*4/3+p characters, where * p is 0, 1, or 2, so as to make the total output length a * multiple of 4. * * @see #encodeAsBytes(byte[], int, int) encodeAsBytes() * @see Base64Decoder#decodeBytes(byte[]) Base64Decoder.decodeBytes() * * @since 1.1, 2005-04-01 */ public static byte[] encodeAsBytes(/*const*/ byte[] data) { // Encode the binary data as base-64 characters return (encodeAsBytes(data, 0, data.length)); } /*************************************************************************** * Encode binary data as base-64 characters. * * * @param data (const) * Binary data, as an array of bytes (8-bit octets). * * @param off * Index of the first byte (octet) within data to encode. * * @param len * Number of bytes (octets) within data to encode. * * @return * An array of bytes containing printable ASCII characters containing the * contents of data encoded as base-64 characters. This array will * contain data.length*4/3+p characters, where * p is 0, 1, or 2, so as to make the total output length a * multiple of 4. * * @see #encodeAsBytes(byte[], int, int, byte[], int) encodeAsBytes() * @see Base64Decoder#decodeBytes(byte[], int, int) * Base64Decoder.decodeBytes() * * @since 1.1, 2005-04-01 */ public static byte[] encodeAsBytes(/*const*/ byte[] data, int off, int len) { byte[] enc; int olen; // Allocate the output buffer olen = (data.length+3-1)/3*4; enc = new byte[olen]; // Encode the binary data as base-64 characters encodeAsBytes(data, off, len, enc, 0); return (enc); } /*************************************************************************** * Encode binary data as base-64 characters. * *

* Base-64 (a.k.a. radix-64) encoding converts 8-bit bytes (octets) into * characters by encoding 6 bits of data (sextets) in each output character; * thus 3 8-bit input bytes can be converted into 4 6-bit output characters * (for a total of 24 data bits). Any input bytes left over (two or less) * are converted and padded. * *

    *    +---------------+---------------+---------------+
    *    |     octet     |     octet     |     octet     |
    *    |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|  input octets
    *    :- - - - - -:- -:- - - -:- - - -:- -:- - - - - -:
    *    |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|  output sextets
    *    |   sextet  |   sextet  |   sextet  |   sextet  |
    *    +-----------+-----------+-----------+-----------+
    *
    *    +---------------+---------------+ - - - - - - - +
    *    |     octet     |     octet     |    no data    :
    *    |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|               :  input octets
    *    :- - - - - -:- -:- - - -:- - - -:- -:- - - - - -:
    *    |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 z z|    '='    |  output sextets
    *    |   sextet  |   sextet  |   sextet  |  padding  |
    *    +-----------+-----------+-----------+-----------+
    *
    *    +---------------+ - - - - - - - + - - - - - - - +
    *    |     octet     |    no data    :    no data    :
    *    |7 6 5 4 3 2 1 0|               :               :  input octets
    *    :- - - - - -:- -:- - - -:- - - -:- -:- - - - - -:
    *    |5 4 3 2 1 0|5 4 z z z z|    '='    |    '='    |  output sextets
    *    |   sextet  |   sextet  |  padding  |  padding  |
    *    +-----------+-----------+-----------+-----------+ 
* *

* For example, the following table list some octet sequences and their * resulting sextet encodings: *

    *    11,11,11           => 04,11,04,11
    *    11,22,33           => 04,12,08,33
    *    FF,FF,FF           => 3F,3F,3F,3F
    *    11,11              => 04,11,04, =
    *    FF,FF              => 3F,3F,3C, =
    *    11                 => 04,10, =, =
    *    FF                 => 3F,30, =, =
    *    FF,00,FF,00,FF,00  => 3F,30,03,3F,00,0F,3C,00 
* * * @param data (const) * Binary data, as an array of bytes (8-bit octets). * * @param off * Index of the first byte (octet) within data to encode. * * @param len * Number of bytes (octets) within data to encode. * * @param enc * An array of bytes into which will be written printable ASCII characters * representating the contents of data encoded as base-64 * characters. * * @param encOff * Index of the first byte (octet) within enc to write to. * * @return * The number of bytes (8-bit octets) actually written into enc. * This will be exactly len*4/3+p bytes, where * p is 0, 1, or 2, so as to make the total output length a * multiple of 4. * * @see #encodeAsBytes(byte[], int, int, byte[], int) encodeAsBytes() * @see Base64Decoder#decodeBytes(byte[], int, int) * Base64Decoder.decodeBytes() * * @since 1.1, 2005-04-01 */ public static int encodeAsBytes(/*const*/ byte[] data, int off, int len, byte[] enc, int encOff) { int d; int i; int o; // Convert the input bytes in chunks, 24 bits (3 octets) at a time len += off; i = off; o = encOff; while (i < len-2) { // Convert a single 24-bit chunk (3 octets into 4 sextets) d = ((data[i+0] & 0xFF) << 16) | ((data[i+1] & 0xFF) << 8) | ((data[i+2] & 0xFF)); i += 3; enc[o++] = toBase64((d >> 18) & 0x3F); enc[o++] = toBase64((d >> 12) & 0x3F); enc[o++] = toBase64((d >> 6) & 0x3F); enc[o++] = toBase64((d) & 0x3F); } // Convert leftover input bytes, if any if (i < len-1) { // Two input bytes left, requires one padding char d = ((data[i+0] & 0xFF) << 16) | ((data[i+1] & 0xFF) << 8); enc[o++] = toBase64((d >> 18) & 0x3F); enc[o++] = toBase64((d >> 12) & 0x3F); enc[o++] = toBase64((d >> 6) & 0x3F); enc[o++] = '='; } else if (i < len) { // One input byte left, requires two padding chars d = ((data[i+0] & 0xFF) << 16); enc[o++] = toBase64((d >> 18) & 0x3F); enc[o++] = toBase64((d >> 12) & 0x3F); enc[o++] = '='; enc[o++] = '='; } // Done return (o-encOff); } /*************************************************************************** * Convert a 6-bit binary value into its corresponding base-64 printable * ASCII character code. * * * @param bits * A 6-bit binary value in the range [0,63]; or the value 64, indicating the * special trailing padding character code; or the character '?', * indicating an invalid 6-bit code. * * @return * A printable ASCII character code. * * @see Base64Decoder#fromBase64 Base64Decoder.fromBase64() * * @since 1.1, 2003-02-26 */ public static byte toBase64(int bits) { // This averages 2.85 comparisons per call if (bits >= 52) { if (bits < 62) return ((byte) (bits-52+'0')); if (bits == 62) return ((byte) '+'); if (bits == 63) return ((byte) '/'); if (bits == 64) return ((byte) '='); return ((byte) '?'); } if (bits >= 26) return ((byte) (bits-26+'a')); if (bits >= 0) return ((byte) (bits-0+'A')); return ((byte) '?'); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Variables // (None) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Public constructors /*************************************************************************** * Default constructor. * *

* This constructor is provided for compatibility with the * {@link sun.misc.BASE64Encoder} class, which allows this class to be used * as a simple replacement for it. * * @since 1.2, 2005-04-10 */ public Base64Encoder() { // Do nothing } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Public methods /*************************************************************************** * Encode binary data as base-64 characters. * *

* This method produces the same result as the encode() method * of the {@link sun.misc.BASE64Encoder} class. * * * @param data (const) * Binary data, as an array of bytes (8-bit octets). * * @return * A printable ASCII string containing the contents of data encoded * as base-64 characters. This string will contain * data.length*4/3+p characters, where p is * 0, 1, or 2, so as to make the total output length a multiple of 4. * * @see #encodeAsString(byte[]) encodeAsString() * @see Base64Decoder#decodeString(String) Base64Decoder.decodeString() * * @since 1.2, 2005-04-10 */ public String encode(/*const*/ byte[] data) { // Encode the binary data as base-64 characters return (encodeAsString(data, 0, data.length)); } } // End Base64Encoder.java