Java/Development Class/Base64 — различия между версиями
Admin (обсуждение | вклад) м (1 версия) |
|
(нет различий)
|
Текущая версия на 10:07, 1 июня 2010
Содержание
- 1 A Base64 Encoder/Decoder
- 2 A fast and memory efficient class to encode and decode to and from BASE64 in full accordance with RFC 2045
- 3 array of byte to encode
- 4 Base64 Character encoder as specified in RFC1113
- 5 Base64 encoder/decoder
- 6 BASE64 encoder implementation
- 7 Base-64 Encoder - translates from base-64 text into binary
- 8 Base64 encoding/decoding.
- 9 Base64 from by Funambol, Inc.
- 10 Base64 Utils
- 11 byte to be tested if it is Base64 alphabet
- 12 Codes number up to radix 62
- 13 Converting hexadecimal strings
- 14 Convert to hex from byte arrays and back
- 15 Decodes Base64 data into octects
- 16 Encode and decode data in Base64 format as described in RFC 1521
- 17 Encode and decode integers, times, and internationalized strings to and from popular binary formats
- 18 Encode/decode for RFC 2045 Base64 as defined by RFC 2045
- 19 Encode/decode for RFC 2045 Base64 as defined by RFC 2045, N. Freed and N. Borenstein.
- 20 Encodes and decodes to and from Base64 notation.
- 21 Encodes hex octects into Base64
- 22 Encoding of raw bytes to base64-encoded characters, and decoding of base64 characters to raw bytes
- 23 Helper class to provide Base64 encoding routines.
- 24 Implementation of MIME"s Base64 encoding and decoding conversions.
- 25 One of the fastest implementation of the Base64 encoding. Jakarta and others are slower
- 26 Performs Base64 encoding and/or decoding
- 27 Provides Base64 encoding and decoding as defined by RFC 2045
- 28 Provides Base64 encoding and decoding with URL and filename safe alphabet as defined by RFC 3548, section 4.
- 29 Provides utility methods to Base64 encode data
- 30 QP Decoder Stream
- 31 QP Encoder Stream
- 32 Represents a collection of 64 boolean (on/off) flags.
- 33 to Base64
A Base64 Encoder/Decoder
<source lang="java">
/*******************************************************************************
* * A Base64 Encoder/Decoder. * * This class is used to encode and decode data in Base64 format as described in * RFC 1521. **
* Copyright 2003: Christian d"Heureuse, Inventec Informatik AG, Switzerland.
* License: This is "Open Source" software and released under the
*
* <p>
* Version history:
* 2003-07-22 Christian d"Heureuse (chdh): Module created.
* 2005-08-11 chdh: Lincense changed from GPL to LGPL.
*
******************************************************************************/
public class Base64Coder {
// Mapping table from 6-bit nibbles to Base64 characters.
private static char[] map1 = new char[64];
static {
int i = 0;
for (char c = "A"; c <= "Z"; c++)
map1[i++] = c;
for (char c = "a"; c <= "z"; c++)
map1[i++] = c;
for (char c = "0"; c <= "9"; c++)
map1[i++] = c;
map1[i++] = "+";
map1[i++] = "/";
}
// Mapping table from Base64 characters to 6-bit nibbles.
private static byte[] map2 = new byte[128];
static {
for (int i = 0; i < map2.length; i++)
map2[i] = -1;
for (int i = 0; i < 64; i++)
map2[map1[i]] = (byte) i;
}
/**
* Encodes a string into Base64 format. No blanks or line breaks are inserted.
*
* @param s
* a String to be encoded.
* @return A String with the Base64 encoded data.
*/
public static String encode(String s) {
return new String(encode(s.getBytes()));
}
/**
* Encodes a byte array into Base64 format. No blanks or line breaks are
* inserted.
*
* @param in
* an array containing the data bytes to be encoded.
* @return A character array with the Base64 encoded data.
*/
public static char[] encode(byte[] in) {
int iLen = in.length;
int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
int oLen = ((iLen + 2) / 3) * 4; // output length including padding
char[] out = new char[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++] & 0xff;
int i1 = ip < iLen ? in[ip++] & 0xff : 0;
int i2 = ip < iLen ? in[ip++] & 0xff : 0;
int o0 = i0 >>> 2;
int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
int o3 = i2 & 0x3F;
out[op++] = map1[o0];
out[op++] = map1[o1];
out[op] = op < oDataLen ? map1[o2] : "=";
op++;
out[op] = op < oDataLen ? map1[o3] : "=";
op++;
}
return out;
}
/**
* Decodes a Base64 string.
*
* @param s
* a Base64 String to be decoded.
* @return A String containing the decoded data.
* @throws IllegalArgumentException
* if the input is not valid Base64 encoded data.
*/
public static String decode(String s) {
return new String(decode(s.toCharArray()));
}
/**
* Decodes Base64 data. No blanks or line breaks are allowed within the Base64
* encoded data.
*
* @param in
* a character array containing the Base64 encoded data.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException
* if the input is not valid Base64 encoded data.
*/
public static byte[] decode(char[] in) {
int iLen = in.length;
if (iLen % 4 != 0)
throw new IllegalArgumentException(
"Length of Base64 encoded input string is not a multiple of 4.");
while (iLen > 0 && in[iLen - 1] == "=")
iLen--;
int oLen = (iLen * 3) / 4;
byte[] out = new byte[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++];
int i1 = in[ip++];
int i2 = ip < iLen ? in[ip++] : "A";
int i3 = ip < iLen ? in[ip++] : "A";
if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
int b0 = map2[i0];
int b1 = map2[i1];
int b2 = map2[i2];
int b3 = map2[i3];
if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
int o0 = (b0 << 2) | (b1 >>> 4);
int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
int o2 = ((b2 & 3) << 6) | b3;
out[op++] = (byte) o0;
if (op < oLen)
out[op++] = (byte) o1;
if (op < oLen)
out[op++] = (byte) o2;
}
return out;
}
}
</source>
A fast and memory efficient class to encode and decode to and from BASE64 in full accordance with RFC 2045
<source lang="java">
import java.util.Arrays; /** A very fast and memory efficient class to encode and decode to and from BASE64 in full accordance
* with RFC 2045.
* On Windows XP sp1 with 1.4.2_04 and later ;), this encoder and decoder is about 10 times faster * on small arrays (10 - 1000 bytes) and 2-3 times as fast on larger arrays (10000 - 1000000 bytes) * compared tosun.misc.Encoder()/Decoder()
.
* * On byte arrays the encoder is about 20% faster than Jakarta Commons Base64 Codec for encode and * about 50% faster for decoding large arrays. This implementation is about twice as fast on very small * arrays (< 30 bytes). If source/destination is aString
this * version is about three times as fast due to the fact that the Commons Codec result has to be recoded * to aString
frombyte[]
, which is very expensive.
* * This encode/decode algorithm doesn"t create any temporary arrays as many other codecs do, it only * allocates the resulting array. This produces less garbage and it is possible to handle arrays twice * as large as algorithms that create a temporary array. (E.g. Jakarta Commons Codec). It is unknown * whether Sun"ssun.misc.Encoder()/Decoder()
produce temporary arrays but since performance * is quite low it probably does.
* * The encoder produces the same output as the Sun one except that the Sun"s encoder appends * a trailing line separator if the last character isn"t a pad. Unclear why but it only adds to the * length and is probably a side effect. Both are in conformance with RFC 2045 though.
* Commons codec seem to always att a trailing line separator.
* * Note! * The encode/decode method pairs (types) come in three versions with the exact same algorithm and * thus a lot of code redundancy. This is to not create any temporary arrays for transcoding to/from different * format types. The methods not used can simply be commented out.
* * There is also a "fast" version of all decode methods that works the same way as the normal ones, but * har a few demands on the decoded input. Normally though, these fast verions should be used if the source if * the input is known and it hasn"t bee tampered with.
* * If you find the code useful or you find a bug, please send me a note at base64 @ miginfocom . com. * * Licence (BSD): * * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * Neither the name of the MiG InfoCom AB nor the names of its contributors may be * used to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * @version 2.2 * @author Mikael Grev * Date: 2004-aug-02 * Time: 11:31:11 */
public class Base64 {
private static final char[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); private static final int[] IA = new int[256]; static { Arrays.fill(IA, -1); for (int i = 0, iS = CA.length; i < iS; ++i) { IA[CA[i]] = i; } IA["="] = 0; } // **************************************************************************************** // * char[] version // **************************************************************************************** /** Encodes a raw byte array into a BASE64char[]
representation i accordance with RFC 2045. * @param sArr The bytes to convert. Ifnull
or length 0 an empty array will be returned. * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
* No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a * little faster. * @return A BASE64 encoded array. Nevernull
. */ public final static char[] encodeToChar(byte[] sArr, boolean lineSep) { // Check special case int sLen = sArr != null ? sArr.length : 0; if (sLen == 0) { return new char[0]; } //assert sArr != null; int eLen = (sLen / 3) * 3; // Length of even 24-bits. int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array char[] dArr = new char[dLen]; // Encode even 24-bits for (int s = 0, d = 0, cc = 0; s < eLen;) { // Copy next three bytes into lower 24 bits of int, paying attension to sign. int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); // Encode the int into four chars dArr[d++] = CA[(i >>> 18) & 0x3f]; dArr[d++] = CA[(i >>> 12) & 0x3f]; dArr[d++] = CA[(i >>> 6) & 0x3f]; dArr[d++] = CA[i & 0x3f]; // Add optional line separator if (lineSep && ++cc == 19 && d < dLen - 2) { dArr[d++] = "\r"; dArr[d++] = "\n"; cc = 0; } } // Pad and encode last bits if source isn"t even 24 bits. int left = sLen - eLen; // 0 - 2. if (left > 0) { // Prepare the int int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); // Set last four chars dArr[dLen - 4] = CA[i >> 12]; dArr[dLen - 3] = CA[(i >>> 6) & 0x3f]; dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : "="; dArr[dLen - 1] = "="; } return dArr; } /** Decodes a BASE64 encoded char array. All illegal characters will be ignored and can handle both arrays with * and without line separators. * @param sArr The source array.null
or length 0 will return an empty array. * @return The decoded array of bytes. May be of length 0. Will benull
if the legal characters * (including "=") isn"t divideable by 4. (I.e. definitely corrupted). */ public final static byte[] decode(char[] sArr) { // Check special case int sLen = sArr != null ? sArr.length : 0; if (sLen == 0) { return new byte[0]; } //assert sArr != null; // Count illegal characters (including "\r", "\n") to know what size the returned array will be, // so we don"t have to reallocate & copy it later. int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that"s a bonus...) for (int i = 0; i < sLen; ++i) { if (IA[sArr[i]] < 0) { ++sepCnt; } } // Check so that legal chars (including "=") are evenly divideable by 4 as specified in RFC 2045. if ((sLen - sepCnt) % 4 != 0) { return null; } int pad = 0; for (int i = sLen; i > 1 && IA[sArr[--i]] <= 0;) { if (sArr[i] == "=") { ++pad; } } int len = ((sLen - sepCnt) * 6 >> 3) - pad; byte[] dArr = new byte[len]; // Preallocate byte[] of exact length for (int s = 0, d = 0; d < len;) { // Assemble three bytes into an int from four "valid" characters. int i = 0; for (int j = 0; j < 4; ++j) { // j only increased if a valid char was found. int c = IA[sArr[s++]]; if (c >= 0) { i |= c << (18 - j * 6); } else { --j; } } // Add the bytes dArr[d++] = (byte) (i >> 16); if (d < len) { dArr[d++]= (byte) (i >> 8); if (d < len) { dArr[d++] = (byte) i; } } } return dArr; } /* * Decodes a BASE64 encoded char array that is known to be resonably well formatted. The method is about twice as * fast as {@link #decode(char[])}. The preconditions are:
* + The array must have a line length of 76 chars OR no line separators at all (one line).
* + Line separator must be "\r\n", as specified in RFC 2045 * + The array must not contain illegal characters within the encoded string
* + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
* @param sArr The source array. Length 0 will return an empty array.null
will throw an exception. * @return The decoded array of bytes. May be of length 0. * / public final static byte[] decodeFast(char[] sArr) { // Check special case int sLen = sArr.length; if (sLen == 0) { return new byte[0]; } int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. // Trim illegal chars from start while (sIx < eIx && IA[sArr[sIx]] < 0) { ++sIx; } // Trim illegal chars from end while (eIx > 0 && IA[sArr[eIx]] < 0) { --eIx; } // get the padding count (=) (0, 1 or 2) int pad = sArr[eIx] == "=" ? (sArr[eIx - 1] == "=" ? 2 : 1) : 0; // Count "=" at end. int cCnt = eIx - sIx + 1; // Content count including possible separators int sepCnt = sLen > 76 ? (sArr[76] == "\r" ? cCnt / 78 : 0) << 1 : 0; int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes byte[] dArr = new byte[len]; // Preallocate byte[] of exact length // Decode all but the last 0 - 2 bytes. int d = 0; for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { // Assemble three bytes into an int from four "valid" characters. int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; // Add the bytes dArr[d++] = (byte) (i >> 16); dArr[d++] = (byte) (i >> 8); dArr[d++] = (byte) i; // If line separator, jump over it. if (sepCnt > 0 && ++cc == 19) { sIx += 2; cc = 0; } } if (d < len) { // Decode last 1-3 bytes (incl "=") into 1-3 bytes int i = 0; for (int j = 0; sIx <= eIx - pad; ++j) { i |= IA[sArr[sIx++]] << (18 - j * 6); } for (int r = 16; d < len; r -= 8) { dArr[d++] = (byte) (i >> r); } } return dArr; }*/ // **************************************************************************************** // * byte[] version // **************************************************************************************** /** Encodes a raw byte array into a BASE64byte[]
representation i accordance with RFC 2045. * @param sArr The bytes to convert. Ifnull
or length 0 an empty array will be returned. * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
* No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a * little faster. * @return A BASE64 encoded array. Nevernull
. */ public final static byte[] encodeToByte(byte[] sArr, boolean lineSep) { // Check special case int sLen = sArr != null ? sArr.length : 0; if (sLen == 0) { return new byte[0]; } //assert sArr != null; int eLen = (sLen / 3) * 3; // Length of even 24-bits. int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array byte[] dArr = new byte[dLen]; // Encode even 24-bits for (int s = 0, d = 0, cc = 0; s < eLen;) { // Copy next three bytes into lower 24 bits of int, paying attension to sign. int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); // Encode the int into four chars dArr[d++] = (byte) CA[(i >>> 18) & 0x3f]; dArr[d++] = (byte) CA[(i >>> 12) & 0x3f]; dArr[d++] = (byte) CA[(i >>> 6) & 0x3f]; dArr[d++] = (byte) CA[i & 0x3f]; // Add optional line separator if (lineSep && ++cc == 19 && d < dLen - 2) { dArr[d++] = "\r"; dArr[d++] = "\n"; cc = 0; } } // Pad and encode last bits if source isn"t an even 24 bits. int left = sLen - eLen; // 0 - 2. if (left > 0) { // Prepare the int int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); // Set last four chars dArr[dLen - 4] = (byte) CA[i >> 12]; dArr[dLen - 3] = (byte) CA[(i >>> 6) & 0x3f]; dArr[dLen - 2] = left == 2 ? (byte) CA[i & 0x3f] : (byte) "="; dArr[dLen - 1] = "="; } return dArr; } /** Decodes a BASE64 encoded byte array. All illegal characters will be ignored and can handle both arrays with * and without line separators. * @param sArr The source array. Length 0 will return an empty array.null
will throw an exception. * @return The decoded array of bytes. May be of length 0. Will benull
if the legal characters * (including "=") isn"t divideable by 4. (I.e. definitely corrupted). */ public final static byte[] decode(byte[] sArr) { // Check special case int sLen = sArr.length; // Count illegal characters (including "\r", "\n") to know what size the returned array will be, // so we don"t have to reallocate & copy it later. int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that"s a bonus...) for (int i = 0; i < sLen; ++i) { if (IA[sArr[i] & 0xff] < 0) { ++sepCnt; } } // Check so that legal chars (including "=") are evenly divideable by 4 as specified in RFC 2045. if ((sLen - sepCnt) % 4 != 0) { return null; } int pad = 0; for (int i = sLen; i > 1 && IA[sArr[--i] & 0xff] <= 0;) { if (sArr[i] == "=") { ++pad; } } int len = ((sLen - sepCnt) * 6 >> 3) - pad; byte[] dArr = new byte[len]; // Preallocate byte[] of exact length for (int s = 0, d = 0; d < len;) { // Assemble three bytes into an int from four "valid" characters. int i = 0; for (int j = 0; j < 4; ++j) { // j only increased if a valid char was found. int c = IA[sArr[s++] & 0xff]; if (c >= 0) { i |= c << (18 - j * 6); } else { --j; } } // Add the bytes dArr[d++] = (byte) (i >> 16); if (d < len) { dArr[d++]= (byte) (i >> 8); if (d < len) { dArr[d++] = (byte) i; } } } return dArr; }
/* * Decodes a BASE64 encoded byte array that is known to be resonably well formatted. The method is about twice as * fast as {@link #decode(byte[])}. The preconditions are:
* + The array must have a line length of 76 chars OR no line separators at all (one line).
* + Line separator must be "\r\n", as specified in RFC 2045 * + The array must not contain illegal characters within the encoded string
* + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
* @param sArr The source array. Length 0 will return an empty array.null
will throw an exception. * @return The decoded array of bytes. May be of length 0. * / public final static byte[] decodeFast(byte[] sArr) { // Check special case int sLen = sArr.length; if (sLen == 0) { return new byte[0]; } int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. // Trim illegal chars from start while (sIx < eIx && IA[sArr[sIx] & 0xff] < 0) { ++sIx; } // Trim illegal chars from end while (eIx > 0 && IA[sArr[eIx] & 0xff] < 0) { --eIx; } // get the padding count (=) (0, 1 or 2) int pad = sArr[eIx] == "=" ? (sArr[eIx - 1] == "=" ? 2 : 1) : 0; // Count "=" at end. int cCnt = eIx - sIx + 1; // Content count including possible separators int sepCnt = sLen > 76 ? (sArr[76] == "\r" ? cCnt / 78 : 0) << 1 : 0; int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes byte[] dArr = new byte[len]; // Preallocate byte[] of exact length // Decode all but the last 0 - 2 bytes. int d = 0; for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { // Assemble three bytes into an int from four "valid" characters. int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; // Add the bytes dArr[d++] = (byte) (i >> 16); dArr[d++] = (byte) (i >> 8); dArr[d++] = (byte) i; // If line separator, jump over it. if (sepCnt > 0 && ++cc == 19) { sIx += 2; cc = 0; } } if (d < len) { // Decode last 1-3 bytes (incl "=") into 1-3 bytes int i = 0; for (int j = 0; sIx <= eIx - pad; ++j) { i |= IA[sArr[sIx++]] << (18 - j * 6); } for (int r = 16; d < len; r -= 8) { dArr[d++] = (byte) (i >> r); } } return dArr; }*/ // **************************************************************************************** // * String version // **************************************************************************************** /** Encodes a raw byte array into a BASE64String
representation i accordance with RFC 2045. * @param sArr The bytes to convert. Ifnull
or length 0 an empty array will be returned. * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
* No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a * little faster. * @return A BASE64 encoded array. Nevernull
. */ public final static String encodeToString(byte[] sArr, boolean lineSep) { // Reuse char[] since we can"t create a String incrementally anyway and StringBuffer/Builder would be slower. return new String(encodeToChar(sArr, lineSep)); } /** Decodes a BASE64 encodedString
. All illegal characters will be ignored and can handle both strings with * and without line separators.
* Note! It can be up to about 2x the speed to calldecode(str.toCharArray())
instead. That * will create a temporary array though. This version will usestr.charAt(i)
to iterate the string. * @param str The source string.null
or length 0 will return an empty array. * @return The decoded array of bytes. May be of length 0. Will benull
if the legal characters * (including "=") isn"t divideable by 4. (I.e. definitely corrupted). */ public final static byte[] decode(String str) { // Check special case int sLen = str != null ? str.length() : 0; if (sLen == 0) { return new byte[0]; } //assert str != null; // Count illegal characters (including "\r", "\n") to know what size the returned array will be, // so we don"t have to reallocate & copy it later. int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that"s a bonus...) for (int i = 0; i < sLen; ++i) { if (IA[str.charAt(i)] < 0) { ++sepCnt; } } // Check so that legal chars (including "=") are evenly divideable by 4 as specified in RFC 2045. if ((sLen - sepCnt) % 4 != 0) { return null; } // Count "=" at end int pad = 0; for (int i = sLen; i > 1 && IA[str.charAt(--i)] <= 0;) { if (str.charAt(i) == "=") { ++pad; } } int len = ((sLen - sepCnt) * 6 >> 3) - pad; byte[] dArr = new byte[len]; // Preallocate byte[] of exact length for (int s = 0, d = 0; d < len;) { // Assemble three bytes into an int from four "valid" characters. int i = 0; for (int j = 0; j < 4; ++j) { // j only increased if a valid char was found. int c = IA[str.charAt(s++)]; if (c >= 0) { i |= c << (18 - j * 6); } else { --j; } } // Add the bytes dArr[d++] = (byte) (i >> 16); if (d < len) { dArr[d++]= (byte) (i >> 8); if (d < len) { dArr[d++] = (byte) i; } } } return dArr; } /* * Decodes a BASE64 encoded string that is known to be resonably well formatted. The method is about twice as * fast as {@link #decode(String)}. The preconditions are:
* + The array must have a line length of 76 chars OR no line separators at all (one line).
* + Line separator must be "\r\n", as specified in RFC 2045 * + The array must not contain illegal characters within the encoded string
* + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
* @param s The source string. Length 0 will return an empty array.null
will throw an exception. * @return The decoded array of bytes. May be of length 0. * / public final static byte[] decodeFast(String s) { // Check special case int sLen = s.length(); if (sLen == 0) { return new byte[0]; } int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. // Trim illegal chars from start while (sIx < eIx && IA[s.charAt(sIx) & 0xff] < 0) { ++sIx; } // Trim illegal chars from end while (eIx > 0 && IA[s.charAt(eIx) & 0xff] < 0) { --eIx; } // get the padding count (=) (0, 1 or 2) int pad = s.charAt(eIx) == "=" ? (s.charAt(eIx - 1) == "=" ? 2 : 1) : 0; // Count "=" at end. int cCnt = eIx - sIx + 1; // Content count including possible separators int sepCnt = sLen > 76 ? (s.charAt(76) == "\r" ? cCnt / 78 : 0) << 1 : 0; int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes byte[] dArr = new byte[len]; // Preallocate byte[] of exact length // Decode all but the last 0 - 2 bytes. int d = 0; for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { // Assemble three bytes into an int from four "valid" characters. int i = IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12 | IA[s.charAt(sIx++)] << 6 | IA[s.charAt(sIx++)]; // Add the bytes dArr[d++] = (byte) (i >> 16); dArr[d++] = (byte) (i >> 8); dArr[d++] = (byte) i; // If line separator, jump over it. if (sepCnt > 0 && ++cc == 19) { sIx += 2; cc = 0; } } if (d < len) { // Decode last 1-3 bytes (incl "=") into 1-3 bytes int i = 0; for (int j = 0; sIx <= eIx - pad; ++j) { i |= IA[s.charAt(sIx++)] << (18 - j * 6); } for (int r = 16; d < len; r -= 8) { dArr[d++] = (byte) (i >> r); } } return dArr; }*/
}
</source>
array of byte to encode
<source lang="java">
/* Copyright 2004 The Apache Software Foundation
* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
//xmlbeans import java.io.UnsupportedEncodingException; /**
* format validation * * This class encodes/decodes hexadecimal data * @author Jeffrey Rodriguez * @version $Id: HexBin.java 125124 2005-01-14 00:23:54Z kkrouse $ */
public class Main {
static private final int BASELENGTH = 255; static private final int LOOKUPLENGTH = 16; static private byte [] hexNumberTable = new byte[BASELENGTH]; static private byte [] lookUpHexAlphabet = new byte[LOOKUPLENGTH];
static { for (int i = 0; i<BASELENGTH; i++ ) { hexNumberTable[i] = -1; } for ( int i = "9"; i >= "0"; i--) { hexNumberTable[i] = (byte) (i-"0"); } for ( int i = "F"; i>= "A"; i--) { hexNumberTable[i] = (byte) ( i-"A" + 10 ); } for ( int i = "f"; i>= "a"; i--) { hexNumberTable[i] = (byte) ( i-"a" + 10 ); } for(int i = 0; i<10; i++ ) lookUpHexAlphabet[i] = (byte) ("0"+i ); for(int i = 10; i<=15; i++ ) lookUpHexAlphabet[i] = (byte) ("A"+i -10); } /** * array of byte to encode * * @param binaryData * @return return encode binary array */ static public byte[] encode(byte[] binaryData) { if (binaryData == null) return null; int lengthData = binaryData.length; int lengthEncode = lengthData * 2; byte[] encodedData = new byte[lengthEncode]; for( int i = 0; i<lengthData; i++ ){ encodedData[i*2] = lookUpHexAlphabet[(binaryData[i] >> 4) & 0xf]; encodedData[i*2+1] = lookUpHexAlphabet[ binaryData[i] & 0xf]; } return encodedData; }
}
</source>
Base64 Character encoder as specified in RFC1113
<source lang="java">
/*
* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
/* $Id: Base64EncodeStream.java 447277 2006-09-18 06:19:34Z jeremias $ */
import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; /**
* This class implements a Base64 Character encoder as specified in RFC1113. * Unlike some other encoding schemes there is nothing in this encoding * that indicates where a buffer starts or ends. * * This means that the encoded text will simply start with the first line * of encoded text and end with the last line of encoded text. * * @author * @author Chuck McManis * @version $Id: Base64EncodeStream.java 447277 2006-09-18 06:19:34Z jeremias $ */
public class Base64EncodeStream extends OutputStream {
/** This array maps the 6 bit values to their characters */ private final static byte pem_array[] = { // 0 1 2 3 4 5 6 7 "A","B","C","D","E","F","G","H", // 0 "I","J","K","L","M","N","O","P", // 1 "Q","R","S","T","U","V","W","X", // 2 "Y","Z","a","b","c","d","e","f", // 3 "g","h","i","j","k","l","m","n", // 4 "o","p","q","r","s","t","u","v", // 5 "w","x","y","z","0","1","2","3", // 6 "4","5","6","7","8","9","+","/" // 7 }; byte [] atom = new byte[3]; int atomLen = 0; byte [] encodeBuf = new byte[4]; int lineLen = 0; PrintStream out; boolean closeOutOnClose; public Base64EncodeStream(OutputStream out) { this.out = new PrintStream(out); closeOutOnClose = true; } public Base64EncodeStream(OutputStream out, boolean closeOutOnClose) { this.out = new PrintStream(out); this.closeOutOnClose = closeOutOnClose; } public void close () throws IOException { if (out != null) { encodeAtom(); out.flush(); if (closeOutOnClose) out.close(); out=null; } } /** * This can"t really flush out output since that may generate * "=" chars which would indicate the end of the stream. * Instead we flush out. You can only be sure all output is * writen by closing this stream. */ public void flush() throws IOException { out.flush(); } public void write(int b) throws IOException { atom[atomLen++] = (byte)b; if (atomLen == 3) encodeAtom(); } public void write(byte []data) throws IOException { encodeFromArray(data, 0, data.length); } public void write(byte [] data, int off, int len) throws IOException { encodeFromArray(data, off, len); } /** * enocodeAtom - Take three bytes of input and encode it as 4 * printable characters. Note that if the length in len is less * than three is encodes either one or two "=" signs to indicate * padding characters. */ void encodeAtom() throws IOException { byte a, b, c; switch (atomLen) { case 0: return; case 1: a = atom[0]; encodeBuf[0] = pem_array[((a >>> 2) & 0x3F)]; encodeBuf[1] = pem_array[((a << 4) & 0x30)]; encodeBuf[2] = encodeBuf[3] = "="; break; case 2: a = atom[0]; b = atom[1]; encodeBuf[0] = pem_array[((a >>> 2) & 0x3F)]; encodeBuf[1] = pem_array[(((a << 4) & 0x30) | ((b >>> 4) & 0x0F))]; encodeBuf[2] = pem_array[((b << 2) & 0x3C)]; encodeBuf[3] = "="; break; default: a = atom[0]; b = atom[1]; c = atom[2]; encodeBuf[0] = pem_array[((a >>> 2) & 0x3F)]; encodeBuf[1] = pem_array[(((a << 4) & 0x30) | ((b >>> 4) & 0x0F))]; encodeBuf[2] = pem_array[(((b << 2) & 0x3C) | ((c >>> 6) & 0x03))]; encodeBuf[3] = pem_array[c & 0x3F]; } if (lineLen == 64) { out.println(); lineLen = 0; } out.write(encodeBuf); lineLen += 4; atomLen = 0; } /** * enocodeAtom - Take three bytes of input and encode it as 4 * printable characters. Note that if the length in len is less * than three is encodes either one or two "=" signs to indicate * padding characters. */ void encodeFromArray(byte[] data, int offset, int len) throws IOException{ byte a, b, c; if (len == 0) return; // System.out.println("atomLen: " + atomLen + // " len: " + len + // " offset: " + offset); if (atomLen != 0) { switch(atomLen) { case 1: atom[1] = data[offset++]; len--; atomLen++; if (len == 0) return; atom[2] = data[offset++]; len--; atomLen++; break; case 2: atom[2] = data[offset++]; len--; atomLen++; break; default: } encodeAtom(); } while (len >=3) { a = data[offset++]; b = data[offset++]; c = data[offset++]; encodeBuf[0] = pem_array[((a >>> 2) & 0x3F)]; encodeBuf[1] = pem_array[(((a << 4) & 0x30) | ((b >>> 4) & 0x0F))]; encodeBuf[2] = pem_array[(((b << 2) & 0x3C) | ((c >>> 6) & 0x03))]; encodeBuf[3] = pem_array[c & 0x3F]; out.write(encodeBuf); lineLen += 4; if (lineLen == 64) { out.println(); lineLen = 0; } len -=3; } switch (len) { case 1: atom[0] = data[offset]; break; case 2: atom[0] = data[offset]; atom[1] = data[offset+1]; break; default: } atomLen = len; }
}
</source>
Base64 encoder/decoder
<source lang="java">
/*************************************************************** Copyright (c) 1998, 1999 Nate Sammons <nate@protomatter.ru> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Contact support@protomatter.ru with your questions, comments, gripes, praise, etc...
- /
/***************************************************************
- moved to the net.matuschek.util tree by Daniel Matuschek - replaced deprecated getBytes() method in method decode - added String encode(String) method to encode a String to base64 ***************************************************************/
/**
* Base64 encoder/decoder. Does not stream, so be careful with * using large amounts of data * * @author Nate Sammons * @author Daniel Matuschek * @version $Id: Base64.java,v 1.4 2001/04/17 10:09:27 matuschd Exp $ */
public class Base64 {
private Base64() { super(); } /** * Encode some data and return a String. */ public final static String encode(byte[] d) { if (d == null) return null; byte data[] = new byte[d.length+2]; System.arraycopy(d, 0, data, 0, d.length); byte dest[] = new byte[(data.length/3)*4]; // 3-byte to 4-byte conversion for (int sidx = 0, didx=0; sidx < d.length; sidx += 3, didx += 4) { dest[didx] = (byte) ((data[sidx] >>> 2) & 077); dest[didx+1] = (byte) ((data[sidx+1] >>> 4) & 017 | (data[sidx] << 4) & 077); dest[didx+2] = (byte) ((data[sidx+2] >>> 6) & 003 | (data[sidx+1] << 2) & 077); dest[didx+3] = (byte) (data[sidx+2] & 077); } // 0-63 to ascii printable conversion for (int idx = 0; idx <dest.length; idx++) { if (dest[idx] < 26) dest[idx] = (byte)(dest[idx] + "A"); else if (dest[idx] < 52) dest[idx] = (byte)(dest[idx] + "a" - 26); else if (dest[idx] < 62) dest[idx] = (byte)(dest[idx] + "0" - 52); else if (dest[idx] < 63) dest[idx] = (byte)"+"; else dest[idx] = (byte)"/"; } // add padding for (int idx = dest.length-1; idx > (d.length*4)/3; idx--) { dest[idx] = (byte)"="; } return new String(dest); } /** * Encode a String using Base64 using the default platform encoding **/ public final static String encode(String s) { return encode(s.getBytes()); } /** * Decode data and return bytes. */ public final static byte[] decode(String str) { if (str == null) return null; byte data[] = str.getBytes(); return decode(data); } /** * Decode data and return bytes. Assumes that the data passed * in is ASCII text. */ public final static byte[] decode(byte[] data) { int tail = data.length; while (data[tail-1] == "=") tail--; byte dest[] = new byte[tail - data.length/4]; // ascii printable to 0-63 conversion for (int idx = 0; idx <data.length; idx++) { if (data[idx] == "=") data[idx] = 0; else if (data[idx] == "/") data[idx] = 63; else if (data[idx] == "+") data[idx] = 62; else if (data[idx] >= "0" && data[idx] <= "9") data[idx] = (byte)(data[idx] - ("0" - 52)); else if (data[idx] >= "a" && data[idx] <= "z") data[idx] = (byte)(data[idx] - ("a" - 26)); else if (data[idx] >= "A" && data[idx] <= "Z") data[idx] = (byte)(data[idx] - "A"); } // 4-byte to 3-byte conversion int sidx, didx; for (sidx = 0, didx=0; didx < dest.length-2; sidx += 4, didx += 3) { dest[didx] = (byte) ( ((data[sidx] << 2) & 255) | ((data[sidx+1] >>> 4) & 3) ); dest[didx+1] = (byte) ( ((data[sidx+1] << 4) & 255) | ((data[sidx+2] >>> 2) & 017) ); dest[didx+2] = (byte) ( ((data[sidx+2] << 6) & 255) | (data[sidx+3] & 077) ); } if (didx < dest.length) { dest[didx] = (byte) ( ((data[sidx] << 2) & 255) | ((data[sidx+1] >>> 4) & 3) ); } if (++didx < dest.length) { dest[didx] = (byte) ( ((data[sidx+1] << 4) & 255) | ((data[sidx+2] >>> 2) & 017) ); } return dest; } /** * A simple test that encodes and decodes the first commandline argument. */ public static final void main(String[] args) { if (args.length != 1) { System.out.println("Usage: Base64 string"); System.exit(0); } try { String e = Base64.encode(args[0].getBytes()); String d = new String(Base64.decode(e)); System.out.println("Input = "" + args[0] + """); System.out.println("Encoded = "" + e + """); System.out.println("Decoded = "" + d + """); } catch (Exception x) { x.printStackTrace(); } }
}
</source>
BASE64 encoder implementation
<source lang="java">
/*
* Copyright � World Wide Web Consortium, (Massachusetts Institute of Technology, * Institut National de Recherche en Informatique et en Automatique, Keio University). * All Rights Reserved. http://www.w3.org/Consortium/Legal/ */
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; /**
* BASE64 encoder implementation. * This object takes as parameter an input stream and an output stream. It * encodes the input stream, using the BASE64 encoding rules, as defined * in * and emit the resulting data to the output stream. * @see org.w3c.tools.codec.Base64Decoder */
public class Base64Encoder {
private static final int BUFFER_SIZE = 1024; private static byte encoding[] = { (byte) "A", (byte) "B", (byte) "C", (byte) "D", (byte) "E", (byte) "F", (byte) "G", (byte) "H", // 0-7 (byte) "I", (byte) "J", (byte) "K", (byte) "L", (byte) "M", (byte) "N", (byte) "O", (byte) "P", // 8-15 (byte) "Q", (byte) "R", (byte) "S", (byte) "T", (byte) "U", (byte) "V", (byte) "W", (byte) "X", // 16-23 (byte) "Y", (byte) "Z", (byte) "a", (byte) "b", (byte) "c", (byte) "d", (byte) "e", (byte) "f", // 24-31 (byte) "g", (byte) "h", (byte) "i", (byte) "j", (byte) "k", (byte) "l", (byte) "m", (byte) "n", // 32-39 (byte) "o", (byte) "p", (byte) "q", (byte) "r", (byte) "s", (byte) "t", (byte) "u", (byte) "v", // 40-47 (byte) "w", (byte) "x", (byte) "y", (byte) "z", (byte) "0", (byte) "1", (byte) "2", (byte) "3", // 48-55 (byte) "4", (byte) "5", (byte) "6", (byte) "7", (byte) "8", (byte) "9", (byte) "+", (byte) "/", // 56-63 (byte) "=" // 64 }; InputStream in = null; OutputStream out = null; boolean stringp = false; private final int get1(byte buf[], int off) { return (buf[off] & 0xfc) >> 2; } private final int get2(byte buf[], int off) { return ((buf[off] & 0x3) << 4) | ((buf[off + 1] & 0xf0) >>> 4); } private final int get3(byte buf[], int off) { return ((buf[off + 1] & 0x0f) << 2) | ((buf[off + 2] & 0xc0) >>> 6); } private static final int get4(byte buf[], int off) { return buf[off + 2] & 0x3f; } /** * Process the data: encode the input stream to the output stream. * This method runs through the input stream, encoding it to the output * stream. * @exception IOException If we weren"t able to access the input stream or * the output stream. */ public void process() throws IOException { byte buffer[] = new byte[BUFFER_SIZE]; int got = -1; int off = 0; int count = 0; while ((got = in.read(buffer, off, BUFFER_SIZE - off)) > 0) { if (got >= 3) { got += off; off = 0; while (off + 3 <= got) { int c1 = get1(buffer, off); int c2 = get2(buffer, off); int c3 = get3(buffer, off); int c4 = get4(buffer, off); switch (count) { case 73 : out.write(encoding[c1]); out.write(encoding[c2]); out.write(encoding[c3]); out.write("\n"); out.write(encoding[c4]); count = 1; break; case 74 : out.write(encoding[c1]); out.write(encoding[c2]); out.write("\n"); out.write(encoding[c3]); out.write(encoding[c4]); count = 2; break; case 75 : out.write(encoding[c1]); out.write("\n"); out.write(encoding[c2]); out.write(encoding[c3]); out.write(encoding[c4]); count = 3; break; case 76 : out.write("\n"); out.write(encoding[c1]); out.write(encoding[c2]); out.write(encoding[c3]); out.write(encoding[c4]); count = 4; break; default : out.write(encoding[c1]); out.write(encoding[c2]); out.write(encoding[c3]); out.write(encoding[c4]); count += 4; break; } off += 3; } // Copy remaining bytes to beginning of buffer: for (int i = 0; i < 3; i++) buffer[i] = (i < got - off) ? buffer[off + i] : ((byte) 0); off = got - off; } else { // Total read amount is less then 3 bytes: off += got; } } // Manage the last bytes, from 0 to off: switch (off) { case 1 : out.write(encoding[get1(buffer, 0)]); out.write(encoding[get2(buffer, 0)]); out.write("="); out.write("="); break; case 2 : out.write(encoding[get1(buffer, 0)]); out.write(encoding[get2(buffer, 0)]); out.write(encoding[get3(buffer, 0)]); out.write("="); } return; } /** * Encode the content of this encoder, as a string. * This methods encode the String content, that was provided at creation * time, following the BASE64 rules, as specified in the rfc1521. * @return A String, reprenting the encoded content of the input String. */ public String processString() { if (!stringp) throw new RuntimeException( this.getClass().getName() + "[processString]" + "invalid call (not a String)"); try { process(); } catch (IOException e) { } return ((ByteArrayOutputStream) out).toString(); } /** * Create a new Base64 encoder, to encode the given string. * @param input The String to be encoded. */ public Base64Encoder(String input) { byte bytes[]; try { bytes = input.getBytes("ISO-8859-1"); } catch (UnsupportedEncodingException ex) { throw new RuntimeException( this.getClass().getName() + "[Constructor] Unable to convert" + "properly char to bytes"); } this.stringp = true; this.in = new ByteArrayInputStream(bytes); this.out = new ByteArrayOutputStream(); } /** * Create a new Base64 encoder, encoding input to output. * @param in The input stream to be encoded. * @param out The output stream, to write encoded data to. */ public Base64Encoder(InputStream in, OutputStream out) { this.in = in; this.out = out; this.stringp = false; } /** * Testing the encoder. * Run with one argument, prints the encoded version of it. */ public static void main(String args[]) { if (args.length != 1) { System.out.println("Base64Encoder <string>"); System.exit(0); } Base64Encoder b = new Base64Encoder(args[0]); System.out.println("[" + b.processString() + "]"); // joe:eoj -> am9lOmVvag== // 12345678:87654321 -> MTIzNDU2Nzg6ODc2NTQzMjE= }
}
</source>
Base-64 Encoder - translates from base-64 text into binary
<source lang="java">
/*
* Base64Encoder.java * * Created on 20 December 2005, 11:15 * */
import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; /**
* <p>Base-64 Encoder - translates from base-64 text into binary. *Whitespace is ignored, so is anything following a terminating = * character.
* @author Malcolm McMahon * @version $Revision: 1.1 $ */
public class Base64Encoder extends CharsetEncoder {
final static int CHARCODE_INVALID = -1; final static int CHARCODE_PADDER = -2; final static int CHARCODE_WHITESPACE = -3; int[] encTable; int encState; Byte excessByte; int bits; /** Creates a new instance of Base64Encoder * @param cs The Charset which created this * @param encTable Table which maps chacacters onto 6 bit values. */ public Base64Encoder(Charset cs, int[] encTable) { super(cs, 1.4f, 2f); this.encTable = encTable; } private boolean out(ByteBuffer bb, int outValue) { if(bb.remaining() > 0) { bb.put((byte)outValue); return true; } else { excessByte = Byte.valueOf((byte)outValue); return false; } } /** * Flushes this encoder. **
The default implementation of this method does nothing, and always * returns {@link CoderResult#UNDERFLOW}. This method should be overridden * by encoders that may need to write final bytes to the output buffer * once the entire input sequence has been read.
* * @param out * The output byte buffer * * @return A coder-result object, either {@link CoderResult#UNDERFLOW} or * {@link CoderResult#OVERFLOW} */ protected java.nio.charset.CoderResult implFlush(java.nio.ByteBuffer out) { if(encState != 0 && encState != 4) throw new IllegalArgumentException("Base-64 text ends prematurely"); if(excessByte == null) { implReset(); return CoderResult.UNDERFLOW; } if(out.remaining() > 0) { out.put(excessByte.byteValue()); implReset(); return CoderResult.UNDERFLOW; } else return CoderResult.OVERFLOW; } /** * Encodes one or more characters into one or more bytes. **
This method encapsulates the basic encoding loop, encoding as many * characters as possible until it either runs out of input, runs out of room * in the output buffer, or encounters an encoding error. This method is * invoked by the {@link #encode encode} method, which handles result * interpretation and error recovery. * * <p> The buffers are read from, and written to, starting at their current * positions. At most {@link Buffer#remaining in.remaining()} characters * will be read, and at most {@link Buffer#remaining out.remaining()} * bytes will be written. The buffers" positions will be advanced to * reflect the characters read and the bytes written, but their marks and * limits will not be modified. * * <p> This method returns a {@link CoderResult} object to describe its * reason for termination, in the same manner as the {@link #encode encode} * method. Most implementations of this method will handle encoding errors * by returning an appropriate result object for interpretation by the * {@link #encode encode} method. An optimized implementation may instead * examine the relevant error action and implement that action itself. * * <p> An implementation of this method may perform arbitrary lookahead by * returning {@link CoderResult#UNDERFLOW} until it receives sufficient * input.
* * @param in * The input character buffer * * @param out * The output byte buffer * * @return A coder-result object describing the reason for termination */ public java.nio.charset.CoderResult encodeLoop(java.nio.CharBuffer in, java.nio.ByteBuffer out) { if(excessByte != null) { if(out.remaining() > 0) { out.put(excessByte.byteValue()); excessByte = null; } else return CoderResult.OVERFLOW; } while(in.remaining() > 0) { char inch = in.get(); int code = (int)inch >= encTable.length ? CHARCODE_INVALID : encTable[(int)inch]; if(encState < 4) { switch(code) { case CHARCODE_INVALID: throw new IllegalArgumentException("Invalid base-64 character"" + inch + """ ); case CHARCODE_WHITESPACE: break; case CHARCODE_PADDER: if(encState == 1) throw new IllegalArgumentException("Mal-formed base-64 (= after one character"); encState = 4; break; default: switch(encState) { case 0: bits = code << 2; encState = 1; break; case 1: encState = 2; int v = bits | ((code >> 4) & 3); bits = (code << 4) & 0xF0; if(!out(out, v)) return CoderResult.OVERFLOW; break; case 2: encState = 3; v = bits | (code >> 2) & 0x0f; bits = (code << 6) & 0xC0; if(!out(out, v)) return CoderResult.OVERFLOW; break; case 3: encState = 0; bits |= (code & 0x3f); if(!out(out, bits)) return CoderResult.OVERFLOW; break; } break; } } } return CoderResult.UNDERFLOW; } /** * Reset - clear encoder state */ protected void implReset() { encState = 0; bits = 0; excessByte = null; }
}
</source>
Base64 encoding/decoding.
<source lang="java">
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common * Development and Distribution License("CDDL") (collectively, the * "License"). You may not use this file except in compliance with the * License. You can obtain a copy of the License at * http://www.netbeans.org/cddl-gplv2.html * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the * specific language governing permissions and limitations under the * License. When distributing the software, include this License Header * Notice in each file and include the License file at * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the * License Header, with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * Contributor(s): * * The Original Software is NetBeans. The Initial Developer of the Original * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun * Microsystems, Inc. All Rights Reserved. * * If you wish your version of this file to be governed by only the CDDL * or only the GPL Version 2, indicate your decision by adding * "[Contributor] elects to include this software in this distribution * under the [CDDL or GPL Version 2] license." If you do not indicate a * single choice of license, a recipient has the option to distribute * your version of this file under either the CDDL, the GPL Version 2 or * to extend the choice of license to its licensees as provided above. * However, if you add GPL Version 2 code and therefore, elected the GPL * Version 2 license, then the option applies only if the new code is * made subject to such option by the copyright holder. */
/** This class provides Base64 encoding/decoding.
*/
public class Base64 {
private Base64() { //Avoid instantiation of this class } /** Encodes datas using base64 encoding. * @param abyte0 data for encoding * @return encoded string */ static String encode(final byte abyte0[]) { final StringBuffer stringbuffer = new StringBuffer(); for(int i = 0; i < abyte0.length; i += 3) stringbuffer.append(encodeBlock(abyte0, i)); return stringbuffer.toString(); } private static char[] encodeBlock(final byte abyte0[], final int i) { int j = 0; final int k = abyte0.length - i - 1; final int l = k < 2 ? k : 2; for(int i1 = 0; i1 <= l; i1++) { final byte byte0 = abyte0[i + i1]; final int j1 = byte0 >= 0 ? ((int) (byte0)) : byte0 + 256; j += j1 << 8 * (2 - i1); } char ac[] = new char[4]; for(int k1 = 0; k1 < 4; k1++) { final int l1 = j >>> 6 * (3 - k1) & 0x3f; ac[k1] = getChar(l1); } if(k < 1) ac[2] = "="; if(k < 2) ac[3] = "="; return ac; } private static char getChar(final int i) { if(i >= 0 && i <= 25) return (char)(65 + i); if(i >= 26 && i <= 51) return (char)(97 + (i - 26)); if(i >= 52 && i <= 61) return (char)(48 + (i - 52)); if(i == 62) return "+"; return i != 63 ? "?" : "/"; } /** Decode string using Base64 encoding. * @param s string for decoding * @return decoded data */ static byte[] decode(final String s) { if (s.length() == 0) return new byte[0]; int i = 0; for(int j = s.length() - 1; j > 0 && s.charAt(j) == "="; j--) i++; final int k = (s.length() * 6) / 8 - i; byte abyte0[] = new byte[k]; int l = 0; for(int i1 = 0; i1 < s.length(); i1 += 4) { final int j1 = (getValue(s.charAt(i1)) << 18) + (getValue(s.charAt(i1 + 1)) << 12) + (getValue(s.charAt(i1 + 2)) << 6) + getValue(s.charAt(i1 + 3)); for(int k1 = 0; k1 < 3 && l + k1 < abyte0.length; k1++) abyte0[l + k1] = (byte)(j1 >> 8 * (2 - k1) & 0xff); l += 3; } return abyte0; } private static int getValue(final char c) { if(c >= "A" && c <= "Z") return c - 65; if(c >= "a" && c <= "z") return (c - 97) + 26; if(c >= "0" && c <= "9") return (c - 48) + 52; if(c == "+") return 62; if(c == "/") return 63; return c != "=" ? -1 : 0; }
}
</source>
Base64 from by Funambol, Inc.
<source lang="java">
/*
* Funambol is a mobile platform developed by Funambol, Inc. * Copyright (C) 2003 - 2007 Funambol, Inc. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation with the addition of the following permission * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program; if not, see http://www.gnu.org/licenses or write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA. * * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite * 305, Redwood City, CA 94063, USA, or at email address info@funambol.ru. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License * version 3, these Appropriate Legal Notices must retain the display of the * "Powered by Funambol" logo. If the display of the logo is not reasonably * feasible for technical reasons, the Appropriate Legal Notices must display * the words "Powered by Funambol". */
import java.io.UnsupportedEncodingException; public class Base64 {
private static final byte[] encodingTable = { (byte)"A", (byte)"B", (byte)"C", (byte)"D", (byte)"E", (byte)"F", (byte)"G", (byte)"H", (byte)"I", (byte)"J", (byte)"K", (byte)"L", (byte)"M", (byte)"N", (byte)"O", (byte)"P", (byte)"Q", (byte)"R", (byte)"S", (byte)"T", (byte)"U", (byte)"V", (byte)"W", (byte)"X", (byte)"Y", (byte)"Z", (byte)"a", (byte)"b", (byte)"c", (byte)"d", (byte)"e", (byte)"f", (byte)"g", (byte)"h", (byte)"i", (byte)"j", (byte)"k", (byte)"l", (byte)"m", (byte)"n", (byte)"o", (byte)"p", (byte)"q", (byte)"r", (byte)"s", (byte)"t", (byte)"u", (byte)"v", (byte)"w", (byte)"x", (byte)"y", (byte)"z", (byte)"0", (byte)"1", (byte)"2", (byte)"3", (byte)"4", (byte)"5", (byte)"6", (byte)"7", (byte)"8", (byte)"9", (byte)"+", (byte)"/" };
/** * encode the input data producong a base 64 encoded byte array. * * @return a byte array containing the base 64 encoded data. */ public static byte[] encode(byte[] data) { byte[] bytes; int modulus = data.length % 3; if (modulus == 0) { bytes = new byte[4 * data.length / 3]; } else { bytes = new byte[4 * ((data.length / 3) + 1)]; } int dataLength = (data.length - modulus); int a1, a2, a3; for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) { a1 = data[i] & 0xff; a2 = data[i + 1] & 0xff; a3 = data[i + 2] & 0xff; bytes[j] = encodingTable[(a1 >>> 2) & 0x3f]; bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]; bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]; bytes[j + 3] = encodingTable[a3 & 0x3f]; } /* * process the tail end. */ int b1, b2, b3; int d1, d2; switch (modulus) { case 0: /* nothing left to do */ break; case 1: d1 = data[data.length - 1] & 0xff; b1 = (d1 >>> 2) & 0x3f; b2 = (d1 << 4) & 0x3f; bytes[bytes.length - 4] = encodingTable[b1]; bytes[bytes.length - 3] = encodingTable[b2]; bytes[bytes.length - 2] = (byte)"="; bytes[bytes.length - 1] = (byte)"="; break; case 2: d1 = data[data.length - 2] & 0xff; d2 = data[data.length - 1] & 0xff; b1 = (d1 >>> 2) & 0x3f; b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f; b3 = (d2 << 2) & 0x3f; bytes[bytes.length - 4] = encodingTable[b1]; bytes[bytes.length - 3] = encodingTable[b2]; bytes[bytes.length - 2] = encodingTable[b3]; bytes[bytes.length - 1] = (byte)"="; break; } return bytes; } /* * set up the decoding table. */ private static final byte[] decodingTable; static { decodingTable = new byte[128]; for (int i = 0; i < 128; i++) { decodingTable[i] = (byte)-1; } for (int i = "A"; i <= "Z"; i++) { decodingTable[i] = (byte)(i - "A"); } for (int i = "a"; i <= "z"; i++) { decodingTable[i] = (byte)(i - "a" + 26); } for (int i = "0"; i <= "9"; i++) { decodingTable[i] = (byte)(i - "0" + 52); } decodingTable["+"] = 62; decodingTable["/"] = 63; }
/** * decode the base 64 encoded input data. * * @return a byte array representing the decoded data. */ public static byte[] decode(byte[] data) { byte[] bytes; byte b1, b2, b3, b4; data = discardNonBase64Bytes(data); if (data[data.length - 2] == "=") { bytes = new byte[(((data.length / 4) - 1) * 3) + 1]; } else if (data[data.length - 1] == "=") { bytes = new byte[(((data.length / 4) - 1) * 3) + 2]; } else { bytes = new byte[((data.length / 4) * 3)]; } for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3) { b1 = decodingTable[data[i]]; b2 = decodingTable[data[i + 1]]; b3 = decodingTable[data[i + 2]]; b4 = decodingTable[data[i + 3]]; bytes[j] = (byte)((b1 << 2) | (b2 >> 4)); bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2)); bytes[j + 2] = (byte)((b3 << 6) | b4); } if (data[data.length - 2] == "=") { b1 = decodingTable[data[data.length - 4]]; b2 = decodingTable[data[data.length - 3]]; bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4)); } else if (data[data.length - 1] == "=") { b1 = decodingTable[data[data.length - 4]]; b2 = decodingTable[data[data.length - 3]]; b3 = decodingTable[data[data.length - 2]]; bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2)); } else { b1 = decodingTable[data[data.length - 4]]; b2 = decodingTable[data[data.length - 3]]; b3 = decodingTable[data[data.length - 2]]; b4 = decodingTable[data[data.length - 1]]; bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2)); bytes[bytes.length - 1] = (byte)((b3 << 6) | b4); } return bytes; }
/** * decode the base 64 encoded String data. * * TODO: Use the byte version to avoid duplication? * * @return a byte array representing the decoded data. */ public static byte[] decode(String data) { byte[] bytes; byte b1, b2, b3, b4; data = discardNonBase64Chars(data); if (data.charAt(data.length() - 2) == "=") { bytes = new byte[(((data.length() / 4) - 1) * 3) + 1]; } else if (data.charAt(data.length() - 1) == "=") { bytes = new byte[(((data.length() / 4) - 1) * 3) + 2]; } else { bytes = new byte[((data.length() / 4) * 3)]; } for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3) { b1 = decodingTable[data.charAt(i)]; b2 = decodingTable[data.charAt(i + 1)]; b3 = decodingTable[data.charAt(i + 2)]; b4 = decodingTable[data.charAt(i + 3)]; bytes[j] = (byte)((b1 << 2) | (b2 >> 4)); bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2)); bytes[j + 2] = (byte)((b3 << 6) | b4); } if (data.charAt(data.length() - 2) == "=") { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4)); } else if (data.charAt(data.length() - 1) == "=") { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; b3 = decodingTable[data.charAt(data.length() - 2)]; bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2)); } else { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; b3 = decodingTable[data.charAt(data.length() - 2)]; b4 = decodingTable[data.charAt(data.length() - 1)]; bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2)); bytes[bytes.length - 1] = (byte)((b3 << 6) | b4); } return bytes; } /** * Decode the string and convert back the decoded value into a string * using the specified charset. * Use default encoding if charset is null or invalid. */ public static String decode(String data, String charset) { if (charset == null){ // use default return new String(Base64.decode(data)); } try { return new String(Base64.decode(data), charset); } catch (UnsupportedEncodingException ex) { return new String(Base64.decode(data)); } } /** * Decode the string and convert back the decoded value into a string * using the specified charset. * Use default encoding if charset is null or invalid. */ public static String decode(byte[] data, String charset) { if (charset == null){ // use default return new String(Base64.decode(data)); } try { return new String(Base64.decode(data), charset); } catch (UnsupportedEncodingException ex) { return new String(Base64.decode(data)); } } // --------------------------------------------------------- Private Methods /** * Discards any characters outside of the base64 alphabet (see page 25 of * RFC 2045) "Any characters outside of the base64 alphabet are to be * ignored in base64 encoded data." * * @param data * the base64 encoded data * @return the data, less non-base64 characters. */ private static byte[] discardNonBase64Bytes(byte[] data) { byte temp[] = new byte[data.length]; int bytesCopied = 0; for (int i = 0; i < data.length; i++) { if (isValidBase64Byte(data[i])) { temp[bytesCopied++] = data[i]; } } byte newData[] = new byte[bytesCopied]; System.arraycopy(temp, 0, newData, 0, bytesCopied); return newData; }
/** * Discards any characters outside of the base64 alphabet (see page 25 of * RFC 2045) "Any characters outside of the base64 alphabet are to be * ignored in base64 encoded data." * * @param data * the base64 encoded data * @return the data, less non-base64 characters. */ private static String discardNonBase64Chars(String data) { StringBuffer sb = new StringBuffer(); int length = data.length(); for (int i = 0; i < length; i++) { if (isValidBase64Byte((byte)(data.charAt(i)))) { sb.append(data.charAt(i)); } } return sb.toString(); }
/** * Checks is the given byte is in base64 alphabet * * @param b * the byte to check * @return boolean true if the byte is in base64 alphabet */ private static boolean isValidBase64Byte(byte b) { if (b == "=") { return true; } else if (b < 0 || b >= 128) { return false; } else if (decodingTable[b] == -1) { return false; } return true; }
}
</source>
Base64 Utils
<source lang="java">
// Revised act soap util; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; import java.io.ByteArrayOutputStream; public class Base64Utils {
private static final char[] S_BASE64CHAR = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/" }; private static final char S_BASE64PAD = "="; private static final byte[] S_DECODETABLE = new byte[128]; static { for (int i = 0; i < S_DECODETABLE.length; i++) { S_DECODETABLE[i] = Byte.MAX_VALUE; } for (int i = 0; i < S_BASE64CHAR.length; i++) { S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i; } } private static int base64Decode0(char[] ibuf, byte[] obuf, int wp) { int outlen = 3; if (ibuf[3] == S_BASE64PAD) { outlen = 2; } if (ibuf[2] == S_BASE64PAD) { outlen = 1; } int b0 = S_DECODETABLE[ibuf[0]]; int b1 = S_DECODETABLE[ibuf[1]]; int b2 = S_DECODETABLE[ibuf[2]]; int b3 = S_DECODETABLE[ibuf[3]]; switch (outlen) { case 1: obuf[wp] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); return 1; case 2: obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); obuf[wp] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf); return 2; case 3: obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); obuf[wp++] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf); obuf[wp] = (byte) (b2 << 6 & 0xc0 | b3 & 0x3f); return 3; default: throw new RuntimeException("Internal Errror"); } } public static byte[] base64Decode(char[] data, int off, int len) { char[] ibuf = new char[4]; int ibufcount = 0; byte[] obuf = new byte[len / 4 * 3 + 3]; int obufcount = 0; for (int i = off; i < off + len; i++) { char ch = data[i]; if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; if (ibufcount == ibuf.length) { ibufcount = 0; obufcount += base64Decode0(ibuf, obuf, obufcount); } } } if (obufcount == obuf.length) { return obuf; } byte[] ret = new byte[obufcount]; System.arraycopy(obuf, 0, ret, 0, obufcount); return ret; } public static byte[] base64Decode(String data) { char[] ibuf = new char[4]; int ibufcount = 0; byte[] obuf = new byte[data.length() / 4 * 3 + 3]; int obufcount = 0; for (int i = 0; i < data.length(); i++) { char ch = data.charAt(i); if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; if (ibufcount == ibuf.length) { ibufcount = 0; obufcount += base64Decode0(ibuf, obuf, obufcount); } } } if (obufcount == obuf.length) { return obuf; } byte[] ret = new byte[obufcount]; System.arraycopy(obuf, 0, ret, 0, obufcount); return ret; } public static byte[] base64Decode(byte[] data) { return base64Decode(data, 0, data.length); } public static byte[] base64Decode(byte[] data, int off, int len) { char[] ibuf = new char[4]; int ibufcount = 0; byte[] obuf = new byte[len / 4 * 3 + 3]; int obufcount = 0; for (int i = off; i < off + len; i++) { char ch = (char) data[i]; if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; if (ibufcount == ibuf.length) { ibufcount = 0; obufcount += base64Decode0(ibuf, obuf, obufcount); } } } if (obufcount == obuf.length) { return obuf; } byte[] ret = new byte[obufcount]; System.arraycopy(obuf, 0, ret, 0, obufcount); return ret; } public static void base64Decode(char[] data, int off, int len, OutputStream ostream) throws IOException { char[] ibuf = new char[4]; int ibufcount = 0; byte[] obuf = new byte[3]; for (int i = off; i < off + len; i++) { char ch = data[i]; if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; if (ibufcount == ibuf.length) { ibufcount = 0; int obufcount = base64Decode0(ibuf, obuf, 0); ostream.write(obuf, 0, obufcount); } } } } public static void base64Decode(String data, OutputStream ostream) throws IOException { char[] ibuf = new char[4]; int ibufcount = 0; byte[] obuf = new byte[3]; for (int i = 0; i < data.length(); i++) { char ch = data.charAt(i); if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; if (ibufcount == ibuf.length) { ibufcount = 0; int obufcount = base64Decode0(ibuf, obuf, 0); ostream.write(obuf, 0, obufcount); } } } } public static String base64Encode(byte[] data) { return base64Encode(data, 0, data.length); } public static String base64Encode(byte[] data, int off, int len) { if (len <= 0) { return ""; } char[] out = new char[len / 3 * 4 + 4]; int rindex = off; int windex = 0; int rest = len; while (rest >= 3) { int i = ( (data[rindex] & 0xff) << 16) + ( (data[rindex + 1] & 0xff) << 8) + (data[rindex + 2] & 0xff); out[windex++] = S_BASE64CHAR[i >> 18]; out[windex++] = S_BASE64CHAR[ (i >> 12) & 0x3f]; out[windex++] = S_BASE64CHAR[ (i >> 6) & 0x3f]; out[windex++] = S_BASE64CHAR[i & 0x3f]; rindex += 3; rest -= 3; } if (rest == 1) { int i = data[rindex] & 0xff; out[windex++] = S_BASE64CHAR[i >> 2]; out[windex++] = S_BASE64CHAR[ (i << 4) & 0x3f]; out[windex++] = S_BASE64PAD; out[windex++] = S_BASE64PAD; } else if (rest == 2) { int i = ( (data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); out[windex++] = S_BASE64CHAR[i >> 10]; out[windex++] = S_BASE64CHAR[ (i >> 4) & 0x3f]; out[windex++] = S_BASE64CHAR[ (i << 2) & 0x3f]; out[windex++] = S_BASE64PAD; } return new String(out, 0, windex); } public static void base64Encode(byte[] data, int off, int len, OutputStream ostream) throws IOException { if (len <= 0) { return; } byte[] out = new byte[4]; int rindex = off; int rest = len - off; while (rest >= 3) { int i = ( (data[rindex] & 0xff) << 16) + ( (data[rindex + 1] & 0xff) << 8) + (data[rindex + 2] & 0xff); out[0] = (byte) S_BASE64CHAR[i >> 18]; out[1] = (byte) S_BASE64CHAR[ (i >> 12) & 0x3f]; out[2] = (byte) S_BASE64CHAR[ (i >> 6) & 0x3f]; out[3] = (byte) S_BASE64CHAR[i & 0x3f]; ostream.write(out, 0, 4); rindex += 3; rest -= 3; } if (rest == 1) { int i = data[rindex] & 0xff; out[0] = (byte) S_BASE64CHAR[i >> 2]; out[1] = (byte) S_BASE64CHAR[ (i << 4) & 0x3f]; out[2] = (byte) S_BASE64PAD; out[3] = (byte) S_BASE64PAD; ostream.write(out, 0, 4); } else if (rest == 2) { int i = ( (data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); out[0] = (byte) S_BASE64CHAR[i >> 10]; out[1] = (byte) S_BASE64CHAR[ (i >> 4) & 0x3f]; out[2] = (byte) S_BASE64CHAR[ (i << 2) & 0x3f]; out[3] = (byte) S_BASE64PAD; ostream.write(out, 0, 4); } } public static void base64Encode(byte[] data, int off, int len, Writer writer) throws IOException { if (len <= 0) { return; } char[] out = new char[4]; int rindex = off; int rest = len - off; int output = 0; while (rest >= 3) { int i = ( (data[rindex] & 0xff) << 16) + ( (data[rindex + 1] & 0xff) << 8) + (data[rindex + 2] & 0xff); out[0] = S_BASE64CHAR[i >> 18]; out[1] = S_BASE64CHAR[ (i >> 12) & 0x3f]; out[2] = S_BASE64CHAR[ (i >> 6) & 0x3f]; out[3] = S_BASE64CHAR[i & 0x3f]; writer.write(out, 0, 4); rindex += 3; rest -= 3; output += 4; if (output % 76 == 0) { writer.write("\n"); } } if (rest == 1) { int i = data[rindex] & 0xff; out[0] = S_BASE64CHAR[i >> 2]; out[1] = S_BASE64CHAR[ (i << 4) & 0x3f]; out[2] = S_BASE64PAD; out[3] = S_BASE64PAD; writer.write(out, 0, 4); } else if (rest == 2) { int i = ( (data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); out[0] = S_BASE64CHAR[i >> 10]; out[1] = S_BASE64CHAR[ (i >> 4) & 0x3f]; out[2] = S_BASE64CHAR[ (i << 2) & 0x3f]; out[3] = S_BASE64PAD; writer.write(out, 0, 4); } }
}
</source>
byte to be tested if it is Base64 alphabet
<source lang="java">
/* Copyright 2004 The Apache Software Foundation
* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
//xmlbeans import java.io.UnsupportedEncodingException; /**
* format validation * * This class encodes/decodes hexadecimal data * @author Jeffrey Rodriguez * @version $Id: HexBin.java 125124 2005-01-14 00:23:54Z kkrouse $ */
public class Main {
static private final int BASELENGTH = 255; static private final int LOOKUPLENGTH = 16; static private byte [] hexNumberTable = new byte[BASELENGTH]; static private byte [] lookUpHexAlphabet = new byte[LOOKUPLENGTH];
static { for (int i = 0; i<BASELENGTH; i++ ) { hexNumberTable[i] = -1; } for ( int i = "9"; i >= "0"; i--) { hexNumberTable[i] = (byte) (i-"0"); } for ( int i = "F"; i>= "A"; i--) { hexNumberTable[i] = (byte) ( i-"A" + 10 ); } for ( int i = "f"; i>= "a"; i--) { hexNumberTable[i] = (byte) ( i-"a" + 10 ); } for(int i = 0; i<10; i++ ) lookUpHexAlphabet[i] = (byte) ("0"+i ); for(int i = 10; i<=15; i++ ) lookUpHexAlphabet[i] = (byte) ("A"+i -10); } /** * byte to be tested if it is Base64 alphabet * * @param octect * @return */ static boolean isHex(byte octect) { return (hexNumberTable[octect] != -1); }
}
</source>
Codes number up to radix 62
<source lang="java">
/*
* Copyright 2000,2005 wingS development team. * * This file is part of wingS (http://wingsframework.org). * * wingS is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * Please see COPYING for the complete licence. */
import java.util.StringTokenizer; /**
* Some string manipulation utilities. * * @author */
public class StringUtil {
private final static char[] ALPHAS = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", }; /** * All possible digits for representing a number as a String * This is conservative and does not include "special" * characters since some browsers don"t handle them right. * The IE for instance seems to be case insensitive in class * names for CSSs. Grrr. */ private final static char[] DIGITS = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", /* This %@&!-IE is case insensitive for certain * URLs and IDs * "A" , "B" , * "C" , "D" , "E" , "F" , "G" , "H" , * "I" , "J" , "K" , "L" , "M" , "N" , * "O" , "P" , "Q" , "R" , "S" , "T" , * "U" , "V" , "W" , "X" , "Y" , "Z" */ }; public static final int MAX_RADIX = DIGITS.length; /** * Codes number up to radix 62. * Note, this method is only public for backward compatiblity. don"t * use it. * * @param minDigits returns a string with a least minDigits digits */ public static String toString(long i, int radix, int minDigits) { char[] buf = new char[65]; radix = Math.min(Math.abs(radix), MAX_RADIX); minDigits = Math.min(buf.length - 1, Math.abs(minDigits));
int charPos = buf.length - 1; boolean negative = (i < 0); if (negative) { i = -i; } while (i >= radix) { buf[charPos--] = DIGITS[(int) (i % radix)]; i /= radix; } buf[charPos] = DIGITS[(int) i]; // if minimum length of the result string is set, pad it with the // zero-representation (that is: "0") while (charPos > buf.length - minDigits) buf[--charPos] = DIGITS[0]; if (negative) { buf[--charPos] = "-"; } return new String(buf, charPos, buf.length - charPos); }
}
</source>
Converting hexadecimal strings
<source lang="java">
/*
* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
/* $Id$ */
/**
* Provides helper functions for converting hexadecimal strings. */
public class HexUtil {
private static final char[] DIGITS = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}; /** * Converts a byte array to a hexadecimal String * @param data the data to encode * @return String the resulting String */ public static final String toHex(byte[] data) { final StringBuffer sb = new StringBuffer(data.length * 2); for (int i = 0; i < data.length; i++) { sb.append(DIGITS[(data[i] >>> 4) & 0x0F]); sb.append(DIGITS[data[i] & 0x0F]); } return sb.toString(); }
}
</source>
Convert to hex from byte arrays and back
<source lang="java">
/**
* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
/**
* Used to convert to hex from byte arrays and back. * * @version $Revision: 1.2 $ */
public final class HexSupport {
private static final String[] HEX_TABLE = new String[]{ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff", }; private static final int[] INT_OFFSETS = new int[]{ 24,16,8,0 }; private HexSupport() { } /** * @param hex * @return */ public static byte[] toBytesFromHex(String hex) { byte rc[] = new byte[hex.length() / 2]; for (int i = 0; i < rc.length; i++) { String h = hex.substring(i * 2, i * 2 + 2); int x = Integer.parseInt(h, 16); rc[i] = (byte) x; } return rc; } /** * @param bytes * @return */ public static String toHexFromBytes(byte[] bytes) { StringBuffer rc = new StringBuffer(bytes.length * 2); for (int i = 0; i < bytes.length; i++) { rc.append(HEX_TABLE[0xFF & bytes[i]]); } return rc.toString(); } /** * * @param value * @param trim if the leading 0"s should be trimmed off. * @return */ public static String toHexFromInt(int value, boolean trim) { StringBuffer rc = new StringBuffer(INT_OFFSETS.length*2); for (int i = 0; i < INT_OFFSETS.length; i++) { int b = 0xFF & (value>>INT_OFFSETS[i]); if( !(trim && b == 0) ) { rc.append(HEX_TABLE[b]); trim=false; } } return rc.toString(); }
}
</source>
Decodes Base64 data into octects
<source lang="java">
/* Copyright 2004 The Apache Software Foundation
* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
import java.io.UnsupportedEncodingException; /**
* This class provides encode/decode for RFC 2045 Base64 as * defined by RFC 2045, N. Freed and N. Borenstein. * RFC 2045: Multipurpose Internet Mail Extensions (MIME) * Part One: Format of Internet Message Bodies. Reference * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt * This class is used by XML Schema binary format validation * * This implementation does not encode/decode streaming * data. You need the data that you will encode/decode * already on a byte arrray. * * * From xmlbeans * @author Jeffrey Rodriguez * @author Sandy Gao * @version $Id: Base64.java 111285 2004-12-08 16:54:26Z cezar $ */
public final class Base64 {
static private final int BASELENGTH = 255; static private final int LOOKUPLENGTH = 64; static private final int TWENTYFOURBITGROUP = 24; static private final int EIGHTBIT = 8; static private final int SIXTEENBIT = 16; //static private final int SIXBIT = 6; static private final int FOURBYTE = 4; static private final int SIGN = -128; static private final byte PAD = ( byte ) "="; static private final boolean fDebug = false; static private byte [] base64Alphabet = new byte[BASELENGTH]; static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; static { for (int i = 0; i<BASELENGTH; i++) { base64Alphabet[i] = -1; } for (int i = "Z"; i >= "A"; i--) { base64Alphabet[i] = (byte) (i-"A"); } for (int i = "z"; i>= "a"; i--) { base64Alphabet[i] = (byte) ( i-"a" + 26); } for (int i = "9"; i >= "0"; i--) { base64Alphabet[i] = (byte) (i-"0" + 52); } base64Alphabet["+"] = 62; base64Alphabet["/"] = 63; for (int i = 0; i<=25; i++) lookUpBase64Alphabet[i] = (byte) ("A"+i ); for (int i = 26, j = 0; i<=51; i++, j++) lookUpBase64Alphabet[i] = (byte) ("a"+ j ); for (int i = 52, j = 0; i<=61; i++, j++) lookUpBase64Alphabet[i] = (byte) ("0" + j ); lookUpBase64Alphabet[62] = (byte) "+"; lookUpBase64Alphabet[63] = (byte) "/"; } protected static boolean isWhiteSpace(byte octect) { return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); } protected static boolean isPad(byte octect) { return (octect == PAD); } protected static boolean isData(byte octect) { return (base64Alphabet[octect] != -1); } protected static boolean isBase64(byte octect) { return (isWhiteSpace(octect) || isPad(octect) || isData(octect)); } /** * Encodes hex octects into Base64 * * @param binaryData Array containing binaryData * @return Encoded Base64 array */ public static byte[] encode(byte[] binaryData) { if (binaryData == null) return null; int lengthDataBits = binaryData.length*EIGHTBIT; int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; byte encodedData[] = null; if (fewerThan24bits != 0) //data not divisible by 24 bit encodedData = new byte[ (numberTriplets + 1 )*4 ]; else // 16 or 8 bit encodedData = new byte[ numberTriplets*4 ]; byte k=0, l=0, b1=0,b2=0,b3=0; int encodedIndex = 0; int dataIndex = 0; int i = 0; if (fDebug) { System.out.println("number of triplets = " + numberTriplets ); } for (i = 0; i<numberTriplets; i++) { dataIndex = i*3; b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; b3 = binaryData[dataIndex + 2]; if (fDebug) { System.out.println( "b1= " + b1 +", b2= " + b2 + ", b3= " + b3 ); } l = (byte)(b2 & 0x0f); k = (byte)(b1 & 0x03); encodedIndex = i*4; byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0); byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc); encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ]; if (fDebug) { System.out.println( "val2 = " + val2 ); System.out.println( "k4 = " + (k<<4)); System.out.println( "vak = " + (val2 | (k<<4))); } encodedData[encodedIndex+1] = lookUpBase64Alphabet[ val2 | ( k<<4 )]; encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | val3 ]; encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ]; } // form integral number of 6-bit groups dataIndex = i*3; encodedIndex = i*4; if (fewerThan24bits == EIGHTBIT) { b1 = binaryData[dataIndex]; k = (byte) ( b1 &0x03 ); if (fDebug) { System.out.println("b1=" + b1); System.out.println("b1<<2 = " + (b1>>2) ); } byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ]; encodedData[encodedIndex + 2] = PAD; encodedData[encodedIndex + 3] = PAD; } else if (fewerThan24bits == SIXTEENBIT) { b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex +1 ]; l = ( byte ) ( b2 &0x0f ); k = ( byte ) ( b1 &0x03 ); byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0); encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ val2 | ( k<<4 )]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ]; encodedData[encodedIndex + 3] = PAD; } return encodedData; } /** * Decodes Base64 data into octects * * @param base64Data Byte array containing Base64 data * @return Array containind decoded data. */ public static byte[] decode(byte[] base64Data) { if (base64Data == null) return null; // remove white spaces base64Data = removeWhiteSpace(base64Data); if (base64Data.length%FOURBYTE != 0) { return null;//should be divisible by four } int numberQuadruple = (base64Data.length/FOURBYTE ); if (numberQuadruple == 0) return new byte[0]; byte decodedData[] = null; byte b1=0,b2=0,b3=0, b4=0;//, marker0=0, marker1=0; byte d1=0,d2=0,d3=0,d4=0; // Throw away anything not in normalizedBase64Data // Adjust size int i = 0; int encodedIndex = 0; int dataIndex = 0; decodedData = new byte[ (numberQuadruple)*3]; for (; i<numberQuadruple-1; i++) { if (!isData( (d1 = base64Data[dataIndex++]) )|| !isData( (d2 = base64Data[dataIndex++]) )|| !isData( (d3 = base64Data[dataIndex++]) )|| !isData( (d4 = base64Data[dataIndex++]) )) return null;//if found "no data" just return null b1 = base64Alphabet[d1]; b2 = base64Alphabet[d2]; b3 = base64Alphabet[d3]; b4 = base64Alphabet[d4]; decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ; decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); decodedData[encodedIndex++] = (byte)( b3<<6 | b4 ); } if (!isData( (d1 = base64Data[dataIndex++]) ) || !isData( (d2 = base64Data[dataIndex++]) )) { return null;//if found "no data" just return null } b1 = base64Alphabet[d1]; b2 = base64Alphabet[d2]; d3 = base64Data[dataIndex++]; d4 = base64Data[dataIndex++]; if (!isData( (d3 ) ) || !isData( (d4 ) )) {//Check if they are PAD characters if (isPad( d3 ) && isPad( d4)) { //Two PAD e.g. 3c[Pad][Pad] if ((b2 & 0xf) != 0)//last 4 bits should be zero return null; byte[] tmp = new byte[ i*3 + 1 ]; System.arraycopy( decodedData, 0, tmp, 0, i*3 ); tmp[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; return tmp; } else if (!isPad( d3) && isPad(d4)) { //One PAD e.g. 3cQ[Pad] b3 = base64Alphabet[ d3 ]; if ((b3 & 0x3 ) != 0)//last 2 bits should be zero return null; byte[] tmp = new byte[ i*3 + 2 ]; System.arraycopy( decodedData, 0, tmp, 0, i*3 ); tmp[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ); tmp[encodedIndex] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); return tmp; } else { return null;//an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data } } else { //No PAD e.g 3cQl b3 = base64Alphabet[ d3 ]; b4 = base64Alphabet[ d4 ]; decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ; decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); decodedData[encodedIndex++] = (byte)( b3<<6 | b4 ); } return decodedData; }
// /** // * Decodes Base64 data into octects // * // * @param base64Data String containing Base64 data // * @return string containing decoded data. // */ // public static String decode(String base64Data) { // if (base64Data == null) // return null; // // byte[] decoded = null; // try { // decoded = decode(base64Data.getBytes("utf-8")); // } // catch(UnsupportedEncodingException e) { // } // finally { // return decoded == null ? null : new String(decoded); // } // } // // /** // * Encodes octects (using utf-8) into Base64 data // * // * @param binaryData String containing Hex data // * @return string containing decoded data. // */ // public static String encode(String binaryData) { // if (binaryData == null) // return null; // // byte[] encoded = null; // try { // encoded = encode(binaryData.getBytes("utf-8")); // } // catch(UnsupportedEncodingException e) {} // finally { // return encoded == null ? null : new String(encoded); // } // }
/** * remove WhiteSpace from MIME containing encoded Base64 data. * * @param data the byte array of base64 data (with WS) * @return the byte array of base64 data (without WS) */ protected static byte[] removeWhiteSpace(byte[] data) { if (data == null) return null; // count characters that"s not whitespace int newSize = 0; int len = data.length; for (int i = 0; i < len; i++) { if (!isWhiteSpace(data[i])) newSize++; } // if no whitespace, just return the input array if (newSize == len) return data; // create the array to return byte[] newArray = new byte[newSize]; int j = 0; for (int i = 0; i < len; i++) { if (!isWhiteSpace(data[i])) newArray[j++] = data[i]; } return newArray; }
}
</source>
Encode and decode data in Base64 format as described in RFC 1521
<source lang="java">
/**************************************************************************
* * A Base64 Encoder/Decoder. * * This class is used to encode and decode data in Base64 format * as described in RFC 1521. **
* Copyright 2003: Christian d"Heureuse, Inventec Informatik AG, Switzerland.
* License: This is "Open Source" software and released under the
*
* <p>
* Version history:
* 2003-07-22 Christian d"Heureuse (chdh): Module created.
* 2005-08-11 chdh: Lincense changed from GPL to LGPL.
*
**************************************************************************/
public class Base64Coder {
// Mapping table from 6-bit nibbles to Base64 characters.
private static char[] map1 = new char[64];
static {
int i = 0;
for (char c = "A"; c <= "Z"; c++)
map1[i++] = c;
for (char c = "a"; c <= "z"; c++)
map1[i++] = c;
for (char c = "0"; c <= "9"; c++)
map1[i++] = c;
map1[i++] = "+";
map1[i++] = "/";
}
// Mapping table from Base64 characters to 6-bit nibbles.
private static byte[] map2 = new byte[128];
static {
for (int i = 0; i < map2.length; i++)
map2[i] = -1;
for (int i = 0; i < 64; i++)
map2[map1[i]] = (byte) i;
}
/**
* Encodes a string into Base64 format.
* No blanks or line breaks are inserted.
* @param s a String to be encoded.
* @return A String with the Base64 encoded data.
*/
public static String encode(String s) {
return new String(encode(s.getBytes()));
}
/**
* Encodes a byte array into Base64 format.
* No blanks or line breaks are inserted.
* @param in an array containing the data bytes to be encoded.
* @return A character array with the Base64 encoded data.
*/
public static char[] encode(byte[] in) {
int iLen = in.length;
int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
int oLen = ((iLen + 2) / 3) * 4; // output length including padding
char[] out = new char[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++] & 0xff;
int i1 = ip < iLen ? in[ip++] & 0xff : 0;
int i2 = ip < iLen ? in[ip++] & 0xff : 0;
int o0 = i0 >>> 2;
int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
int o3 = i2 & 0x3F;
out[op++] = map1[o0];
out[op++] = map1[o1];
out[op] = op < oDataLen ? map1[o2] : "=";
op++;
out[op] = op < oDataLen ? map1[o3] : "=";
op++;
}
return out;
}
/**
* Decodes a Base64 string.
* @param s a Base64 String to be decoded.
* @return A String containing the decoded data.
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
*/
public static String decode(String s) {
return new String(decode(s.toCharArray()));
}
/**
* Decodes Base64 data.
* No blanks or line breaks are allowed within the Base64 encoded data.
* @param in a character array containing the Base64 encoded data.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
*/
public static byte[] decode(char[] in) {
int iLen = in.length;
if (iLen % 4 != 0)
throw new IllegalArgumentException(
"Length of Base64 encoded input string is not a multiple of 4.");
while (iLen > 0 && in[iLen - 1] == "=")
iLen--;
int oLen = (iLen * 3) / 4;
byte[] out = new byte[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++];
int i1 = in[ip++];
int i2 = ip < iLen ? in[ip++] : "A";
int i3 = ip < iLen ? in[ip++] : "A";
if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
throw new IllegalArgumentException(
"Illegal character in Base64 encoded data.");
int b0 = map2[i0];
int b1 = map2[i1];
int b2 = map2[i2];
int b3 = map2[i3];
if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
throw new IllegalArgumentException(
"Illegal character in Base64 encoded data.");
int o0 = (b0 << 2) | (b1 >>> 4);
int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
int o2 = ((b2 & 3) << 6) | b3;
out[op++] = (byte) o0;
if (op < oLen)
out[op++] = (byte) o1;
if (op < oLen)
out[op++] = (byte) o2;
}
return out;
}
}
</source>
Encode and decode integers, times, and internationalized strings to and from popular binary formats
<source lang="java">
/* encdec - encode and decode integers, times, and
* internationalized strings to and from popular binary formats * http://www.ioplex.ru/~miallen/encdec/ * Copyright (c) 2003 Michael B. Allen <mballen@erols.ru> * * The GNU Library General Public License * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA */
import java.util.Date; import java.io.IOException; public class Encdec {
public static final long MILLISECONDS_BETWEEN_1970_AND_1601 = 11644473600000L; public static final long SEC_BETWEEEN_1904_AND_1970 = 2082844800L; public static final int TIME_1970_SEC_32BE = 1; public static final int TIME_1970_SEC_32LE = 2; public static final int TIME_1904_SEC_32BE = 3; public static final int TIME_1904_SEC_32LE = 4; public static final int TIME_1601_NANOS_64LE = 5; public static final int TIME_1601_NANOS_64BE = 6; public static final int TIME_1970_MILLIS_64BE = 7; public static final int TIME_1970_MILLIS_64LE = 8; /* Encode integers */ public static int enc_uint16be( short s, byte[] dst, int di ) { dst[di++] = (byte)((s >> 8) & 0xFF); dst[di] = (byte)(s & 0xFF); return 2; } public static int enc_uint32be( int i, byte[] dst, int di ) { dst[di++] = (byte)((i >> 24) & 0xFF); dst[di++] = (byte)((i >> 16) & 0xFF); dst[di++] = (byte)((i >> 8) & 0xFF); dst[di] = (byte)(i & 0xFF); return 4; } public static int enc_uint16le( short s, byte[] dst, int di ) { dst[di++] = (byte)(s & 0xFF); dst[di] = (byte)((s >> 8) & 0xFF); return 2; } public static int enc_uint32le( int i, byte[] dst, int di ) { dst[di++] = (byte)(i & 0xFF); dst[di++] = (byte)((i >> 8) & 0xFF); dst[di++] = (byte)((i >> 16) & 0xFF); dst[di] = (byte)((i >> 24) & 0xFF); return 4; } /* Decode integers */ public static short dec_uint16be( byte[] src, int si ) { return (short)(((src[si] & 0xFF) << 8) | (src[si + 1] & 0xFF)); } public static int dec_uint32be( byte[] src, int si ) { return ((src[si] & 0xFF) << 24) | ((src[si + 1] & 0xFF) << 16) | ((src[si + 2] & 0xFF) << 8) | (src[si + 3] & 0xFF); } public static short dec_uint16le( byte[] src, int si ) { return (short)((src[si] & 0xFF) | ((src[si + 1] & 0xFF) << 8)); } public static int dec_uint32le( byte[] src, int si ) { return (src[si] & 0xFF) | ((src[si + 1] & 0xFF) << 8) | ((src[si + 2] & 0xFF) << 16) | ((src[si + 3] & 0xFF) << 24); } /* Encode and decode 64 bit integers */ public static int enc_uint64be( long l, byte[] dst, int di ) { enc_uint32be( (int)(l & 0xFFFFFFFFL), dst, di + 4 ); enc_uint32be( (int)(( l >> 32L ) & 0xFFFFFFFFL), dst, di ); return 8; } public static int enc_uint64le( long l, byte[] dst, int di ) { enc_uint32le( (int)(l & 0xFFFFFFFFL), dst, di ); enc_uint32le( (int)(( l >> 32L ) & 0xFFFFFFFFL), dst, di + 4 ); return 8; } public static long dec_uint64be( byte[] src, int si ) { long l; l = dec_uint32be( src, si ) & 0xFFFFFFFFL; l <<= 32L; l |= dec_uint32be( src, si + 4 ) & 0xFFFFFFFFL; return l; } public static long dec_uint64le( byte[] src, int si ) { long l; l = dec_uint32le( src, si + 4 ) & 0xFFFFFFFFL; l <<= 32L; l |= dec_uint32le( src, si ) & 0xFFFFFFFFL; return l; } /* Encode floats */ public static int enc_floatle( float f, byte[] dst, int di ) { return enc_uint32le( Float.floatToIntBits( f ), dst, di ); } public static int enc_floatbe( float f, byte[] dst, int di ) { return enc_uint32be( Float.floatToIntBits( f ), dst, di ); } /* Decode floating point numbers */ public static float dec_floatle( byte[] src, int si ) { return Float.intBitsToFloat( dec_uint32le( src, si )); } public static float dec_floatbe( byte[] src, int si ) { return Float.intBitsToFloat( dec_uint32be( src, si )); } /* Encode and decode doubles */ public static int enc_doublele( double d, byte[] dst, int di ) { return enc_uint64le( Double.doubleToLongBits( d ), dst, di ); } public static int enc_doublebe( double d, byte[] dst, int di ) { return enc_uint64be( Double.doubleToLongBits( d ), dst, di ); } public static double dec_doublele( byte[] src, int si ) { return Double.longBitsToDouble( dec_uint64le( src, si )); } public static double dec_doublebe( byte[] src, int si ) { return Double.longBitsToDouble( dec_uint64be( src, si )); } /* Encode times */ public static int enc_time( Date date, byte[] dst, int di, int enc ) { long t; switch( enc ) { case TIME_1970_SEC_32BE: return enc_uint32be( (int)(date.getTime() / 1000L), dst, di ); case TIME_1970_SEC_32LE: return enc_uint32le( (int)(date.getTime() / 1000L), dst, di ); case TIME_1904_SEC_32BE: return enc_uint32be( (int)((date.getTime() / 1000L + SEC_BETWEEEN_1904_AND_1970) & 0xFFFFFFFF), dst, di ); case TIME_1904_SEC_32LE: return enc_uint32le( (int)((date.getTime() / 1000L + SEC_BETWEEEN_1904_AND_1970) & 0xFFFFFFFF), dst, di ); case TIME_1601_NANOS_64BE: t = (date.getTime() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L; return enc_uint64be( t, dst, di ); case TIME_1601_NANOS_64LE: t = (date.getTime() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L; return enc_uint64le( t, dst, di ); case TIME_1970_MILLIS_64BE: return enc_uint64be( date.getTime(), dst, di ); case TIME_1970_MILLIS_64LE: return enc_uint64le( date.getTime(), dst, di ); default: throw new IllegalArgumentException( "Unsupported time encoding" ); } } /* Decode times */ public static Date dec_time( byte[] src, int si, int enc ) { long t; switch( enc ) { case TIME_1970_SEC_32BE: return new Date( dec_uint32be( src, si ) * 1000L ); case TIME_1970_SEC_32LE: return new Date( dec_uint32le( src, si ) * 1000L ); case TIME_1904_SEC_32BE: return new Date((( dec_uint32be( src, si ) & 0xFFFFFFFFL) - SEC_BETWEEEN_1904_AND_1970 ) * 1000L ); case TIME_1904_SEC_32LE: return new Date((( dec_uint32le( src, si ) & 0xFFFFFFFFL) - SEC_BETWEEEN_1904_AND_1970 ) * 1000L ); case TIME_1601_NANOS_64BE: t = dec_uint64be( src, si ); return new Date( t / 10000L - MILLISECONDS_BETWEEN_1970_AND_1601); case TIME_1601_NANOS_64LE: t = dec_uint64le( src, si ); return new Date( t / 10000L - MILLISECONDS_BETWEEN_1970_AND_1601); case TIME_1970_MILLIS_64BE: return new Date( dec_uint64be( src, si )); case TIME_1970_MILLIS_64LE: return new Date( dec_uint64le( src, si )); default: throw new IllegalArgumentException( "Unsupported time encoding" ); } } public static int enc_utf8( String str, byte[] dst, int di, int dlim ) throws IOException { int start = di, ch; int strlen = str.length(); for( int i = 0; di < dlim && i < strlen; i++ ) { ch = str.charAt( i ); if ((ch >= 0x0001) && (ch <= 0x007F)) { dst[di++] = (byte)ch; } else if (ch > 0x07FF) { if((dlim - di) < 3 ) { break; } dst[di++] = (byte)(0xE0 | ((ch >> 12) & 0x0F)); dst[di++] = (byte)(0x80 | ((ch >> 6) & 0x3F)); dst[di++] = (byte)(0x80 | ((ch >> 0) & 0x3F)); } else { if((dlim - di) < 2 ) { break; } dst[di++] = (byte)(0xC0 | ((ch >> 6) & 0x1F)); dst[di++] = (byte)(0x80 | ((ch >> 0) & 0x3F)); } } return di - start; } public static String dec_utf8( byte[] src, int si, int slim ) throws IOException { char[] uni = new char[slim - si]; int ui, ch; for( ui = 0; si < slim && (ch = src[si++] & 0xFF) != 0; ui++ ) { if( ch < 0x80 ) { uni[ui] = (char)ch; } else if((ch & 0xE0) == 0xC0 ) { if((slim - si) < 2 ) { break; } uni[ui] = (char)((ch & 0x1F) << 6); ch = src[si++] & 0xFF; uni[ui] |= ch & 0x3F; if ((ch & 0xC0) != 0x80 || uni[ui] < 0x80 ) { throw new IOException( "Invalid UTF-8 sequence" ); } } else if((ch & 0xF0) == 0xE0 ) { if((slim - si) < 3 ) { break; } uni[ui] = (char)((ch & 0x0F) << 12); ch = src[si++] & 0xFF; if ((ch & 0xC0) != 0x80 ) { throw new IOException( "Invalid UTF-8 sequence" ); } else { uni[ui] |= (ch & 0x3F) << 6; ch = src[si++] & 0xFF; uni[ui] |= ch & 0x3F; if ((ch & 0xC0) != 0x80 || uni[ui] < 0x800) { throw new IOException( "Invalid UTF-8 sequence" ); } } } else { throw new IOException( "Unsupported UTF-8 sequence" ); } } return new String( uni, 0, ui ); } public static String dec_ucs2le( byte[] src, int si, int slim, char[] buf ) throws IOException { int bi; for( bi = 0; (si + 1) < slim; bi++, si += 2 ) { buf[bi] = (char)dec_uint16le( src, si ); if( buf[bi] == "\0" ) { break; } } return new String( buf, 0, bi ); }
}
</source>
Encode/decode for RFC 2045 Base64 as defined by RFC 2045
<source lang="java">
/*
* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
/**
* This class provides encode/decode for RFC 2045 Base64 as defined by * RFC 2045, N. Freed and N. Borenstein. : * Multipurpose Internet Mail Extensions (MIME) Part One: Format of * Internet Message Bodies. Reference 1996 * * @author Jeffrey Rodriguez * @version $Id: Base64.java 515 2008-03-17 21:02:23Z jfrederic.clere@jboss.ru $ */
public final class Base64 {
static private final int BASELENGTH = 255; static private final int LOOKUPLENGTH = 64; static private final int TWENTYFOURBITGROUP = 24; static private final int EIGHTBIT = 8; static private final int SIXTEENBIT = 16; static private final int SIXBIT = 6; static private final int FOURBYTE = 4; static private final int SIGN = -128; static private final byte PAD = (byte) "="; static private byte [] base64Alphabet = new byte[BASELENGTH]; static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; //static private final Log log = LogSource.getInstance("org.apache.rumons.util.Base64"); static { for (int i = 0; i < BASELENGTH; i++ ) { base64Alphabet[i] = -1; } for (int i = "Z"; i >= "A"; i--) { base64Alphabet[i] = (byte) (i - "A"); } for (int i = "z"; i>= "a"; i--) { base64Alphabet[i] = (byte) (i - "a" + 26); } for (int i = "9"; i >= "0"; i--) { base64Alphabet[i] = (byte) (i - "0" + 52); } base64Alphabet["+"] = 62; base64Alphabet["/"] = 63; for (int i = 0; i <= 25; i++ ) lookUpBase64Alphabet[i] = (byte) ("A" + i); for (int i = 26, j = 0; i <= 51; i++, j++ ) lookUpBase64Alphabet[i] = (byte) ("a"+ j); for (int i = 52, j = 0; i <= 61; i++, j++ ) lookUpBase64Alphabet[i] = (byte) ("0" + j); lookUpBase64Alphabet[62] = (byte) "+"; lookUpBase64Alphabet[63] = (byte) "/"; } public static boolean isBase64( String isValidString ) { return isArrayByteBase64(isValidString.getBytes()); } public static boolean isBase64( byte octect ) { //shall we ignore white space? JEFF?? return (octect == PAD || base64Alphabet[octect] != -1); } public static boolean isArrayByteBase64( byte[] arrayOctect ) { int length = arrayOctect.length; if (length == 0) { // shouldn"t a 0 length array be valid base64 data? // return false; return true; } for (int i=0; i < length; i++) { if ( !Base64.isBase64(arrayOctect[i]) ) return false; } return true; } /** * Encodes hex octects into Base64. * * @param binaryData Array containing binary data to encode. * @return Base64-encoded data. */ public static byte[] encode( byte[] binaryData ) { int lengthDataBits = binaryData.length*EIGHTBIT; int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; byte encodedData[] = null;
if (fewerThan24bits != 0) { //data not divisible by 24 bit encodedData = new byte[ (numberTriplets + 1 ) * 4 ]; } else { // 16 or 8 bit encodedData = new byte[ numberTriplets * 4 ]; } byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; int encodedIndex = 0; int dataIndex = 0; int i = 0; //log.debug("number of triplets = " + numberTriplets); for ( i = 0; i<numberTriplets; i++ ) { dataIndex = i*3; b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; b3 = binaryData[dataIndex + 2]; //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3); l = (byte)(b2 & 0x0f); k = (byte)(b1 & 0x03); encodedIndex = i * 4; byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0); byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc); encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ]; //log.debug( "val2 = " + val2 ); //log.debug( "k4 = " + (k<<4) ); //log.debug( "vak = " + (val2 | (k<<4)) ); encodedData[encodedIndex+1] = lookUpBase64Alphabet[ val2 | ( k<<4 )]; encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | val3 ]; encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ]; } // form integral number of 6-bit groups dataIndex = i*3; encodedIndex = i*4; if (fewerThan24bits == EIGHTBIT ) { b1 = binaryData[dataIndex]; k = (byte) ( b1 &0x03 ); //log.debug("b1=" + b1); //log.debug("b1<<2 = " + (b1>>2) ); byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ]; encodedData[encodedIndex + 2] = PAD; encodedData[encodedIndex + 3] = PAD; } else if (fewerThan24bits == SIXTEENBIT) { b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex +1 ]; l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); byte val2 = ((b2 & SIGN) == 0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0); encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ val2 | ( k<<4 )]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ]; encodedData[encodedIndex + 3] = PAD; } return encodedData; }
}
</source>
Encode/decode for RFC 2045 Base64 as defined by RFC 2045, N. Freed and N. Borenstein.
<source lang="java">
/*
* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
/**
* This class provides encode/decode for RFC 2045 Base64 as * defined by RFC 2045, N. Freed and N. Borenstein. * RFC 2045: Multipurpose Internet Mail Extensions (MIME) * Part One: Format of Internet Message Bodies. Reference * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt * This class is used by XML Schema binary format validation * * This implementation does not encode/decode streaming * data. You need the data that you will encode/decode * already on a byte arrray. * * @xerces.internal * * @author Jeffrey Rodriguez * @author Sandy Gao * @version $Id: Base64.java 446747 2006-09-15 21:46:20Z mrglavas $ */
public final class Base64 {
static private final int BASELENGTH = 128; static private final int LOOKUPLENGTH = 64; static private final int TWENTYFOURBITGROUP = 24; static private final int EIGHTBIT = 8; static private final int SIXTEENBIT = 16; static private final int SIXBIT = 6; static private final int FOURBYTE = 4; static private final int SIGN = -128; static private final char PAD = "="; static private final boolean fDebug = false; static final private byte [] base64Alphabet = new byte[BASELENGTH]; static final private char [] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; static { for (int i = 0; i < BASELENGTH; ++i) { base64Alphabet[i] = -1; } for (int i = "Z"; i >= "A"; i--) { base64Alphabet[i] = (byte) (i-"A"); } for (int i = "z"; i>= "a"; i--) { base64Alphabet[i] = (byte) ( i-"a" + 26); } for (int i = "9"; i >= "0"; i--) { base64Alphabet[i] = (byte) (i-"0" + 52); } base64Alphabet["+"] = 62; base64Alphabet["/"] = 63; for (int i = 0; i<=25; i++) lookUpBase64Alphabet[i] = (char)("A"+i); for (int i = 26, j = 0; i<=51; i++, j++) lookUpBase64Alphabet[i] = (char)("a"+ j); for (int i = 52, j = 0; i<=61; i++, j++) lookUpBase64Alphabet[i] = (char)("0" + j); lookUpBase64Alphabet[62] = (char)"+"; lookUpBase64Alphabet[63] = (char)"/"; } protected static boolean isWhiteSpace(char octect) { return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); } protected static boolean isPad(char octect) { return (octect == PAD); } protected static boolean isData(char octect) { return (octect < BASELENGTH && base64Alphabet[octect] != -1); } protected static boolean isBase64(char octect) { return (isWhiteSpace(octect) || isPad(octect) || isData(octect)); } /** * Encodes hex octects into Base64 * * @param binaryData Array containing binaryData * @return Encoded Base64 array */ public static String encode(byte[] binaryData) { if (binaryData == null) return null; int lengthDataBits = binaryData.length*EIGHTBIT; if (lengthDataBits == 0) { return ""; } int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; int numberQuartet = fewerThan24bits != 0 ? numberTriplets+1 : numberTriplets; char encodedData[] = null; encodedData = new char[numberQuartet*4]; byte k=0, l=0, b1=0,b2=0,b3=0; int encodedIndex = 0; int dataIndex = 0; if (fDebug) { System.out.println("number of triplets = " + numberTriplets ); } for (int i=0; i<numberTriplets; i++) { b1 = binaryData[dataIndex++]; b2 = binaryData[dataIndex++]; b3 = binaryData[dataIndex++]; if (fDebug) { System.out.println( "b1= " + b1 +", b2= " + b2 + ", b3= " + b3 ); } l = (byte)(b2 & 0x0f); k = (byte)(b1 & 0x03); byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0); byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc); if (fDebug) { System.out.println( "val2 = " + val2 ); System.out.println( "k4 = " + (k<<4)); System.out.println( "vak = " + (val2 | (k<<4))); } encodedData[encodedIndex++] = lookUpBase64Alphabet[ val1 ]; encodedData[encodedIndex++] = lookUpBase64Alphabet[ val2 | ( k<<4 )]; encodedData[encodedIndex++] = lookUpBase64Alphabet[ (l <<2 ) | val3 ]; encodedData[encodedIndex++] = lookUpBase64Alphabet[ b3 & 0x3f ]; } // form integral number of 6-bit groups if (fewerThan24bits == EIGHTBIT) { b1 = binaryData[dataIndex]; k = (byte) ( b1 &0x03 ); if (fDebug) { System.out.println("b1=" + b1); System.out.println("b1<<2 = " + (b1>>2) ); } byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); encodedData[encodedIndex++] = lookUpBase64Alphabet[ val1 ]; encodedData[encodedIndex++] = lookUpBase64Alphabet[ k<<4 ]; encodedData[encodedIndex++] = PAD; encodedData[encodedIndex++] = PAD; } else if (fewerThan24bits == SIXTEENBIT) { b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex +1 ]; l = ( byte ) ( b2 &0x0f ); k = ( byte ) ( b1 &0x03 ); byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0); encodedData[encodedIndex++] = lookUpBase64Alphabet[ val1 ]; encodedData[encodedIndex++] = lookUpBase64Alphabet[ val2 | ( k<<4 )]; encodedData[encodedIndex++] = lookUpBase64Alphabet[ l<<2 ]; encodedData[encodedIndex++] = PAD; } return new String(encodedData); } /** * Decodes Base64 data into octects * * @param encoded string containing Base64 data * @return Array containind decoded data. */ public static byte[] decode(String encoded) { if (encoded == null) return null; char[] base64Data = encoded.toCharArray(); // remove white spaces int len = removeWhiteSpace(base64Data); if (len%FOURBYTE != 0) { return null;//should be divisible by four } int numberQuadruple = (len/FOURBYTE ); if (numberQuadruple == 0) return new byte[0]; byte decodedData[] = null; byte b1=0,b2=0,b3=0,b4=0; char d1=0,d2=0,d3=0,d4=0; int i = 0; int encodedIndex = 0; int dataIndex = 0; decodedData = new byte[ (numberQuadruple)*3]; for (; i<numberQuadruple-1; i++) { if (!isData( (d1 = base64Data[dataIndex++]) )|| !isData( (d2 = base64Data[dataIndex++]) )|| !isData( (d3 = base64Data[dataIndex++]) )|| !isData( (d4 = base64Data[dataIndex++]) )) return null;//if found "no data" just return null b1 = base64Alphabet[d1]; b2 = base64Alphabet[d2]; b3 = base64Alphabet[d3]; b4 = base64Alphabet[d4]; decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ; decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); decodedData[encodedIndex++] = (byte)( b3<<6 | b4 ); } if (!isData( (d1 = base64Data[dataIndex++]) ) || !isData( (d2 = base64Data[dataIndex++]) )) { return null;//if found "no data" just return null } b1 = base64Alphabet[d1]; b2 = base64Alphabet[d2]; d3 = base64Data[dataIndex++]; d4 = base64Data[dataIndex++]; if (!isData( (d3 ) ) || !isData( (d4 ) )) {//Check if they are PAD characters if (isPad( d3 ) && isPad( d4)) { //Two PAD e.g. 3c[Pad][Pad] if ((b2 & 0xf) != 0)//last 4 bits should be zero return null; byte[] tmp = new byte[ i*3 + 1 ]; System.arraycopy( decodedData, 0, tmp, 0, i*3 ); tmp[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; return tmp; } else if (!isPad( d3) && isPad(d4)) { //One PAD e.g. 3cQ[Pad] b3 = base64Alphabet[ d3 ]; if ((b3 & 0x3 ) != 0)//last 2 bits should be zero return null; byte[] tmp = new byte[ i*3 + 2 ]; System.arraycopy( decodedData, 0, tmp, 0, i*3 ); tmp[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ); tmp[encodedIndex] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); return tmp; } else { return null;//an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data } } else { //No PAD e.g 3cQl b3 = base64Alphabet[ d3 ]; b4 = base64Alphabet[ d4 ]; decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ; decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); decodedData[encodedIndex++] = (byte)( b3<<6 | b4 ); } return decodedData; } /** * remove WhiteSpace from MIME containing encoded Base64 data. * * @param data the byte array of base64 data (with WS) * @return the new length */ protected static int removeWhiteSpace(char[] data) { if (data == null) return 0; // count characters that"s not whitespace int newSize = 0; int len = data.length; for (int i = 0; i < len; i++) { if (!isWhiteSpace(data[i])) data[newSize++] = data[i]; } return newSize; }
}
</source>
Encodes and decodes to and from Base64 notation.
<source lang="java">
/*
* JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */
import java.io.IOException;
/**
* Encodes and decodes to and from Base64 notation. * * <p> * Change Log:* *
-
*
- v2.1 - Cleaned up javadoc comments and unused variables and methods. Added * some convenience methods for reading and writing to and from files. *
- v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on systems * with other encodings (like EBCDIC). *
- v2.0.1 - Fixed an error when decoding a single byte, that is, when the * encoded data was a single byte. *
- v2.0 - I got rid of methods that used booleans to set options. * Now everything is more consolidated and cleaner. The code now detects * when data that"s being decoded is gzip-compressed and will decompress it * automatically. Generally things are cleaner. You"ll probably have to * change some method calls that you were making to support the new * options format (ints that you "OR" together). *
- v1.5.1 - Fixed bug when decompressing and decoding to a * byte[] using decode( String s, boolean gzipCompressed ). * Added the ability to "suspend" encoding in the Output Stream so * you can turn on and off the encoding if you need to embed base64 * data in an otherwise "normal" stream (like an XML file). *
- v1.5 - Output stream pases on flush() command but doesn"t do anything itself. * This helps when using GZIP streams. * Added the ability to GZip-compress objects before encoding them. *
- v1.4 - Added helper methods to read/write files. *
- v1.3.6 - Fixed OutputStream.flush() so that "position" is reset. *
- v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream * where last buffer being read, if not completely full, was not returned. *
- v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time. *
- v1.3.3 - Fixed I/O streams which were totally messed up. *
**
* I am placing this code in the Public Domain. Do with it as you will. * This software comes with no guarantees or warranties but with * plenty of well-wishing instead! * Please visit * periodically to check for updates or to contribute improvements. *
* * @author Robert Harder * @author rob@iharder.net * @version 2.1 */
public class Base64 {
// provide logging /* ******** P U B L I C F I E L D S ******** */ /** No options specified. Value is zero. */ public final static int NO_OPTIONS = 0; /** Specify encoding. */ public final static int ENCODE = 1; /** Specify decoding. */ public final static int DECODE = 0; /** Specify that data should be gzip-compressed. */ public final static int GZIP = 2; /** Don"t break lines when encoding (violates strict Base64 specification) */ public final static int DONT_BREAK_LINES = 8; /* ******** P R I V A T E F I E L D S ******** */ /** Maximum line length (76) of Base64 output. */ private final static int MAX_LINE_LENGTH = 76; /** The equals sign (=) as a byte. */ private final static byte EQUALS_SIGN = (byte)"="; /** The new line character (\n) as a byte. */ private final static byte NEW_LINE = (byte)"\n"; /** Preferred encoding. */ private final static String PREFERRED_ENCODING = "UTF-8"; /** The 64 valid Base64 values. */ private final static byte[] ALPHABET; private final static byte[] _NATIVE_ALPHABET = /* May be something funny like EBCDIC */ { (byte)"A", (byte)"B", (byte)"C", (byte)"D", (byte)"E", (byte)"F", (byte)"G", (byte)"H", (byte)"I", (byte)"J", (byte)"K", (byte)"L", (byte)"M", (byte)"N", (byte)"O", (byte)"P", (byte)"Q", (byte)"R", (byte)"S", (byte)"T", (byte)"U", (byte)"V", (byte)"W", (byte)"X", (byte)"Y", (byte)"Z", (byte)"a", (byte)"b", (byte)"c", (byte)"d", (byte)"e", (byte)"f", (byte)"g", (byte)"h", (byte)"i", (byte)"j", (byte)"k", (byte)"l", (byte)"m", (byte)"n", (byte)"o", (byte)"p", (byte)"q", (byte)"r", (byte)"s", (byte)"t", (byte)"u", (byte)"v", (byte)"w", (byte)"x", (byte)"y", (byte)"z", (byte)"0", (byte)"1", (byte)"2", (byte)"3", (byte)"4", (byte)"5", (byte)"6", (byte)"7", (byte)"8", (byte)"9", (byte)"+", (byte)"/" }; /** Determine which ALPHABET to use. */ static { byte[] __bytes; try { __bytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(PREFERRED_ENCODING); } // end try catch (java.io.UnsupportedEncodingException use) { __bytes = _NATIVE_ALPHABET; // Fall back to native encoding } // end catch ALPHABET = __bytes; } // end static /** * Translates a Base64 value to either its 6-bit reconstruction value * or a negative number indicating some other meaning. **/ private final static byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 -5, -5, // Whitespace: Tab and Linefeed -9, -9, // Decimal 11 - 12 -5, // Whitespace: Carriage Return -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 -9, -9, -9, -9, -9, // Decimal 27 - 31 -5, // Whitespace: Space -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 62, // Plus sign at decimal 43 -9, -9, -9, // Decimal 44 - 46 63, // Slash at decimal 47 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine -9, -9, -9, // Decimal 58 - 60 -1, // Equals sign at decimal 61 -9, -9, -9, // Decimal 62 - 64 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters "A" through "N" 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters "O" through "Z" -9, -9, -9, -9, -9, -9, // Decimal 91 - 96 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters "a" through "m" 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters "n" through "z" -9, -9, -9, -9 // Decimal 123 - 126 /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ }; // I think I end up not using the BAD_ENCODING indicator. //private final static byte BAD_ENCODING = -9; // Indicates error in encoding private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding /** Defeats instantiation. */ private Base64() { } /* ******** E N C O D I N G M E T H O D S ******** */ /** * Encodes up to the first three bytes of array threeBytes * and returns a four-byte array in Base64 notation. * The actual number of significant bytes in your array is * given by numSigBytes. * The array threeBytes needs only be as big as * numSigBytes. * Code can reuse a byte array by passing a four-byte array as b4. * * @param b4 A reusable byte array to reduce array instantiation * @param threeBytes the array to convert * @param numSigBytes the number of significant bytes in your array * @return four byte array in Base64 notation. * @since 1.5.1 */ private static byte[] encode3to4(byte[] b4, byte[] threeBytes, int numSigBytes) { encode3to4(threeBytes, 0, numSigBytes, b4, 0); return b4; } // end encode3to4 /** * Encodes up to three bytes of the array source * and writes the resulting four Base64 bytes to destination. * The source and destination arrays can be manipulated * anywhere along their length by specifying * srcOffset and destOffset. * This method does not check to make sure your arrays * are large enough to accomodate srcOffset + 3 for * the source array or destOffset + 4 for * the destination array. * The actual number of significant bytes in your array is * given by numSigBytes. * * @param source the array to convert * @param srcOffset the index where conversion begins * @param numSigBytes the number of significant bytes in your array * @param destination the array to hold the conversion * @param destOffset the index where output will be put * @return the destination array * @since 1.3 */ private static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, byte[] destination, int destOffset) { // 1 2 3 // 01234567890123456789012345678901 Bit position // --------000000001111111122222222 Array position from threeBytes // --------| || || || | Six bit groups to index ALPHABET // >>18 >>12 >> 6 >> 0 Right shift necessary // 0x3f 0x3f 0x3f Additional AND // Create buffer with zero-padding if there are only one or two // significant bytes passed in the array. // We have to shift left 24 in order to flush out the 1"s that appear // when Java treats a value as negative that is cast from a byte to an int. int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); switch (numSigBytes) { case 3: destination[destOffset] = ALPHABET[(inBuff >>> 18)]; destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f]; return destination; case 2: destination[destOffset] = ALPHABET[(inBuff >>> 18)]; destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; destination[destOffset + 3] = EQUALS_SIGN; return destination; case 1: destination[destOffset] = ALPHABET[(inBuff >>> 18)]; destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; destination[destOffset + 2] = EQUALS_SIGN; destination[destOffset + 3] = EQUALS_SIGN; return destination; default: return destination; } // end switch } // end encode3to4 /** * Serializes an object and returns the Base64-encoded * version of that serialized object. If the object * cannot be serialized or there is another error, * the method will return null. * The object is not GZip-compressed before being encoded. * * @param serializableObject The object to encode * @return The Base64-encoded object * @since 1.4 */ public static String encodeObject(java.io.Serializable serializableObject) { return encodeObject(serializableObject, NO_OPTIONS); } // end encodeObject /** * Serializes an object and returns the Base64-encoded * version of that serialized object. If the object * cannot be serialized or there is another error, * the method will return null.*
* Valid options:
* GZIP: gzip-compresses object before encoding it. * DONT_BREAK_LINES: don"t break lines at 76 characters * <i>Note: Technically, this makes your encoding non-compliant.</i> *
* <p> * Example:* Valid options:encodeObject( myObj, Base64.GZIP )
or * <p> * Example:encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )
* * @param serializableObject The object to encode * @param options Specified options * @return The Base64-encoded object * @see Base64#GZIP * @see Base64#DONT_BREAK_LINES * @since 2.0 */ public static String encodeObject(java.io.Serializable serializableObject, int options) { // Streams java.io.ByteArrayOutputStream baos = null; java.io.OutputStream b64os = null; java.io.ObjectOutputStream oos = null; java.util.zip.GZIPOutputStream gzos = null; // Isolate options int gzip = (options & GZIP); int dontBreakLines = (options & DONT_BREAK_LINES); try { // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines); // GZip? if (gzip == GZIP) { gzos = new java.util.zip.GZIPOutputStream(b64os); oos = new java.io.ObjectOutputStream(gzos); } // end if: gzip else oos = new java.io.ObjectOutputStream(b64os); oos.writeObject(serializableObject); } // end try catch (java.io.IOException e) { e.printStackTrace(); return null; } // end catch finally { try { oos.close(); } catch (Exception e) { } try { gzos.close(); } catch (Exception e) { } try { b64os.close(); } catch (Exception e) { } try { baos.close(); } catch (Exception e) { } } // end finally // Return value according to relevant encoding. try { return new String(baos.toByteArray(), PREFERRED_ENCODING); } // end try catch (java.io.UnsupportedEncodingException uue) { return new String(baos.toByteArray()); } // end catch } // end encode /** * Encodes a byte array into Base64 notation. * Does not GZip-compress data. * * @param source The data to convert * @return the encode bytes * @since 1.4 */ public static String encodeBytes(byte[] source) { return encodeBytes(source, 0, source.length, NO_OPTIONS); } // end encodeBytes /** * Encodes a byte array into Base64 notation. * <p>
* GZIP: gzip-compresses object before encoding it. * DONT_BREAK_LINES: don"t break lines at 76 characters * <i>Note: Technically, this makes your encoding non-compliant.</i> *
* <p> * Example:* Valid options:encodeBytes( myData, Base64.GZIP )
or * <p> * Example:encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )
* * * @param source The data to convert * @param options Specified options * @return the encoded bytes * @see Base64#GZIP * @see Base64#DONT_BREAK_LINES * @since 2.0 */ public static String encodeBytes(byte[] source, int options) { return encodeBytes(source, 0, source.length, options); } // end encodeBytes /** * Encodes a byte array into Base64 notation. * Does not GZip-compress data. * * @param source The data to convert * @param off Offset in array where conversion should begin * @param len Length of data to convert * @return the text node * @since 1.4 */ public static String encodeBytes(byte[] source, int off, int len) { return encodeBytes(source, off, len, NO_OPTIONS); } // end encodeBytes /** * Encodes a byte array into Base64 notation. * <p>
* GZIP: gzip-compresses object before encoding it. * DONT_BREAK_LINES: don"t break lines at 76 characters * <i>Note: Technically, this makes your encoding non-compliant.</i> *
* <p> * Example:* Valid options:encodeBytes( myData, Base64.GZIP )
or * <p> * Example:encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )
* * * @param source The data to convert * @param off Offset in array where conversion should begin * @param len Length of data to convert * @param options Specified options * @see Base64#GZIP * @see Base64#DONT_BREAK_LINES * @return the text node * @since 2.0 */ public static String encodeBytes(byte[] source, int off, int len, int options) { // Isolate options int dontBreakLines = (options & DONT_BREAK_LINES); int gzip = (options & GZIP); // Compress? if (gzip == GZIP) { java.io.ByteArrayOutputStream baos = null; java.util.zip.GZIPOutputStream gzos = null; Base64.OutputStream b64os = null; try { // GZip -> Base64 -> ByteArray baos = new java.io.ByteArrayOutputStream(); b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines); gzos = new java.util.zip.GZIPOutputStream(b64os); gzos.write(source, off, len); gzos.close(); } // end try catch (java.io.IOException e) { e.printStackTrace(); return null; } // end catch finally { try { gzos.close(); } catch (Exception e) { } try { b64os.close(); } catch (Exception e) { } try { baos.close(); } catch (Exception e) { } } // end finally // Return value according to relevant encoding. try { return new String(baos.toByteArray(), PREFERRED_ENCODING); } // end try catch (java.io.UnsupportedEncodingException uue) { return new String(baos.toByteArray()); } // end catch } // end if: compress // Else, don"t compress. Better not to use streams at all then. else { // Convert option to boolean in way that code likes it. boolean breakLines = dontBreakLines == 0; int len43 = len * 4 / 3; byte[] outBuff = new byte[(len43) // Main 4:3 + ((len % 3) > 0 ? 4 : 0) // Account for padding + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New lines int d = 0; int e = 0; int len2 = len - 2; int lineLength = 0; for (; d < len2; d += 3, e += 4) { encode3to4(source, d + off, 3, outBuff, e); lineLength += 4; if (breakLines && lineLength == MAX_LINE_LENGTH) { outBuff[e + 4] = NEW_LINE; e++; lineLength = 0; } // end if: end of line } // en dfor: each piece of array if (d < len) { encode3to4(source, d + off, len - d, outBuff, e); e += 4; } // end if: some padding needed // Return value according to relevant encoding. try { return new String(outBuff, 0, e, PREFERRED_ENCODING); } // end try catch (java.io.UnsupportedEncodingException uue) { return new String(outBuff, 0, e); } // end catch } // end else: don"t compress } // end encodeBytes /* ******** D E C O D I N G M E T H O D S ******** */ /** * Decodes four bytes from array source * and writes the resulting bytes (up to three of them) * to destination. * The source and destination arrays can be manipulated * anywhere along their length by specifying * srcOffset and destOffset. * This method does not check to make sure your arrays * are large enough to accomodate srcOffset + 4 for * the source array or destOffset + 3 for * the destination array. * This method returns the actual number of bytes that * were converted from the Base64 encoding. * * * @param source the array to convert * @param srcOffset the index where conversion begins * @param destination the array to hold the conversion * @param destOffset the index where output will be put * @return the number of decoded bytes converted * @since 1.3 */ private static int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset) { // Example: Dk== if (source[srcOffset + 2] == EQUALS_SIGN) { // Two ways to do the same thing. Don"t know which way I like best. //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 ); int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12); destination[destOffset] = (byte)(outBuff >>> 16); return 1; } // Example: DkL= else if (source[srcOffset + 3] == EQUALS_SIGN) { // Two ways to do the same thing. Don"t know which way I like best. //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ); int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6); destination[destOffset] = (byte)(outBuff >>> 16); destination[destOffset + 1] = (byte)(outBuff >>> 8); return 2; } // Example: DkLE else { try { // Two ways to do the same thing. Don"t know which way I like best. //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ) // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 ); int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) | ((DECODABET[source[srcOffset + 3]] & 0xFF)); destination[destOffset] = (byte)(outBuff >> 16); destination[destOffset + 1] = (byte)(outBuff >> 8); destination[destOffset + 2] = (byte)(outBuff); return 3; } catch (Exception e) { System.out.println("" + source[srcOffset] + ": " + (DECODABET[source[srcOffset]])); System.out.println("" + source[srcOffset + 1] + ": " + (DECODABET[source[srcOffset + 1]])); System.out.println("" + source[srcOffset + 2] + ": " + (DECODABET[source[srcOffset + 2]])); System.out.println("" + source[srcOffset + 3] + ": " + (DECODABET[source[srcOffset + 3]])); return -1; } //end catch } } // end decodeToBytes /** * Very low-level access to decoding ASCII characters in * the form of a byte array. Does not support automatically * gunzipping or any other "fancy" features. * * @param source The Base64 encoded data * @param off The offset of where to begin decoding * @param len The length of characters to decode * @return decoded data * @since 1.3 */ public static byte[] decode(byte[] source, int off, int len) { int len34 = len * 3 / 4; byte[] outBuff = new byte[len34]; // Upper limit on size of output int outBuffPosn = 0; byte[] b4 = new byte[4]; int b4Posn = 0; int i = 0; byte sbiCrop = 0; byte sbiDecode = 0; for (i = off; i < off + len; i++) { sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits sbiDecode = DECODABET[sbiCrop]; if (sbiDecode >= WHITE_SPACE_ENC) // White space, Equals sign or better { if (sbiDecode >= EQUALS_SIGN_ENC) { b4[b4Posn++] = sbiCrop; if (b4Posn > 3) { outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn); b4Posn = 0; // If that was the equals sign, break out of "for" loop if (sbiCrop == EQUALS_SIGN) break; } // end if: quartet built } // end if: equals sign or better } // end if: white space, equals sign or better else { throw new IllegalStateException("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)"); } // end else: } // each input character byte[] out = new byte[outBuffPosn]; System.arraycopy(outBuff, 0, out, 0, outBuffPosn); return out; } // end decode /** * Decodes data from Base64 notation, automatically * detecting gzip-compressed data and decompressing it. * * @param s the string to decode * @return the decoded data * @since 1.4 */ public static byte[] decode(String s) { byte[] bytes; try { bytes = s.getBytes(PREFERRED_ENCODING); } // end try catch (java.io.UnsupportedEncodingException uee) { bytes = s.getBytes(); } // end catch //</change> // Decode bytes = decode(bytes, 0, bytes.length); // Check to see if it"s gzip-compressed // GZIP Magic Two-Byte Number: 0x8b1f (35615) if (bytes != null && bytes.length >= 4) { int head = (bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head) { java.io.ByteArrayInputStream bais = null; java.util.zip.GZIPInputStream gzis = null; java.io.ByteArrayOutputStream baos = null; byte[] buffer = new byte[2048]; int length = 0; try { baos = new java.io.ByteArrayOutputStream(); bais = new java.io.ByteArrayInputStream(bytes); gzis = new java.util.zip.GZIPInputStream(bais); while ((length = gzis.read(buffer)) >= 0) { baos.write(buffer, 0, length); } // end while: reading input // No error? Get new bytes. bytes = baos.toByteArray(); } // end try catch (java.io.IOException e) { // Just return originally-decoded bytes } // end catch finally { try { baos.close(); } catch (Exception e) { } try { gzis.close(); } catch (Exception e) { } try { bais.close(); } catch (Exception e) { } } // end finally } // end if: gzipped } // end if: bytes.length >= 2 return bytes; } // end decode /** * Attempts to decode Base64 data and deserialize a Java * Object within. Returns null if there was an error. * * @param encodedObject The Base64 data to decode * @return The decoded and deserialized object * @since 1.5 */ public static Object decodeToObject(String encodedObject) { // Decode and gunzip if necessary byte[] objBytes = decode(encodedObject); java.io.ByteArrayInputStream bais = null; java.io.ObjectInputStream ois = null; Object obj = null; try { bais = new java.io.ByteArrayInputStream(objBytes); ois = new java.io.ObjectInputStream(bais); obj = ois.readObject(); } // end try catch (java.io.IOException e) { e.printStackTrace(); obj = null; } // end catch catch (java.lang.ClassNotFoundException e) { e.printStackTrace(); obj = null; } // end catch finally { try { bais.close(); } catch (Exception e) { } try { ois.close(); } catch (Exception e) { } } // end finally return obj; } // end decodeObject /** * Convenience method for encoding data to a file. * * @param dataToEncode byte array of data to encode in base64 form * @param filename Filename for saving encoded data * @return true if successful, false otherwise * * @since 2.1 */ public static boolean encodeToFile(byte[] dataToEncode, String filename) { boolean success = false; Base64.OutputStream bos = null; try { bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.ENCODE); bos.write(dataToEncode); success = true; } // end try catch (java.io.IOException e) { success = false; } // end catch: IOException finally { try { bos.close(); } catch (Exception e) { } } // end finally return success; } // end encodeToFile /** * Convenience method for decoding data to a file. * * @param dataToDecode Base64-encoded data as a string * @param filename Filename for saving decoded data * @return true if successful, false otherwise * * @since 2.1 */ public static boolean decodeToFile(String dataToDecode, String filename) { boolean success = false; Base64.OutputStream bos = null; try { bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.DECODE); bos.write(dataToDecode.getBytes(PREFERRED_ENCODING)); success = true; } // end try catch (java.io.IOException e) { success = false; } // end catch: IOException finally { try { bos.close(); } catch (Exception e) { } } // end finally return success; } // end decodeToFile /** * Convenience method for reading a base64-encoded * file and decoding it. * * @param filename Filename for reading encoded data * @return decoded byte array or null if unsuccessful * * @since 2.1 */ public static byte[] decodeFromFile(String filename) { byte[] decodedData = null; Base64.InputStream bis = null; try { // Set up some useful variables java.io.File file = new java.io.File(filename); byte[] buffer = null; int length = 0; int numBytes = 0; // Check for size of file if (file.length() > Integer.MAX_VALUE) { throw new IllegalStateException("File is too big for this convenience method (" + file.length() + " bytes)."); } // end if: file too big for int index buffer = new byte[(int)file.length()]; // Open a stream bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.DECODE); // Read until done while ((numBytes = bis.read(buffer, length, 4096)) >= 0) length += numBytes; // Save in a variable to return decodedData = new byte[length]; System.arraycopy(buffer, 0, decodedData, 0, length); } // end try catch (java.io.IOException e) { throw new IllegalStateException("Error decoding from file " + filename); } // end catch: IOException finally { try { bis.close(); } catch (Exception e) { } } // end finally return decodedData; } // end decodeFromFile /** * Convenience method for reading a binary file * and base64-encoding it. * * @param filename Filename for reading binary data * @return base64-encoded string or null if unsuccessful * * @since 2.1 */ public static String encodeFromFile(String filename) { String encodedData = null; Base64.InputStream bis = null; try { // Set up some useful variables java.io.File file = new java.io.File(filename); byte[] buffer = new byte[(int)(file.length() * 1.4)]; int length = 0; int numBytes = 0; // Open a stream bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.ENCODE); // Read until done while ((numBytes = bis.read(buffer, length, 4096)) >= 0) length += numBytes; // Save in a variable to return encodedData = new String(buffer, 0, length, Base64.PREFERRED_ENCODING); } // end try catch (java.io.IOException e) { throw new IllegalStateException("Error encoding from file " + filename); } // end catch: IOException finally { try { bis.close(); } catch (Exception e) { } } // end finally return encodedData; } // end encodeFromFile /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */ /** * A {@link Base64.InputStream} will read data from another * java.io.InputStream, given in the constructor, * and encode/decode to/from Base64 notation on the fly. * * @see Base64 * @since 1.3 */ public static class InputStream extends java.io.FilterInputStream { private boolean encode; // Encoding or decoding private int position; // Current position in the buffer private byte[] buffer; // Small buffer holding converted data private int bufferLength; // Length of buffer (3 or 4) private int numSigBytes; // Number of meaningful bytes in the buffer private int lineLength; private boolean breakLines; // Break lines at less than 80 characters /** * Constructs a {@link Base64.InputStream} in DECODE mode. * * @param in the java.io.InputStream from which to read data. * @since 1.3 */ public InputStream(java.io.InputStream in) { this(in, DECODE); } // end constructor /** * Constructs a {@link Base64.InputStream} in * either ENCODE or DECODE mode. * <p>
* ENCODE or DECODE: Encode or Decode as data is read. * DONT_BREAK_LINES: don"t break lines at 76 characters * (only meaningful when encoding) * <i>Note: Technically, this makes your encoding non-compliant.</i> *
* <p>
* Example: new Base64.InputStream( in, Base64.DECODE )
*
*
* @param in the java.io.InputStream from which to read data.
* @param options Specified options
* @see Base64#ENCODE
* @see Base64#DECODE
* @see Base64#DONT_BREAK_LINES
* @since 2.0
*/
public InputStream(java.io.InputStream in, int options)
{
super(in);
this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
this.encode = (options & ENCODE) == ENCODE;
this.bufferLength = encode ? 4 : 3;
this.buffer = new byte[bufferLength];
this.position = -1;
this.lineLength = 0;
} // end constructor
/**
* Reads enough of the input stream to convert
* to/from Base64 and returns the next byte.
*
* @return next byte
* @since 1.3
*/
public int read() throws java.io.IOException
{
// Do we need to get data?
if (position < 0)
{
if (encode)
{
byte[] b3 = new byte[3];
int numBinaryBytes = 0;
for (int i = 0; i < 3; i++)
{
try
{
int b = in.read();
// If end of stream, b is -1.
if (b >= 0)
{
b3[i] = (byte)b;
numBinaryBytes++;
} // end if: not end of stream
} // end try: read
catch (java.io.IOException e)
{
// Only a problem if we got no data at all.
if (i == 0)
throw e;
} // end catch
} // end for: each needed input byte
if (numBinaryBytes > 0)
{
encode3to4(b3, 0, numBinaryBytes, buffer, 0);
position = 0;
numSigBytes = 4;
} // end if: got data
else
{
return -1;
} // end else
} // end if: encoding
// Else decoding
else
{
byte[] b4 = new byte[4];
int i = 0;
for (i = 0; i < 4; i++)
{
// Read four "meaningful" bytes:
int b = 0;
do
{
b = in.read();
}
while (b >= 0 && DECODABET[b & 0x7f] <= WHITE_SPACE_ENC);
if (b < 0)
break; // Reads a -1 if end of stream
b4[i] = (byte)b;
} // end for: each needed input byte
if (i == 4)
{
numSigBytes = decode4to3(b4, 0, buffer, 0);
position = 0;
} // end if: got four characters
else if (i == 0)
{
return -1;
} // end else if: also padded correctly
else
{
// Must have broken out from above.
throw new java.io.IOException("Improperly padded Base64 input.");
} // end
} // end else: decode
} // end else: get data
// Got data?
if (position >= 0)
{
// End of relevant data?
if (/*!encode &&*/position >= numSigBytes)
return -1;
if (encode && breakLines && lineLength >= MAX_LINE_LENGTH)
{
lineLength = 0;
return "\n";
} // end if
else
{
lineLength++; // This isn"t important when decoding
// but throwing an extra "if" seems
// just as wasteful.
int b = buffer[position++];
if (position >= bufferLength)
position = -1;
return b & 0xFF; // This is how you "cast" a byte that"s
// intended to be unsigned.
} // end else
} // end if: position >= 0
// Else error
else
{
// When JDK1.4 is more accepted, use an assertion here.
throw new java.io.IOException("Error in Base64 code reading stream.");
} // end else
} // end read
/**
* Calls {@link #read()} repeatedly until the end of stream
* is reached or len bytes are read.
* Returns number of bytes read into array or -1 if
* end of stream is encountered.
*
* @param dest array to hold values
* @param off offset for array
* @param len max number of bytes to read into array
* @return bytes read into array or -1 if end of stream is encountered.
* @since 1.3
*/
public int read(byte[] dest, int off, int len) throws java.io.IOException
{
int i;
int b;
for (i = 0; i < len; i++)
{
b = read();
//if( b < 0 && i == 0 )
// return -1;
if (b >= 0)
dest[off + i] = (byte)b;
else if (i == 0)
return -1;
else break; // Out of "for" loop
} // end for: each byte read
return i;
} // end read
} // end inner class InputStream
/* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
/**
* A {@link Base64.OutputStream} will write data to another
* java.io.OutputStream, given in the constructor,
* and encode/decode to/from Base64 notation on the fly.
*
* @see Base64
* @since 1.3
*/
public static class OutputStream extends java.io.FilterOutputStream
{
private boolean encode;
private int position;
private byte[] buffer;
private int bufferLength;
private int lineLength;
private boolean breakLines;
private byte[] b4; // Scratch used in a few places
private boolean suspendEncoding;
/**
* Constructs a {@link Base64.OutputStream} in ENCODE mode.
*
* @param out the java.io.OutputStream to which data will be written.
* @since 1.3
*/
public OutputStream(java.io.OutputStream out)
{
this(out, ENCODE);
} // end constructor
/**
* Constructs a {@link Base64.OutputStream} in
* either ENCODE or DECODE mode.
* <p>
* Valid options:* ENCODE or DECODE: Encode or Decode as data is read. * DONT_BREAK_LINES: don"t break lines at 76 characters * (only meaningful when encoding) * <i>Note: Technically, this makes your encoding non-compliant.</i> *
* <p>
* Example: new Base64.OutputStream( out, Base64.ENCODE )
*
* @param out the java.io.OutputStream to which data will be written.
* @param options Specified options.
* @see Base64#ENCODE
* @see Base64#DECODE
* @see Base64#DONT_BREAK_LINES
* @since 1.3
*/
public OutputStream(java.io.OutputStream out, int options)
{
super(out);
this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
this.encode = (options & ENCODE) == ENCODE;
this.bufferLength = encode ? 3 : 4;
this.buffer = new byte[bufferLength];
this.position = 0;
this.lineLength = 0;
this.suspendEncoding = false;
this.b4 = new byte[4];
} // end constructor
/**
* Writes the byte to the output stream after
* converting to/from Base64 notation.
* When encoding, bytes are buffered three
* at a time before the output stream actually
* gets a write() call.
* When decoding, bytes are buffered four
* at a time.
*
* @param theByte the byte to write
* @since 1.3
*/
public void write(int theByte) throws java.io.IOException
{
// Encoding suspended?
if (suspendEncoding)
{
super.out.write(theByte);
return;
} // end if: supsended
// Encode?
if (encode)
{
buffer[position++] = (byte)theByte;
if (position >= bufferLength) // Enough to encode.
{
out.write(encode3to4(b4, buffer, bufferLength));
lineLength += 4;
if (breakLines && lineLength >= MAX_LINE_LENGTH)
{
out.write(NEW_LINE);
lineLength = 0;
} // end if: end of line
position = 0;
} // end if: enough to output
} // end if: encoding
// Else, Decoding
else
{
// Meaningful Base64 character?
if (DECODABET[theByte & 0x7f] > WHITE_SPACE_ENC)
{
buffer[position++] = (byte)theByte;
if (position >= bufferLength) // Enough to output.
{
int len = Base64.decode4to3(buffer, 0, b4, 0);
out.write(b4, 0, len);
//out.write( Base64.decode4to3( buffer ) );
position = 0;
} // end if: enough to output
} // end if: meaningful base64 character
else if (DECODABET[theByte & 0x7f] != WHITE_SPACE_ENC)
{
throw new java.io.IOException("Invalid character in Base64 data.");
} // end else: not white space either
} // end else: decoding
} // end write
/**
* Calls {@link #write(int)} repeatedly until len
* bytes are written.
*
* @param theBytes array from which to read bytes
* @param off offset for array
* @param len max number of bytes to read into array
* @since 1.3
*/
public void write(byte[] theBytes, int off, int len) throws java.io.IOException
{
// Encoding suspended?
if (suspendEncoding)
{
super.out.write(theBytes, off, len);
return;
} // end if: supsended
for (int i = 0; i < len; i++)
{
write(theBytes[off + i]);
} // end for: each byte written
} // end write
/**
* Method added by PHIL. [Thanks, PHIL. -Rob]
* This pads the buffer without closing the stream.
* @throws IOException
*/
public void flushBase64() throws java.io.IOException
{
if (position > 0)
{
if (encode)
{
out.write(encode3to4(b4, buffer, position));
position = 0;
} // end if: encoding
else
{
throw new java.io.IOException("Base64 input not properly padded.");
} // end else: decoding
} // end if: buffer partially full
} // end flush
/**
* Flushes and closes (I think, in the superclass) the stream.
*
* @since 1.3
*/
public void close() throws java.io.IOException
{
// 1. Ensure that pending characters are written
flushBase64();
// 2. Actually close the stream
// Base class both flushes and closes.
super.close();
buffer = null;
out = null;
} // end close
/**
* Suspends encoding of the stream.
* May be helpful if you need to embed a piece of
* base640-encoded data in a stream.
*
* @since 1.5.1
* @throws IOException
*/
public void suspendEncoding() throws java.io.IOException
{
flushBase64();
this.suspendEncoding = true;
} // end suspendEncoding
/**
* Resumes encoding of the stream.
* May be helpful if you need to embed a piece of
* base640-encoded data in a stream.
*
* @since 1.5.1
*/
public void resumeEncoding()
{
this.suspendEncoding = false;
} // end resumeEncoding
} // end inner class OutputStream
} // end class Base64
</source>
Encodes hex octects into Base64
<source lang="java">
/* Copyright 2004 The Apache Software Foundation
* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
import java.io.UnsupportedEncodingException; /**
* This class provides encode/decode for RFC 2045 Base64 as * defined by RFC 2045, N. Freed and N. Borenstein. * RFC 2045: Multipurpose Internet Mail Extensions (MIME) * Part One: Format of Internet Message Bodies. Reference * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt * This class is used by XML Schema binary format validation * * This implementation does not encode/decode streaming * data. You need the data that you will encode/decode * already on a byte arrray. * * * From xmlbeans * @author Jeffrey Rodriguez * @author Sandy Gao * @version $Id: Base64.java 111285 2004-12-08 16:54:26Z cezar $ */
public final class Base64 {
static private final int BASELENGTH = 255; static private final int LOOKUPLENGTH = 64; static private final int TWENTYFOURBITGROUP = 24; static private final int EIGHTBIT = 8; static private final int SIXTEENBIT = 16; //static private final int SIXBIT = 6; static private final int FOURBYTE = 4; static private final int SIGN = -128; static private final byte PAD = ( byte ) "="; static private final boolean fDebug = false; static private byte [] base64Alphabet = new byte[BASELENGTH]; static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; static { for (int i = 0; i<BASELENGTH; i++) { base64Alphabet[i] = -1; } for (int i = "Z"; i >= "A"; i--) { base64Alphabet[i] = (byte) (i-"A"); } for (int i = "z"; i>= "a"; i--) { base64Alphabet[i] = (byte) ( i-"a" + 26); } for (int i = "9"; i >= "0"; i--) { base64Alphabet[i] = (byte) (i-"0" + 52); } base64Alphabet["+"] = 62; base64Alphabet["/"] = 63; for (int i = 0; i<=25; i++) lookUpBase64Alphabet[i] = (byte) ("A"+i ); for (int i = 26, j = 0; i<=51; i++, j++) lookUpBase64Alphabet[i] = (byte) ("a"+ j ); for (int i = 52, j = 0; i<=61; i++, j++) lookUpBase64Alphabet[i] = (byte) ("0" + j ); lookUpBase64Alphabet[62] = (byte) "+"; lookUpBase64Alphabet[63] = (byte) "/"; } protected static boolean isWhiteSpace(byte octect) { return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); } protected static boolean isPad(byte octect) { return (octect == PAD); } protected static boolean isData(byte octect) { return (base64Alphabet[octect] != -1); } protected static boolean isBase64(byte octect) { return (isWhiteSpace(octect) || isPad(octect) || isData(octect)); } /** * Encodes hex octects into Base64 * * @param binaryData Array containing binaryData * @return Encoded Base64 array */ public static byte[] encode(byte[] binaryData) { if (binaryData == null) return null; int lengthDataBits = binaryData.length*EIGHTBIT; int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; byte encodedData[] = null; if (fewerThan24bits != 0) //data not divisible by 24 bit encodedData = new byte[ (numberTriplets + 1 )*4 ]; else // 16 or 8 bit encodedData = new byte[ numberTriplets*4 ]; byte k=0, l=0, b1=0,b2=0,b3=0; int encodedIndex = 0; int dataIndex = 0; int i = 0; if (fDebug) { System.out.println("number of triplets = " + numberTriplets ); } for (i = 0; i<numberTriplets; i++) { dataIndex = i*3; b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; b3 = binaryData[dataIndex + 2]; if (fDebug) { System.out.println( "b1= " + b1 +", b2= " + b2 + ", b3= " + b3 ); } l = (byte)(b2 & 0x0f); k = (byte)(b1 & 0x03); encodedIndex = i*4; byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0); byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc); encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ]; if (fDebug) { System.out.println( "val2 = " + val2 ); System.out.println( "k4 = " + (k<<4)); System.out.println( "vak = " + (val2 | (k<<4))); } encodedData[encodedIndex+1] = lookUpBase64Alphabet[ val2 | ( k<<4 )]; encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | val3 ]; encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ]; } // form integral number of 6-bit groups dataIndex = i*3; encodedIndex = i*4; if (fewerThan24bits == EIGHTBIT) { b1 = binaryData[dataIndex]; k = (byte) ( b1 &0x03 ); if (fDebug) { System.out.println("b1=" + b1); System.out.println("b1<<2 = " + (b1>>2) ); } byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ]; encodedData[encodedIndex + 2] = PAD; encodedData[encodedIndex + 3] = PAD; } else if (fewerThan24bits == SIXTEENBIT) { b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex +1 ]; l = ( byte ) ( b2 &0x0f ); k = ( byte ) ( b1 &0x03 ); byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0); byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0); encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ val2 | ( k<<4 )]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ]; encodedData[encodedIndex + 3] = PAD; } return encodedData; } /** * Decodes Base64 data into octects * * @param base64Data Byte array containing Base64 data * @return Array containind decoded data. */ public static byte[] decode(byte[] base64Data) { if (base64Data == null) return null; // remove white spaces base64Data = removeWhiteSpace(base64Data); if (base64Data.length%FOURBYTE != 0) { return null;//should be divisible by four } int numberQuadruple = (base64Data.length/FOURBYTE ); if (numberQuadruple == 0) return new byte[0]; byte decodedData[] = null; byte b1=0,b2=0,b3=0, b4=0;//, marker0=0, marker1=0; byte d1=0,d2=0,d3=0,d4=0; // Throw away anything not in normalizedBase64Data // Adjust size int i = 0; int encodedIndex = 0; int dataIndex = 0; decodedData = new byte[ (numberQuadruple)*3]; for (; i<numberQuadruple-1; i++) { if (!isData( (d1 = base64Data[dataIndex++]) )|| !isData( (d2 = base64Data[dataIndex++]) )|| !isData( (d3 = base64Data[dataIndex++]) )|| !isData( (d4 = base64Data[dataIndex++]) )) return null;//if found "no data" just return null b1 = base64Alphabet[d1]; b2 = base64Alphabet[d2]; b3 = base64Alphabet[d3]; b4 = base64Alphabet[d4]; decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ; decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); decodedData[encodedIndex++] = (byte)( b3<<6 | b4 ); } if (!isData( (d1 = base64Data[dataIndex++]) ) || !isData( (d2 = base64Data[dataIndex++]) )) { return null;//if found "no data" just return null } b1 = base64Alphabet[d1]; b2 = base64Alphabet[d2]; d3 = base64Data[dataIndex++]; d4 = base64Data[dataIndex++]; if (!isData( (d3 ) ) || !isData( (d4 ) )) {//Check if they are PAD characters if (isPad( d3 ) && isPad( d4)) { //Two PAD e.g. 3c[Pad][Pad] if ((b2 & 0xf) != 0)//last 4 bits should be zero return null; byte[] tmp = new byte[ i*3 + 1 ]; System.arraycopy( decodedData, 0, tmp, 0, i*3 ); tmp[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; return tmp; } else if (!isPad( d3) && isPad(d4)) { //One PAD e.g. 3cQ[Pad] b3 = base64Alphabet[ d3 ]; if ((b3 & 0x3 ) != 0)//last 2 bits should be zero return null; byte[] tmp = new byte[ i*3 + 2 ]; System.arraycopy( decodedData, 0, tmp, 0, i*3 ); tmp[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ); tmp[encodedIndex] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); return tmp; } else { return null;//an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data } } else { //No PAD e.g 3cQl b3 = base64Alphabet[ d3 ]; b4 = base64Alphabet[ d4 ]; decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ; decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); decodedData[encodedIndex++] = (byte)( b3<<6 | b4 ); } return decodedData; }
// /** // * Decodes Base64 data into octects // * // * @param base64Data String containing Base64 data // * @return string containing decoded data. // */ // public static String decode(String base64Data) { // if (base64Data == null) // return null; // // byte[] decoded = null; // try { // decoded = decode(base64Data.getBytes("utf-8")); // } // catch(UnsupportedEncodingException e) { // } // finally { // return decoded == null ? null : new String(decoded); // } // } // // /** // * Encodes octects (using utf-8) into Base64 data // * // * @param binaryData String containing Hex data // * @return string containing decoded data. // */ // public static String encode(String binaryData) { // if (binaryData == null) // return null; // // byte[] encoded = null; // try { // encoded = encode(binaryData.getBytes("utf-8")); // } // catch(UnsupportedEncodingException e) {} // finally { // return encoded == null ? null : new String(encoded); // } // }
/** * remove WhiteSpace from MIME containing encoded Base64 data. * * @param data the byte array of base64 data (with WS) * @return the byte array of base64 data (without WS) */ protected static byte[] removeWhiteSpace(byte[] data) { if (data == null) return null; // count characters that"s not whitespace int newSize = 0; int len = data.length; for (int i = 0; i < len; i++) { if (!isWhiteSpace(data[i])) newSize++; } // if no whitespace, just return the input array if (newSize == len) return data; // create the array to return byte[] newArray = new byte[newSize]; int j = 0; for (int i = 0; i < len; i++) { if (!isWhiteSpace(data[i])) newArray[j++] = data[i]; } return newArray; }
}
</source>
Encoding of raw bytes to base64-encoded characters, and decoding of base64 characters to raw bytes
<source lang="java">
//////////////////////license & copyright header///////////////////////// // // // Base64 - encode/decode data using the Base64 encoding scheme // // // // Copyright (c) 1998 by Kevin Kelley // // // // This library is free software; you can redistribute it and/or // // modify it under the terms of the GNU Lesser General Public // // License as published by the Free Software Foundation; either // // version 2.1 of the License, or (at your option) any later version. // // // // This library is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY; without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU Lesser General Public License for more details. // // // // You should have received a copy of the GNU Lesser General Public // // License along with this library; if not, write to the Free Software // // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // // 02111-1307, USA, or contact the author: // // // // Kevin Kelley <kelley@ruralnet.net> - 30718 Rd. 28, La Junta, CO, // // 81050 USA. // // // ////////////////////end license & copyright header///////////////////////
import java.io.*; // needed only for main() method.
/**
- Provides encoding of raw bytes to base64-encoded characters, and
- decoding of base64 characters to raw bytes.
- @author Kevin Kelley (kelley@ruralnet.net)
- @version 1.3
- date 06 August 1998
- modified 14 February 2000
- modified 22 September 2000
- /
public class Base64 { /**
- returns an array of base64-encoded characters to represent the
- passed data array.
- @param data the array of bytes to encode
- @return base64-coded character array.
- /
static public char[] encode(byte[] data) {
char[] out = new char[((data.length + 2) / 3) * 4]; // // 3 bytes encode to 4 chars. Output is always an even // multiple of 4 characters. // for (int i=0, index=0; i<data.length; i+=3, index+=4) { boolean quad = false; boolean trip = false; int val = (0xFF & (int) data[i]); val <<= 8; if ((i+1) < data.length) { val |= (0xFF & (int) data[i+1]); trip = true; } val <<= 8; if ((i+2) < data.length) { val |= (0xFF & (int) data[i+2]); quad = true; } out[index+3] = alphabet[(quad? (val & 0x3F): 64)]; val >>= 6; out[index+2] = alphabet[(trip? (val & 0x3F): 64)]; val >>= 6; out[index+1] = alphabet[val & 0x3F]; val >>= 6; out[index+0] = alphabet[val & 0x3F]; } return out;
}
/** * Decodes a BASE-64 encoded stream to recover the original * data. White space before and after will be trimmed away, * but no other manipulation of the input will be performed. * * As of version 1.2 this method will properly handle input * containing junk characters (newlines and the like) rather * than throwing an error. It does this by pre-parsing the * input and generating from that a count of VALID input * characters. **/
static public byte[] decode(char[] data) {
// as our input could contain non-BASE64 data (newlines, // whitespace of any sort, whatever) we must first adjust // our count of USABLE data so that... // (a) we don"t misallocate the output array, and // (b) think that we miscalculated our data length // just because of extraneous throw-away junk int tempLen = data.length; for( int ix=0; ix<data.length; ix++ ) { if( (data[ix] > 255) || codes[ data[ix] ] < 0 ) --tempLen; // ignore non-valid chars and padding } // calculate required length: // -- 3 bytes for every 4 valid base64 chars // -- plus 2 bytes if there are 3 extra base64 chars, // or plus 1 byte if there are 2 extra. int len = (tempLen / 4) * 3; if ((tempLen % 4) == 3) len += 2; if ((tempLen % 4) == 2) len += 1; byte[] out = new byte[len];
int shift = 0; // # of excess bits stored in accum int accum = 0; // excess bits int index = 0; // we now go through the entire array (NOT using the "tempLen" value) for (int ix=0; ix<data.length; ix++) { int value = (data[ix]>255)? -1: codes[ data[ix] ]; if ( value >= 0 ) // skip over non-code { accum <<= 6; // bits shift up by 6 each time thru shift += 6; // loop, with new bits being put in accum |= value; // at the bottom. if ( shift >= 8 ) // whenever there are 8 or more shifted in, { shift -= 8; // write them out (from the top, leaving any out[index++] = // excess at the bottom for next iteration. (byte) ((accum >> shift) & 0xff); } } // we will also have skipped processing a padding null byte ("=") here; // these are used ONLY for padding to an even length and do not legally // occur as encoded data. for this reason we can ignore the fact that // no index++ operation occurs in that special case: the out[] array is // initialized to all-zero bytes to start with and that works to our // advantage in this combination. } // if there is STILL something wrong we just have to throw up now! if( index != out.length) { throw new Error("Miscalculated data length (wrote " + index + " instead of " + out.length + ")"); } return out;
}
// // code characters for values 0..63 // static private char[] alphabet =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" .toCharArray();
// // lookup table for converting base64 characters to value in range 0..63 // static private byte[] codes = new byte[256]; static {
for (int i=0; i<256; i++) codes[i] = -1; for (int i = "A"; i <= "Z"; i++) codes[i] = (byte)( i - "A"); for (int i = "a"; i <= "z"; i++) codes[i] = (byte)(26 + i - "a"); for (int i = "0"; i <= "9"; i++) codes[i] = (byte)(52 + i - "0"); codes["+"] = 62; codes["/"] = 63;
}
///////////////////////////////////////////////////
// remainder (main method and helper functions) is
// for testing purposes only, feel free to clip it.
///////////////////////////////////////////////////
public static void main(String[] args)
{
boolean decode = false; if (args.length == 0) { System.out.println("usage: java Base64 [-d[ecode]] filename"); System.exit(0); } for (int i=0; i<args.length; i++) { if ("-decode".equalsIgnoreCase(args[i])) decode = true; else if ("-d".equalsIgnoreCase(args[i])) decode = true; } String filename = args[args.length-1]; File file = new File(filename); if (!file.exists()) { System.out.println("Error: file "" + filename + "" doesn"t exist!"); System.exit(0); } if (decode) { char[] encoded = readChars(file); byte[] decoded = decode(encoded); writeBytes(file, decoded); } else { byte[] decoded = readBytes(file); char[] encoded = encode(decoded); writeChars(file, encoded); }
} private static byte[] readBytes(File file) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { InputStream fis = new FileInputStream(file); InputStream is = new BufferedInputStream(fis); int count = 0; byte[] buf = new byte[16384]; while ((count=is.read(buf)) != -1) { if (count > 0) baos.write(buf, 0, count); } is.close(); } catch (Exception e) { e.printStackTrace(); } return baos.toByteArray();
} private static char[] readChars(File file) {
CharArrayWriter caw = new CharArrayWriter(); try { Reader fr = new FileReader(file); Reader in = new BufferedReader(fr); int count = 0; char[] buf = new char[16384]; while ((count=in.read(buf)) != -1) { if (count > 0) caw.write(buf, 0, count); } in.close(); } catch (Exception e) { e.printStackTrace(); } return caw.toCharArray();
} private static void writeBytes(File file, byte[] data) {
try { OutputStream fos = new FileOutputStream(file); OutputStream os = new BufferedOutputStream(fos); os.write(data); os.close(); } catch (Exception e) { e.printStackTrace(); }
} private static void writeChars(File file, char[] data) {
try { Writer fos = new FileWriter(file); Writer os = new BufferedWriter(fos); os.write(data); os.close(); } catch (Exception e) { e.printStackTrace(); }
}
}
</source>
Helper class to provide Base64 encoding routines.
<source lang="java">
/*******************************************************************************
* Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. ******************************************************************************/
/**
* Helper class to provide Base64 encoding routines. * * @author ? - added by ksim * @date March 6th, 2007 * @version 1.0 * @todo Not unit tested yet. */
/**
* The Base64Coder class provides methods for encoding strings and byte * arrays into Base64 format. It also provides methods for decoding * Base64-encoded strings and character arrays. * * @version 1.0 beta */
public class Base64Coder {
private Base64Coder() { } /** * Mapping table from 6-bit nibbles to Base64 characters. */ private static char[] map1 = new char[64]; static { int i = 0; for (char c = "A"; c <= "Z"; c++) { map1[i++] = c; } for (char c = "a"; c <= "z"; c++) { map1[i++] = c; } for (char c = "0"; c <= "9"; c++) { map1[i++] = c; } map1[i++] = "+"; map1[i++] = "/"; } /** * Mapping table from Base64 characters to 6-bit nibbles. */ private static byte[] map2 = new byte[128]; static { for (int i = 0; i < map2.length; i++) { map2[i] = -1; } for (int i = 0; i < 64; i++) { map2[map1[i]] = (byte) i; } } /** * The encode (String s) method encodes a string into Base64 format. * No blanks or line breaks are inserted. * * @param s * The string to be encoded. * @return String in Base64-encoded format. */ public static String encode(String s) { return new String(encode(s.getBytes())); } /** * The encode (byte[] in) method encodes a byte array into Base64 * format. No blanks or line breaks are inserted. * * @param in * An array containing the data bytes to be encoded. * @return A character array containing the Base64-encoded data. */ public static char[] encode(byte[] in) { int iLen = in.length; int oDataLen = (iLen * 4 + 2) / 3; // output length without padding int oLen = ((iLen + 2) / 3) * 4; // output length including padding char[] out = new char[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++] & 0xff; int i1 = ip < iLen ? in[ip++] & 0xff : 0; int i2 = ip < iLen ? in[ip++] & 0xff : 0; int o0 = i0 >>> 2; int o1 = ((i0 & 3) << 4) | (i1 >>> 4); int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); int o3 = i2 & 0x3F; out[op++] = map1[o0]; out[op++] = map1[o1]; out[op] = op < oDataLen ? map1[o2] : "="; op++; out[op] = op < oDataLen ? map1[o3] : "="; op++; } return out; } /** * The decode (String s) method decodes a Base64-encoded string. * * @param s * The Base64 String to be decoded. * @return A String containing the decoded data. * @throws IllegalArgumentException * if the input is not valid Base64-encoded data. */ public static String decode(String s) { return new String(decode(s.toCharArray())); } /** * The decode (char[] in) method decodes an array of Base64-encoded * characters. No blanks or line breaks are allowed within the * Base64-encoded data. * * @param in * A character array containing the Base64-encoded data. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException * if the input is not valid Base64-encoded data. */ public static byte[] decode(char[] in) { int iLen = in.length; if (iLen % 4 != 0) throw new IllegalArgumentException( "Length of Base64 encoded input " + "string is not a multiple of 4."); while (iLen > 0 && in[iLen - 1] == "=") iLen--; int oLen = (iLen * 3) / 4; byte[] out = new byte[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++]; int i1 = in[ip++]; int i2 = ip < iLen ? in[ip++] : "A"; int i3 = ip < iLen ? in[ip++] : "A"; if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) throw new IllegalArgumentException("Illegal character in " + "Base64 encoded data."); int b0 = map2[i0]; int b1 = map2[i1]; int b2 = map2[i2]; int b3 = map2[i3]; if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) throw new IllegalArgumentException( "Illegal character in Base64 " + "encoded data."); int o0 = (b0 << 2) | (b1 >>> 4); int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); int o2 = ((b2 & 3) << 6) | b3; out[op++] = (byte) o0; if (op < oLen) { out[op++] = (byte) o1; } if (op < oLen) { out[op++] = (byte) o2; } } return out; }
}
</source>
Implementation of MIME"s Base64 encoding and decoding conversions.
<source lang="java">
/*
* Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */
public class Base64 {
/** * Implementation of MIME"s Base64 encoding and decoding conversions. * Optimized code. (raw version taken from oreilly.jonathan.util, and * currently org.apache.xerces.ds.util.Base64) * * @author Raul Benito(Of the xerces copy, and little adaptations). * @author Anli Shundi * @author Christian Geuer-Pollmann * @see * @see org.apache.xml.security.transforms.implementations.TransformBase64Decode */ /** * Field BASE64DEFAULTLENGTH */ public static final int BASE64DEFAULTLENGTH = 76; /** * Field _base64length */ static int _base64length = Base64.BASE64DEFAULTLENGTH; static private final int BASELENGTH = 255; static private final int LOOKUPLENGTH = 64; static private final int TWENTYFOURBITGROUP = 24; static private final int EIGHTBIT = 8; static private final int SIXTEENBIT = 16; static private final int FOURBYTE = 4; static private final int SIGN = -128; static private final char PAD = "="; static final private byte[] base64Alphabet = new byte[BASELENGTH]; static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; static { for (int i = 0; i < BASELENGTH; i++) { base64Alphabet[i] = -1; } for (int i = "Z"; i >= "A"; i--) { base64Alphabet[i] = (byte) (i - "A"); } for (int i = "z"; i >= "a"; i--) { base64Alphabet[i] = (byte) (i - "a" + 26); } for (int i = "9"; i >= "0"; i--) { base64Alphabet[i] = (byte) (i - "0" + 52); } base64Alphabet["+"] = 62; base64Alphabet["/"] = 63; for (int i = 0; i <= 25; i++) lookUpBase64Alphabet[i] = (char) ("A" + i); for (int i = 26, j = 0; i <= 51; i++, j++) lookUpBase64Alphabet[i] = (char) ("a" + j); for (int i = 52, j = 0; i <= 61; i++, j++) lookUpBase64Alphabet[i] = (char) ("0" + j); lookUpBase64Alphabet[62] = "+"; lookUpBase64Alphabet[63] = "/"; } private Base64() { // we don"t allow instantiation } /** * Encode a byte array and fold lines at the standard 76th character. * * @param binaryData *byte[]<code> to be base64 encoded * @return the <code>String<code> with encoded data */ public static String encode(byte[] binaryData) { return encode(binaryData, BASE64DEFAULTLENGTH, false); } protected static boolean isWhiteSpace(byte octect) { return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); } protected static boolean isPad(byte octect) { return (octect == PAD); } /** * Encode a byte array in Base64 format and return an optionally wrapped line. * * @param binaryData * <code>byte[]
data to be encoded * @param length *int<code> length of wrapped lines; No wrapping if less than 4. * @return a <code>String
with encoded data */ public static String encode(byte[] binaryData, int length, boolean wrap) { if (length < 4) { length = Integer.MAX_VALUE; } if (binaryData == null) return null; int lengthDataBits = binaryData.length * EIGHTBIT; if (lengthDataBits == 0) { return ""; } int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets; int quartesPerLine = length / 4; int numberLines = (numberQuartet - 1) / quartesPerLine; char encodedData[]; encodedData = new char[(numberQuartet * 4) + (wrap ? numberLines : 0)]; byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; int encodedIndex = 0; int dataIndex = 0; int tripletsDone = 0; for (int line = 0; line < numberLines; line++) { for (int quartet = 0; quartet < quartesPerLine; quartet++) { b1 = binaryData[dataIndex++]; b2 = binaryData[dataIndex++]; b3 = binaryData[dataIndex++]; l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; tripletsDone++; } if (wrap) { encodedData[encodedIndex++] = 0xa; } } for (; tripletsDone < numberTriplets; tripletsDone++) { b1 = binaryData[dataIndex++]; b2 = binaryData[dataIndex++]; b3 = binaryData[dataIndex++]; l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; } // form integral number of 6-bit groups if (fewerThan24bits == EIGHTBIT) { b1 = binaryData[dataIndex]; k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; encodedData[encodedIndex++] = PAD; encodedData[encodedIndex++] = PAD; } else if (fewerThan24bits == SIXTEENBIT) { b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; encodedData[encodedIndex++] = PAD; } return new String(encodedData); } /** * Decodes Base64 data into octects * * @param encoded * String containing Base64 data * @return Array containing decoded data. */ public static byte[] decode(String encoded) throws RuntimeException { byte[] base64Data = encoded.getBytes(); // remove white spaces int len = removeWhiteSpace(base64Data); if (len % FOURBYTE != 0) { throw new RuntimeException("decoding.divisible.four"); // should be divisible by four } int numberQuadruple = (len / FOURBYTE); if (numberQuadruple == 0) return new byte[0]; byte decodedData[] = null; byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; int i = 0; int encodedIndex = 0; int dataIndex = 0; // decodedData = new byte[ (numberQuadruple)*3]; dataIndex = (numberQuadruple - 1) * 4; encodedIndex = (numberQuadruple - 1) * 3; // first last bits. b1 = base64Alphabet[base64Data[dataIndex++]]; b2 = base64Alphabet[base64Data[dataIndex++]]; if ((b1 == -1) || (b2 == -1)) { throw new RuntimeException("decoding.general");// if found "no data" just // return null } byte d3, d4; b3 = base64Alphabet[d3 = base64Data[dataIndex++]]; b4 = base64Alphabet[d4 = base64Data[dataIndex++]]; if ((b3 == -1) || (b4 == -1)) { // Check if they are PAD characters if (isPad(d3) && isPad(d4)) { // Two PAD e.g. 3c[Pad][Pad] if ((b2 & 0xf) != 0)// last 4 bits should be zero throw new RuntimeException("decoding.general"); decodedData = new byte[encodedIndex + 1]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); } else if (!isPad(d3) && isPad(d4)) { // One PAD e.g. 3cQ[Pad] if ((b3 & 0x3) != 0)// last 2 bits should be zero throw new RuntimeException("decoding.general"); decodedData = new byte[encodedIndex + 2]; decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); } else { throw new RuntimeException("decoding.general");// an error like // "3c[Pad]r", "3cdX", // "3cXd", "3cXX" where // X is non data } } else { // No PAD e.g 3cQl decodedData = new byte[encodedIndex + 3]; decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); } encodedIndex = 0; dataIndex = 0; // the begin for (i = numberQuadruple - 1; i > 0; i--) { b1 = base64Alphabet[base64Data[dataIndex++]]; b2 = base64Alphabet[base64Data[dataIndex++]]; b3 = base64Alphabet[base64Data[dataIndex++]]; b4 = base64Alphabet[base64Data[dataIndex++]]; if ((b1 == -1) || (b2 == -1) || (b3 == -1) || (b4 == -1)) { throw new RuntimeException("decoding.general");// if found "no data" // just return null } decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); } return decodedData; } /** * remove WhiteSpace from MIME containing encoded Base64 data. * * @param data * the byte array of base64 data (with WS) * @return the new length */ protected static int removeWhiteSpace(byte[] data) { if (data == null) return 0; // count characters that"s not whitespace int newSize = 0; int len = data.length; for (int i = 0; i < len; i++) { byte dataS = data[i]; if (!isWhiteSpace(dataS)) data[newSize++] = dataS; } return newSize; } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub }
}
</source>
One of the fastest implementation of the Base64 encoding. Jakarta and others are slower
<source lang="java">
// Copyright (c) 2003-2009, Jodd Team (jodd.org). All Rights Reserved.
import java.io.IOException; import java.io.OutputStream; import java.io.Writer; /**
* One of the fastest implementation of the Base64 encoding. * Jakarta and others are slower. */
public class Base64 {
private static final char[] S_BASE64CHAR = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/" }; private static final char S_BASE64PAD = "="; private static final byte[] S_DECODETABLE = new byte[128]; static { for (int i = 0; i < S_DECODETABLE.length; i ++) { S_DECODETABLE[i] = Byte.MAX_VALUE; // 127 } for (int i = 0; i < S_BASE64CHAR.length; i ++) // 0 to 63 { S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i; } } private static int decode0(char[] ibuf, byte[] obuf, int wp) { int outlen = 3; if (ibuf[3] == S_BASE64PAD) { outlen = 2; } if (ibuf[2] == S_BASE64PAD) { outlen = 1; } int b0 = S_DECODETABLE[ibuf[0]]; int b1 = S_DECODETABLE[ibuf[1]]; int b2 = S_DECODETABLE[ibuf[2]]; int b3 = S_DECODETABLE[ibuf[3]]; switch (outlen) { case 1: obuf[wp] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); return 1; case 2: obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); obuf[wp] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf); return 2; case 3: obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); obuf[wp++] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf); obuf[wp] = (byte) (b2 << 6 & 0xc0 | b3 & 0x3f); return 3; default: throw new RuntimeException("Internal Error"); } } /** * Decode the base64 data. * @param data The base64 encoded data to be decoded * @param off The offset within the encoded data at which to start decoding * @param len The length of data to decode * @return The decoded data */ public static byte[] decode(char[] data, int off, int len) { char[] ibuf = new char[4]; int ibufcount = 0; byte[] obuf = new byte[(len >> 2) * 3 + 3]; int obufcount = 0; for (int i = off; i < off+len; i ++) { char ch = data[i]; if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; if (ibufcount == ibuf.length) { ibufcount = 0; obufcount += decode0(ibuf, obuf, obufcount); } } } if (obufcount == obuf.length) { return obuf; } byte[] ret = new byte[obufcount]; System.arraycopy(obuf, 0, ret, 0, obufcount); return ret; } public static final int BUF_SIZE = 256; /** * Decode the base64 data. * @param data The base64 encoded data to be decoded * @return The decoded data */ public static byte[] decode(String data) { int ibufcount = 0; int slen = data.length(); char[] ibuf = new char[slen < BUF_SIZE +3 ? slen : BUF_SIZE + 3]; byte[] obuf = new byte[(slen >> 2) *3+3]; int obufcount = 0; int blen; for (int i = 0; i < slen; i +=BUF_SIZE ) { // buffer may contain unprocessed characters from previous step if (i + BUF_SIZE <= slen) { data.getChars(i, i+BUF_SIZE , ibuf, ibufcount); blen = BUF_SIZE + ibufcount; } else { data.getChars(i, slen, ibuf, ibufcount); blen = slen - i+ibufcount; } for (int j=ibufcount; j<blen; j++) { char ch = ibuf[j]; if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; // as soon as we have 4 chars process them if (ibufcount == 4) { ibufcount = 0; obufcount += decode0(ibuf, obuf, obufcount); } } } } if (obufcount == obuf.length) { return obuf; } byte[] ret = new byte[obufcount]; System.arraycopy(obuf, 0, ret, 0, obufcount); return ret; } /** * Decode the base64 data. * @param data The base64 encoded data to be decoded * @param off The offset within the encoded data at which to start decoding * @param len The length of data to decode * @param ostream The OutputStream to which the decoded data should be * written */ public static void decode(char[] data, int off, int len, OutputStream ostream) throws IOException { char[] ibuf = new char[4]; int ibufcount = 0; byte[] obuf = new byte[3]; for (int i = off; i < off+len; i ++) { char ch = data[i]; if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; if (ibufcount == ibuf.length) { ibufcount = 0; int obufcount = decode0(ibuf, obuf, 0); ostream.write(obuf, 0, obufcount); } } } } /** * Decode the base64 data. * @param data The base64 encoded data to be decoded * @param ostream The OutputStream to which the decoded data should be * written */ public static void decode(String data, OutputStream ostream) throws IOException { char[] ibuf = new char[BUF_SIZE + 4]; byte[] obuf = new byte[3]; int slen = data.length(); int blen; int ibufcount = 0; for (int i = 0; i < slen; i +=BUF_SIZE ) { // buffer may contain unprocessed characters from previous step if (i + BUF_SIZE <= slen) { data.getChars(i, i + BUF_SIZE , ibuf, ibufcount); blen = BUF_SIZE+ibufcount; } else { data.getChars(i, slen, ibuf, ibufcount); blen = slen - i+ibufcount; } for (int j=ibufcount; j<blen; j++) { char ch = ibuf[j]; if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; // as sson as we have 4 chars process them if (ibufcount == 4) { ibufcount = 0; int obufcount = decode0(ibuf, obuf, 0); ostream.write(obuf, 0, obufcount); } } } } } /** * Returns base64 representation of specified byte array. * @param data The data to be encoded * @return The base64 encoded data */ public static String encode(byte[] data) { return encode(data, 0, data.length); } public static String encode(String s) { return encode(s.getBytes(), 0, s.length()); } /** * Returns base64 representation of specified byte array. * @param data The data to be encoded * @param off The offset within the data at which to start encoding * @param len The length of the data to encode * @return The base64 encoded data */ public static String encode(byte[] data, int off, int len) { if (len <= 0) { return ""; } char[] out = new char[(len / 3 << 2) +4]; int rindex = off; int windex = 0; int rest = len; while (rest >= 3) { int i = ((data[rindex]&0xff)<<16) +((data[rindex+1]&0xff)<<8) +(data[rindex+2]&0xff); out[windex++] = S_BASE64CHAR[i>>18]; out[windex++] = S_BASE64CHAR[(i>>12)&0x3f]; out[windex++] = S_BASE64CHAR[(i>>6)&0x3f]; out[windex++] = S_BASE64CHAR[i&0x3f]; rindex += 3; rest -= 3; } if (rest == 1) { int i = data[rindex]&0xff; out[windex++] = S_BASE64CHAR[i>>2]; out[windex++] = S_BASE64CHAR[(i<<4)&0x3f]; out[windex++] = S_BASE64PAD; out[windex++] = S_BASE64PAD; } else if (rest == 2) { int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff); out[windex++] = S_BASE64CHAR[i>>10]; out[windex++] = S_BASE64CHAR[(i>>4)&0x3f]; out[windex++] = S_BASE64CHAR[(i<<2)&0x3f]; out[windex++] = S_BASE64PAD; } return new String(out, 0, windex); } /** * Outputs base64 representation of the specified byte array to a byte stream. * @param data The data to be encoded * @param off The offset within the data at which to start encoding * @param len The length of the data to encode * @param ostream The OutputStream to which the encoded data should be * written */ public static void encode(byte[] data, int off, int len, OutputStream ostream) throws IOException { if (len <= 0) { return; } byte[] out = new byte[4]; int rindex = off; int rest = len; while (rest >= 3) { int i = ((data[rindex]&0xff)<<16) +((data[rindex+1]&0xff)<<8) +(data[rindex+2]&0xff); out[0] = (byte)S_BASE64CHAR[i>>18]; out[1] = (byte)S_BASE64CHAR[(i>>12)&0x3f]; out[2] = (byte)S_BASE64CHAR[(i>>6)&0x3f]; out[3] = (byte)S_BASE64CHAR[i&0x3f]; ostream.write(out, 0, 4); rindex += 3; rest -= 3; } if (rest == 1) { int i = data[rindex]&0xff; out[0] = (byte)S_BASE64CHAR[i>>2]; out[1] = (byte)S_BASE64CHAR[(i<<4)&0x3f]; out[2] = (byte)S_BASE64PAD; out[3] = (byte)S_BASE64PAD; ostream.write(out, 0, 4); } else if (rest == 2) { int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff); out[0] = (byte)S_BASE64CHAR[i>>10]; out[1] = (byte)S_BASE64CHAR[(i>>4)&0x3f]; out[2] = (byte)S_BASE64CHAR[(i<<2)&0x3f]; out[3] = (byte)S_BASE64PAD; ostream.write(out, 0, 4); } } /** * Outputs base64 representation of the specified byte array to a character stream. * @param data The data to be encoded * @param off The offset within the data at which to start encoding * @param len The length of the data to encode * @param writer The Writer to which the encoded data should be * written */ public static void encode(byte[] data, int off, int len, Writer writer) throws IOException { if (len <= 0) { return; } char[] out = new char[4]; int rindex = off; int rest = len; int output = 0; while (rest >= 3) { int i = ((data[rindex]&0xff)<<16) +((data[rindex+1]&0xff)<<8) +(data[rindex+2]&0xff); out[0] = S_BASE64CHAR[i>>18]; out[1] = S_BASE64CHAR[(i>>12)&0x3f]; out[2] = S_BASE64CHAR[(i>>6)&0x3f]; out[3] = S_BASE64CHAR[i&0x3f]; writer.write(out, 0, 4); rindex += 3; rest -= 3; output += 4; if (output % 76 == 0) { writer.write("\n"); } } if (rest == 1) { int i = data[rindex]&0xff; out[0] = S_BASE64CHAR[i>>2]; out[1] = S_BASE64CHAR[(i<<4)&0x3f]; out[2] = S_BASE64PAD; out[3] = S_BASE64PAD; writer.write(out, 0, 4); } else if (rest == 2) { int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff); out[0] = S_BASE64CHAR[i>>10]; out[1] = S_BASE64CHAR[(i>>4)&0x3f]; out[2] = S_BASE64CHAR[(i<<2)&0x3f]; out[3] = S_BASE64PAD; writer.write(out, 0, 4); } }
}
</source>
Performs Base64 encoding and/or decoding
<source lang="java">
/*
* Copyright 1999,2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.UndeclaredThrowableException; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException;
/** Performs Base64 encoding and/or decoding. This is an on-the-fly decoder: Unlike,
* for example, the commons-codec classes, it doesn"t depend on byte arrays. In * other words, it has an extremely low memory profile. This is well suited even * for very large byte streams. */
public class Base64 {
/** An exception of this type is thrown, if the decoded * character stream contains invalid input. */ public static class DecodingException extends IOException { private static final long serialVersionUID = 3257006574836135478L; DecodingException(String pMessage) { super(pMessage); } } /** An exception of this type is thrown by the {@link SAXEncoder}, * if writing to the target handler causes a SAX exception. * This class is required, because the {@link IOException} * allows no cause until Java 1.3. */ public static class SAXIOException extends IOException { private static final long serialVersionUID = 3258131345216451895L; final SAXException saxException; SAXIOException(SAXException e) { super(); saxException = e; } /** Returns the encapsulated {@link SAXException}. * @return An exception, which was thrown when invoking * {@link ContentHandler#characters(char[], int, int)}. */ public SAXException getSAXException() { return saxException; } }
/** Default line separator: \n */ public static final String LINE_SEPARATOR = "\n"; /** Default size for line wrapping. */ public static final int LINE_SIZE = 76; /** * This array is a lookup table that translates 6-bit positive integer * index values into their "Base64 Alphabet" equivalents as specified * in Table 1 of RFC 2045. */ private static final char intToBase64[] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/" }; /** * This array is a lookup table that translates unicode characters * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045) * into their 6-bit positive integer equivalents. Characters that * are not in the Base64 alphabet but fall within the bounds of the * array are translated to -1. */ private static final byte base64ToInt[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; /** An encoder is an object, which is able to encode byte array * in blocks of three bytes. Any such block is converted into an * array of four bytes. */ public static abstract class Encoder { private int num, numBytes; private final char[] charBuffer; private int charOffset; private final int wrapSize; private final int skipChars; private final String sep; private int lineChars = 0; /** Creates a new instance. * @param pBuffer The encoders buffer. The encoder will * write to the buffer as long as possible. If the * buffer is full or the end of data is signaled, then * the method {@link #writeBuffer(char[], int, int)} * will be invoked. * @param pWrapSize A nonzero value indicates, that a line * wrap should be performed after the given number of * characters. The value must be a multiple of 4. Zero * indicates, that no line wrap should be performed. * @param pSep The eol sequence being used to terminate * a line in case of line wraps. May be null, in which * case the default value {@link Base64#LINE_SEPARATOR} * is being used. */ protected Encoder(char[] pBuffer, int pWrapSize, String pSep) { charBuffer = pBuffer; sep = pSep == null ? null : Base64.LINE_SEPARATOR; skipChars = pWrapSize == 0 ? 4 : 4 + sep.length(); wrapSize = skipChars == 4 ? 0 : pWrapSize; if (wrapSize < 0 || wrapSize %4 > 0) { throw new IllegalArgumentException("Illegal argument for wrap size: " + pWrapSize + "(Expected nonnegative multiple of 4)"); } if (pBuffer.length < skipChars) { throw new IllegalArgumentException("The buffer must contain at least " + skipChars + " characters, but has " + pBuffer.length); } } /** Called for writing the buffer contents to the target. * @param pChars The buffer being written. * @param pOffset Offset of first character being written. * @param pLen Number of characters being written. * @throws IOException Writing to the destination failed. */ protected abstract void writeBuffer(char[] pChars, int pOffset, int pLen) throws IOException; private void wrap() { for (int j = 0; j < sep.length(); j++) { charBuffer[charOffset++] = sep.charAt(j); } lineChars = 0; } /** Encodes the given byte array. * @param pBuffer Byte array being encoded. * @param pOffset Offset of first byte being encoded. * @param pLen Number of bytes being encoded. * @throws IOException Invoking the {@link #writeBuffer(char[],int,int)} method * for writing the encoded data failed. */ public void write(byte[] pBuffer, int pOffset, int pLen) throws IOException { for(int i = 0; i < pLen; i++) { int b = pBuffer[pOffset++]; if (b < 0) { b += 256; } num = (num << 8) + b; if (++numBytes == 3) { charBuffer[charOffset++] = intToBase64[num >> 18]; charBuffer[charOffset++] = intToBase64[(num >> 12) & 0x3f]; charBuffer[charOffset++] = intToBase64[(num >> 6) & 0x3f]; charBuffer[charOffset++] = intToBase64[num & 0x3f]; if (wrapSize > 0) { lineChars += 4; if (lineChars >= wrapSize) { wrap(); } } num = 0; numBytes = 0; if (charOffset + skipChars > charBuffer.length) { writeBuffer(charBuffer, 0, charOffset); charOffset = 0; } } } } /** Writes any currently buffered data to the destination. * @throws IOException Invoking the {@link #writeBuffer(char[],int,int)} * method for writing the encoded data failed. */ public void flush() throws IOException { if (numBytes > 0) { if (numBytes == 1) { charBuffer[charOffset++] = intToBase64[num >> 2]; charBuffer[charOffset++] = intToBase64[(num << 4) & 0x3f]; charBuffer[charOffset++] = "="; charBuffer[charOffset++] = "="; } else { charBuffer[charOffset++] = intToBase64[num >> 10]; charBuffer[charOffset++] = intToBase64[(num >> 4) & 0x3f]; charBuffer[charOffset++] = intToBase64[(num << 2) & 0x3f]; charBuffer[charOffset++] = "="; } lineChars += 4; num = 0; numBytes = 0; } if (wrapSize > 0 && lineChars > 0) { wrap(); } if (charOffset > 0) { writeBuffer(charBuffer, 0, charOffset); charOffset = 0; } } } /** An {@link OutputStream}, which is writing to the given * {@link Encoder}. */ public static class EncoderOutputStream extends OutputStream { private final Encoder encoder; /** Creates a new instance, which is creating * output using the given {@link Encoder}. * @param pEncoder The base64 encoder being used. */ public EncoderOutputStream(Encoder pEncoder) { encoder = pEncoder; } private final byte[] oneByte = new byte[1]; public void write(int b) throws IOException { oneByte[0] = (byte) b; encoder.write(oneByte, 0, 1); } public void write(byte[] pBuffer, int pOffset, int pLen) throws IOException { encoder.write(pBuffer, pOffset, pLen); } public void close() throws IOException { encoder.flush(); } } /** Returns an {@link OutputStream}, that encodes its input in Base64 * and writes it to the given {@link Writer}. If the Base64 stream * ends, then the output streams {@link OutputStream#close()} method * must be invoked. Note, that this will not close the * target {@link Writer}! * @param pWriter Target writer. * @return An output stream, encoding its input in Base64 and writing * the output to the writerpWriter
. */ public static OutputStream newEncoder(Writer pWriter) { return newEncoder(pWriter, LINE_SIZE, LINE_SEPARATOR); } /** Returns an {@link OutputStream}, that encodes its input in Base64 * and writes it to the given {@link Writer}. If the Base64 stream * ends, then the output streams {@link OutputStream#close()} method * must be invoked. Note, that this will not close the * target {@link Writer}! * @param pWriter Target writer. * @param pLineSize Size of one line in characters, must be a multiple * of four. Zero indicates, that no line wrapping should occur. * @param pSeparator Line separator or null, in which case the default value * {@link #LINE_SEPARATOR} is used. * @return An output stream, encoding its input in Base64 and writing * the output to the writerpWriter
. */ public static OutputStream newEncoder(final Writer pWriter, int pLineSize, String pSeparator) { final Encoder encoder = new Encoder(new char[4096], pLineSize, pSeparator){ protected void writeBuffer(char[] pBuffer, int pOffset, int pLen) throws IOException { pWriter.write(pBuffer, pOffset, pLen); } }; return new EncoderOutputStream(encoder); } /** An {@link Encoder}, which is writing to a SAX content handler. * This is typically used for embedding a base64 stream into an * XML document. */ public static class SAXEncoder extends Encoder { private final ContentHandler handler; /** Creates a new instance. * @param pBuffer The encoders buffer. * @param pWrapSize A nonzero value indicates, that a line * wrap should be performed after the given number of * characters. The value must be a multiple of 4. Zero * indicates, that no line wrap should be performed. * @param pSep The eol sequence being used to terminate * a line in case of line wraps. May be null, in which * case the default value {@link Base64#LINE_SEPARATOR} * is being used. * @param pHandler The target handler. */ public SAXEncoder(char[] pBuffer, int pWrapSize, String pSep, ContentHandler pHandler) { super(pBuffer, pWrapSize, pSep); handler = pHandler; } /** Writes to the content handler. * @throws SAXIOException Writing to the content handler * caused a SAXException. */ protected void writeBuffer(char[] pChars, int pOffset, int pLen) throws IOException { try { handler.characters(pChars, pOffset, pLen); } catch (SAXException e) { throw new SAXIOException(e); } } } /** Converts the given byte array into a base64 encoded character * array. * @param pBuffer The buffer being encoded. * @param pOffset Offset in buffer, where to begin encoding. * @param pLength Number of bytes being encoded. * @return Character array of encoded bytes. */ public static String encode(byte[] pBuffer, int pOffset, int pLength) { return encode(pBuffer, pOffset, pLength, LINE_SIZE, LINE_SEPARATOR); } /** Converts the given byte array into a base64 encoded character * array. * @param pBuffer The buffer being encoded. * @param pOffset Offset in buffer, where to begin encoding. * @param pLength Number of bytes being encoded. * @param pLineSize Size of one line in characters, must be a multiple * of four. Zero indicates, that no line wrapping should occur. * @param pSeparator Line separator or null, in which case the default value * {@link #LINE_SEPARATOR} is used. * @return Character array of encoded bytes. */ public static String encode(byte[] pBuffer, int pOffset, int pLength, int pLineSize, String pSeparator) { StringWriter sw = new StringWriter(); OutputStream ostream = newEncoder(sw, pLineSize, pSeparator); try { ostream.write(pBuffer, pOffset, pLength); ostream.close(); } catch (IOException e) { throw new UndeclaredThrowableException(e); } return sw.toString(); } /** Converts the given byte array into a base64 encoded character * array with the line size {@link #LINE_SIZE} and the separator * {@link #LINE_SEPARATOR}. * @param pBuffer The buffer being encoded. * @return Character array of encoded bytes. */ public static String encode(byte[] pBuffer) { return encode(pBuffer, 0, pBuffer.length); } /** An encoder is an object, which is able to decode char arrays * in blocks of four bytes. Any such block is converted into a * array of three bytes. */ public static abstract class Decoder { private final byte[] byteBuffer; private int byteBufferOffset; private int num, numBytes; private int eofBytes; /** Creates a new instance. * @param pBufLen The decoders buffer size. The decoder will * store up to this number of decoded bytes before invoking * {@link #writeBuffer(byte[],int,int)}. */ protected Decoder(int pBufLen) { byteBuffer = new byte[pBufLen]; } /** Called for writing the decoded bytes to the destination. * @param pBuffer The byte array being written. * @param pOffset Offset of the first byte being written. * @param pLen Number of bytes being written. * @throws IOException Writing to the destination failed. */ protected abstract void writeBuffer(byte[] pBuffer, int pOffset, int pLen) throws IOException; /** Converts the Base64 encoded character array. * @param pData The character array being decoded. * @param pOffset Offset of first character being decoded. * @param pLen Number of characters being decoded. * @throws DecodingException Decoding failed. * @throws IOException An invocation of the {@link #writeBuffer(byte[],int,int)} * method failed. */ public void write(char[] pData, int pOffset, int pLen) throws IOException { for (int i = 0; i < pLen; i++) { char c = pData[pOffset++]; if (Character.isWhitespace(c)) { continue; } if (c == "=") { ++eofBytes; num = num << 6; switch(++numBytes) { case 1: case 2: throw new DecodingException("Unexpected end of stream character (=)"); case 3: // Wait for the next "=" break; case 4: byteBuffer[byteBufferOffset++] = (byte) (num >> 16); if (eofBytes == 1) { byteBuffer[byteBufferOffset++] = (byte) (num >> 8); } writeBuffer(byteBuffer, 0, byteBufferOffset); byteBufferOffset = 0; break; case 5: throw new DecodingException("Trailing garbage detected"); default: throw new IllegalStateException("Invalid value for numBytes"); } } else { if (eofBytes > 0) { throw new DecodingException("Base64 characters after end of stream character (=) detected."); } int result; if (c >= 0 && c < base64ToInt.length) { result = base64ToInt[c]; if (result >= 0) { num = (num << 6) + result; if (++numBytes == 4) { byteBuffer[byteBufferOffset++] = (byte) (num >> 16); byteBuffer[byteBufferOffset++] = (byte) ((num >> 8) & 0xff); byteBuffer[byteBufferOffset++] = (byte) (num & 0xff); if (byteBufferOffset + 3 > byteBuffer.length) { writeBuffer(byteBuffer, 0, byteBufferOffset); byteBufferOffset = 0; } num = 0; numBytes = 0; } continue; } } if (!Character.isWhitespace(c)) { throw new DecodingException("Invalid Base64 character: " + (int) c); } } } } /** Indicates, that no more data is being expected. Writes all currently * buffered data to the destination by invoking {@link #writeBuffer(byte[],int,int)}. * @throws DecodingException Decoding failed (Unexpected end of file). * @throws IOException An invocation of the {@link #writeBuffer(byte[],int,int)} method failed. */ public void flush() throws IOException { if (numBytes != 0 && numBytes != 4) { throw new DecodingException("Unexpected end of file"); } if (byteBufferOffset > 0) { writeBuffer(byteBuffer, 0, byteBufferOffset); byteBufferOffset = 0; } } } /** Returns a {@link Writer}, that decodes its Base64 encoded * input and writes it to the given {@link OutputStream}. * Note, that the writers {@link Writer#close()} method will * not close the output streampStream
! * @param pStream Target output stream. * @return An output stream, encoding its input in Base64 and writing * the output to the writerpWriter
. */ public Writer newDecoder(final OutputStream pStream) { return new Writer(){ private final Decoder decoder = new Decoder(1024){ protected void writeBuffer(byte[] pBytes, int pOffset, int pLen) throws IOException { pStream.write(pBytes, pOffset, pLen); } }; public void close() throws IOException { flush(); } public void flush() throws IOException { decoder.flush(); pStream.flush(); } public void write(char[] cbuf, int off, int len) throws IOException { decoder.write(cbuf, off, len); } }; } /** Converts the given base64 encoded character buffer into a byte array. * @param pBuffer The character buffer being decoded. * @param pOffset Offset of first character being decoded. * @param pLength Number of characters being decoded. * @return Converted byte array * @throws DecodingException The input character stream contained invalid data. */ public static byte[] decode(char[] pBuffer, int pOffset, int pLength) throws DecodingException { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); Decoder d = new Decoder(1024){ protected void writeBuffer(byte[] pBuf, int pOff, int pLen) throws IOException { baos.write(pBuf, pOff, pLen); } }; try { d.write(pBuffer, pOffset, pLength); d.flush(); } catch (DecodingException e) { throw e; } catch (IOException e) { throw new UndeclaredThrowableException(e); } return baos.toByteArray(); } /** Converts the given base64 encoded character buffer into a byte array. * @param pBuffer The character buffer being decoded. * @return Converted byte array * @throws DecodingException The input character stream contained invalid data. */ public static byte[] decode(char[] pBuffer) throws DecodingException { return decode(pBuffer, 0, pBuffer.length); } /** Converts the given base64 encoded String into a byte array. * @param pBuffer The string being decoded. * @return Converted byte array * @throws DecodingException The input character stream contained invalid data. */ public static byte[] decode(String pBuffer) throws DecodingException { return decode(pBuffer.toCharArray()); }
}
</source>
Provides Base64 encoding and decoding as defined by RFC 2045
<source lang="java">
/*
* $Id: Base64.java 460331 2006-04-18 22:03:12Z dashorst $ * $Revision: 460331 $ $Date: 2006-04-19 00:03:12 +0200 (Wed, 19 Apr 2006) $ * * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */
/**
* Provides Base64 encoding and decoding as defined by RFC 2045. * <p/> * This class is taken from the Apache commons-codec, and adjusted to fit the * Wicket framework"s needs, especially external dependencies have been removed.*
* <p/> * This class implements section 6.8. Base64 Content-Transfer-Encoding * from RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: * Format of Internet Message Bodies by Freed and Borenstein.</p> * * @author Apache Software Foundation * @since 1.2 */
public class Base64 {
/** * Chunk size per RFC 2045 section 6.8. * <p/>*
The {@value} character limit does not count the trailing CRLF, but counts * all other characters, including any equal signs.
* * @see */ static final byte[] CHUNK_SEPARATOR = "\r\n".getBytes(); /** * The base length. */ static final int BASELENGTH = 255; /** * Lookup length. */ static final int LOOKUPLENGTH = 64; /** * Used to calculate the number of bits in a byte. */ static final int EIGHTBIT = 8; /** * Used when encoding something which has fewer than 24 bits. */ static final int SIXTEENBIT = 16; /** * Used to determine how many bits data contains. */ static final int TWENTYFOURBITGROUP = 24; /** * Used to get the number of Quadruples. */ static final int FOURBYTE = 4; /** * Used to test the sign of a byte. */ static final int SIGN = -128; /** * Byte used to pad output. */ static final byte PAD = (byte) "="; /** * Contains the Base64 values0
through63
accessed by using character encodings as * indices. * <p/> * For example,base64Alphabet["+"]
returns62
. * </p> * <p/> * The value of undefined encodings is-1
. * </p> */ private static byte[] base64Alphabet = new byte[BASELENGTH]; /** * <p/> * Contains the Base64 encodingsA
throughZ
, followed bya
through *z
, followed by0
through9
, followed by+
, and */
. * </p> * <p/> * This array is accessed by using character values as indices. * </p> * <p/> * For example,lookUpBase64Alphabet[62]
returns"+"
. * </p> */ private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; // Populating the lookup and character arrays static { for (int i = 0; i < BASELENGTH; i++) { base64Alphabet[i] = (byte) -1; } for (int i = "Z"; i >= "A"; i--) { base64Alphabet[i] = (byte) (i - "A"); } for (int i = "z"; i >= "a"; i--) { base64Alphabet[i] = (byte) (i - "a" + 26); } for (int i = "9"; i >= "0"; i--) { base64Alphabet[i] = (byte) (i - "0" + 52); } base64Alphabet["+"] = 62; base64Alphabet["/"] = 63; for (int i = 0; i <= 25; i++) { lookUpBase64Alphabet[i] = (byte) ("A" + i); } for (int i = 26, j = 0; i <= 51; i++, j++) { lookUpBase64Alphabet[i] = (byte) ("a" + j); } for (int i = 52, j = 0; i <= 61; i++, j++) { lookUpBase64Alphabet[i] = (byte) ("0" + j); } lookUpBase64Alphabet[62] = (byte) "+"; lookUpBase64Alphabet[63] = (byte) "/"; } /** * Returns whether or not theoctect
is in the base 64 alphabet. * * @param octect The value to test * @returntrue
if the value is defined in the the base 64 alphabet,false
otherwise. */ private static boolean isBase64(byte octect) { if (octect == PAD) { return true; } else if (octect < 0 || base64Alphabet[octect] == -1) { return false; } else { return true; } } /** * Tests a given byte array to see if it contains * only valid characters within the Base64 alphabet. * * @param arrayOctect byte array to test * @returntrue
if all bytes are valid characters in the Base64 * alphabet or if the byte array is empty; false, otherwise */ public static boolean isArrayByteBase64(byte[] arrayOctect) { arrayOctect = discardWhitespace(arrayOctect); int length = arrayOctect.length; if (length == 0) { // shouldn"t a 0 length array be valid base64 data? // return false; return true; } for (int i = 0; i < length; i++) { if (!isBase64(arrayOctect[i])) { return false; } } return true; } /** * Encodes binary data using the base64 algorithm but * does not chunk the output. * * @param binaryData binary data to encode * @return Base64 characters */ public static byte[] encodeBase64(byte[] binaryData) { return encodeBase64(binaryData, false); } /** * Encodes binary data using the base64 algorithm and chunks * the encoded output into 76 character blocks * * @param binaryData binary data to encode * @return Base64 characters chunked in 76 character blocks */ public static byte[] encodeBase64Chunked(byte[] binaryData) { return encodeBase64(binaryData, true); }
/**
* Decodes an Object using the base64 algorithm. This method
* is provided in order to satisfy the requirements of the
* Decoder interface, and will throw a DecoderException if the
* supplied object is not of type byte[].
*
* @param pObject Object to decode
* @return An object (of type byte[]) containing the
* binary data which corresponds to the byte[] supplied.
* @throws IllegalArgumentException if the parameter supplied is not
* of type byte[]
*/
public Object decode(Object pObject)
{
if (!(pObject instanceof byte[]))
{
throw new IllegalArgumentException("Parameter supplied to Base64 decode is not a byte[]");
}
return decode((byte[]) pObject);
}
/**
* Decodes a byte[] containing containing
* characters in the Base64 alphabet.
*
* @param pArray A byte array containing Base64 character data
* @return a byte array containing binary data
*/
public byte[] decode(byte[] pArray)
{
return decodeBase64(pArray);
}
/**
* Encodes binary data using the base64 algorithm, optionally
* chunking the output into 76 character blocks.
*
* @param binaryData Array containing binary data to encode.
* @param isChunked if true
this encoder will chunk
* the base64 output into 76 character blocks
* @return Base64-encoded data.
*/
public static byte[] encodeBase64(byte[] binaryData, boolean isChunked)
{
int lengthDataBits = binaryData.length * EIGHTBIT;
int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
byte encodedData[] = null;
int encodedDataLength = 0;
int nbrChunks = 0;
if (fewerThan24bits != 0)
{
//data not divisible by 24 bit
encodedDataLength = (numberTriplets + 1) * 4;
}
else
{
// 16 or 8 bit
encodedDataLength = numberTriplets * 4;
}
// If the output is to be "chunked" into 76 character sections,
// for compliance with RFC 2045 MIME, then it is important to
// allow for extra length to account for the separator(s)
if (isChunked)
{
nbrChunks =
(CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((float) encodedDataLength / CHUNK_SIZE));
encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length;
}
encodedData = new byte[encodedDataLength];
byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
int encodedIndex = 0;
int dataIndex = 0;
int i = 0;
int nextSeparatorIndex = CHUNK_SIZE;
int chunksSoFar = 0;
//log.debug("number of triplets = " + numberTriplets);
for (i = 0; i < numberTriplets; i++)
{
dataIndex = i * 3;
b1 = binaryData[dataIndex];
b2 = binaryData[dataIndex + 1];
b3 = binaryData[dataIndex + 2];
//log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03);
byte val1 =
((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
byte val2 =
((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
byte val3 =
((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
//log.debug( "val2 = " + val2 );
//log.debug( "k4 = " + (k<<4) );
//log.debug( "vak = " + (val2 | (k<<4)) );
encodedData[encodedIndex + 1] =
lookUpBase64Alphabet[val2 | (k << 4)];
encodedData[encodedIndex + 2] =
lookUpBase64Alphabet[(l << 2) | val3];
encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f];
encodedIndex += 4;
// If we are chunking, let"s put a chunk separator down.
if (isChunked)
{
// this assumes that CHUNK_SIZE % 4 == 0
if (encodedIndex == nextSeparatorIndex)
{
System.arraycopy(
CHUNK_SEPARATOR,
0,
encodedData,
encodedIndex,
CHUNK_SEPARATOR.length);
chunksSoFar++;
nextSeparatorIndex =
(CHUNK_SIZE * (chunksSoFar + 1)) +
(chunksSoFar * CHUNK_SEPARATOR.length);
encodedIndex += CHUNK_SEPARATOR.length;
}
}
}
// form integral number of 6-bit groups
dataIndex = i * 3;
if (fewerThan24bits == EIGHTBIT)
{
b1 = binaryData[dataIndex];
k = (byte) (b1 & 0x03);
//log.debug("b1=" + b1);
//log.debug("b1<<2 = " + (b1>>2) );
byte val1 =
((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4];
encodedData[encodedIndex + 2] = PAD;
encodedData[encodedIndex + 3] = PAD;
}
else if (fewerThan24bits == SIXTEENBIT)
{
b1 = binaryData[dataIndex];
b2 = binaryData[dataIndex + 1];
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03);
byte val1 =
((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
byte val2 =
((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex + 1] =
lookUpBase64Alphabet[val2 | (k << 4)];
encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
encodedData[encodedIndex + 3] = PAD;
}
if (isChunked)
{
// we also add a separator to the end of the final chunk.
if (chunksSoFar < nbrChunks)
{
System.arraycopy(
CHUNK_SEPARATOR,
0,
encodedData,
encodedDataLength - CHUNK_SEPARATOR.length,
CHUNK_SEPARATOR.length);
}
}
return encodedData;
}
/**
* Decodes Base64 data into octects
*
* @param base64Data Byte array containing Base64 data
* @return Array containing decoded data.
*/
public static byte[] decodeBase64(byte[] base64Data)
{
// RFC 2045 requires that we discard ALL non-Base64 characters
base64Data = discardNonBase64(base64Data);
// handle the edge case, so we don"t have to worry about it later
if (base64Data.length == 0)
{
return new byte[0];
}
int numberQuadruple = base64Data.length / FOURBYTE;
byte decodedData[] = null;
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
// Throw away anything not in base64Data
int encodedIndex = 0;
int dataIndex = 0;
{
// this sizes the output array properly - rlw
int lastData = base64Data.length;
// ignore the "=" padding
while (base64Data[lastData - 1] == PAD)
{
if (--lastData == 0)
{
return new byte[0];
}
}
decodedData = new byte[lastData - numberQuadruple];
}
for (int i = 0; i < numberQuadruple; i++)
{
dataIndex = i * 4;
marker0 = base64Data[dataIndex + 2];
marker1 = base64Data[dataIndex + 3];
b1 = base64Alphabet[base64Data[dataIndex]];
b2 = base64Alphabet[base64Data[dataIndex + 1]];
if (marker0 != PAD && marker1 != PAD)
{
//No PAD e.g 3cQl
b3 = base64Alphabet[marker0];
b4 = base64Alphabet[marker1];
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex + 1] =
(byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
}
else if (marker0 == PAD)
{
//Two PAD e.g. 3c[Pad][Pad]
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
}
else if (marker1 == PAD)
{
//One PAD e.g. 3cQ[Pad]
b3 = base64Alphabet[marker0];
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex + 1] =
(byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
}
encodedIndex += 3;
}
return decodedData;
}
/**
* Discards any whitespace from a base-64 encoded block.
*
* @param data The base-64 encoded data to discard the whitespace
* from.
* @return The data, less whitespace (see RFC 2045).
*/
static byte[] discardWhitespace(byte[] data)
{
byte groomedData[] = new byte[data.length];
int bytesCopied = 0;
for (int i = 0; i < data.length; i++)
{
switch (data[i])
{
case (byte) " " :
case (byte) "\n" :
case (byte) "\r" :
case (byte) "\t" :
break;
default:
groomedData[bytesCopied++] = data[i];
}
}
byte packedData[] = new byte[bytesCopied];
System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
return packedData;
}
/**
* Discards any characters outside of the base64 alphabet, per
* the requirements on page 25 of RFC 2045 - "Any characters
* outside of the base64 alphabet are to be ignored in base64
* encoded data."
*
* @param data The base-64 encoded data to groom
* @return The data, less non-base64 characters (see RFC 2045).
*/
static byte[] discardNonBase64(byte[] data)
{
byte groomedData[] = new byte[data.length];
int bytesCopied = 0;
for (int i = 0; i < data.length; i++)
{
if (isBase64(data[i]))
{
groomedData[bytesCopied++] = data[i];
}
}
byte packedData[] = new byte[bytesCopied];
System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
return packedData;
}
// Implementation of the Encoder Interface
/**
* Encodes an Object using the base64 algorithm. This method
* is provided in order to satisfy the requirements of the
* Encoder interface, and will throw an EncoderException if the
* supplied object is not of type byte[].
*
* @param pObject Object to encode
* @return An object (of type byte[]) containing the
* base64 encoded data which corresponds to the byte[] supplied.
* @throws IllegalArgumentException if the parameter supplied is not
* of type byte[]
*/
public Object encode(Object pObject)
{
if (!(pObject instanceof byte[]))
{
throw new IllegalArgumentException(
"Parameter supplied to Base64 encode is not a byte[]");
}
return encode((byte[]) pObject);
}
/**
* Encodes a byte[] containing binary data, into a byte[] containing
* characters in the Base64 alphabet.
*
* @param pArray a byte array containing binary data
* @return A byte array containing only Base64 character data
*/
public byte[] encode(byte[] pArray)
{
return encodeBase64(pArray, false);
}
}
</source>
Provides Base64 encoding and decoding with URL and filename safe alphabet as defined by RFC 3548, section 4.
<source lang="java">
/*
* $Id: Base64.java 5325 2006-04-10 20:56:57 +0000 (Mon, 10 Apr 2006) jdonnerstag $ * $Revision: 5325 $ $Date: 2006-04-10 20:56:57 +0000 (Mon, 10 Apr 2006) $ * * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */
/**
* Provides Base64 encoding and decoding with URL and filename safe alphabet * as defined by RFC 3548, section 4. * <p/> * This Base64 encoder is modified to meet URL requirements. The changes are: * "+" => "*", * "/" => "-", * and no padding. * <p/> * This class is taken from the Apache commons-codec, and adjusted to fit the * Wicket framework"s needs, especially external dependencies have been removed. * </p> * <p/> * This class implements section 4. Base 64 Encoding with URL and Filename Safe Alphabet * from RFC 3548 The Base16, Base32, and Base64 Data Encodings by Simon Josefsson.</p> * * @author Apache Software Foundation * @author Juergen Donnerstag * * @since 1.2 */
public class Base64UrlSafe {
/** * The base length. */ static final int BASELENGTH = 255; /** * Lookup length. */ static final int LOOKUPLENGTH = 64; /** * Used to calculate the number of bits in a byte. */ static final int EIGHTBIT = 8; /** * Used when encoding something which has fewer than 24 bits. */ static final int SIXTEENBIT = 16; /** * Used to determine how many bits data contains. */ static final int TWENTYFOURBITGROUP = 24; /** * Used to get the number of Quadruples. */ static final int FOURBYTE = 4; /** * Used to test the sign of a byte. */ static final int SIGN = -128; /** * Contains the Base64 values0
through63
accessed by using character encodings as * indices. * <p/> * For example,base64Alphabet["+"]
returns62
. * </p> * <p/> * The value of undefined encodings is-1
. * </p> */ private static byte[] base64Alphabet = new byte[BASELENGTH]; /** * <p/> * Contains the Base64 encodingsA
throughZ
, followed bya
through *z
, followed by0
through9
, followed by+
, and */
. * </p> * <p/> * This array is accessed by using character values as indices. * </p> * <p/> * For example,lookUpBase64Alphabet[62]
returns"+"
. * </p> */ private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; // Populating the lookup and character arrays static { for (int i = 0; i < BASELENGTH; i++) { base64Alphabet[i] = (byte) -1; } for (int i = "Z"; i >= "A"; i--) { base64Alphabet[i] = (byte) (i - "A"); } for (int i = "z"; i >= "a"; i--) { base64Alphabet[i] = (byte) (i - "a" + 26); } for (int i = "9"; i >= "0"; i--) { base64Alphabet[i] = (byte) (i - "0" + 52); } base64Alphabet["*"] = 62; base64Alphabet["-"] = 63; for (int i = 0; i <= 25; i++) { lookUpBase64Alphabet[i] = (byte) ("A" + i); } for (int i = 26, j = 0; i <= 51; i++, j++) { lookUpBase64Alphabet[i] = (byte) ("a" + j); } for (int i = 52, j = 0; i <= 61; i++, j++) { lookUpBase64Alphabet[i] = (byte) ("0" + j); } lookUpBase64Alphabet[62] = (byte) "*"; lookUpBase64Alphabet[63] = (byte) "-"; } /** * Returns whether or not theoctect
is in the base 64 alphabet. * * @param octect The value to test * @returntrue
if the value is defined in the the base 64 alphabet,false
otherwise. */ private static boolean isBase64(byte octect) { if (octect < 0 || base64Alphabet[octect] == -1) { return false; } else { return true; } } /** * Tests a given byte array to see if it contains * only valid characters within the Base64 alphabet. * * @param arrayOctect byte array to test * @returntrue
if all bytes are valid characters in the Base64 * alphabet or if the byte array is empty; false, otherwise */ public static boolean isArrayByteBase64(byte[] arrayOctect) { arrayOctect = discardWhitespace(arrayOctect); int length = arrayOctect.length; if (length == 0) { // shouldn"t a 0 length array be valid base64 data? // return false; return true; } for (int i = 0; i < length; i++) { if (!isBase64(arrayOctect[i])) { return false; } } return true; } /** * Decodes an Object using the base64 algorithm. This method * is provided in order to satisfy the requirements of the * Decoder interface, and will throw a DecoderException if the * supplied object is not of type byte[]. * * @param pObject Object to decode * @return An object (of type byte[]) containing the * binary data which corresponds to the byte[] supplied. * @throws IllegalArgumentException if the parameter supplied is not * of type byte[] */ public Object decode(Object pObject) { if (!(pObject instanceof byte[])) { throw new IllegalArgumentException("Parameter supplied to Base64 decode is not a byte[]"); } return decode((byte[]) pObject); } /** * Decodes a byte[] containing containing * characters in the Base64 alphabet. * * @param pArray A byte array containing Base64 character data * @return a byte array containing binary data */ public byte[] decode(byte[] pArray) { return decodeBase64(pArray); } /** * Encodes binary data using the base64 algorithm. * * @param binaryData Array containing binary data to encode. * @return Base64-encoded data. */ public static byte[] encodeBase64(byte[] binaryData) { int lengthDataBits = binaryData.length * EIGHTBIT; int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; byte encodedData[] = null; int encodedDataLength = 0; if (fewerThan24bits != 0) { //data not divisible by 24 bit encodedDataLength = (numberTriplets + 1) * 4; } else { // 16 or 8 bit encodedDataLength = numberTriplets * 4; } if (fewerThan24bits == EIGHTBIT) { encodedDataLength -= 2; } else if (fewerThan24bits == SIXTEENBIT) { encodedDataLength -= 1; } encodedData = new byte[encodedDataLength]; byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; int encodedIndex = 0; int dataIndex = 0; int i = 0; //log.debug("number of triplets = " + numberTriplets); for (i = 0; i < numberTriplets; i++) { dataIndex = i * 3; b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; b3 = binaryData[dataIndex + 2]; //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3); l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; //log.debug( "val2 = " + val2 ); //log.debug( "k4 = " + (k<<4) ); //log.debug( "vak = " + (val2 | (k<<4)) ); encodedData[encodedIndex + 1] = lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[(l << 2) | val3]; encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f]; encodedIndex += 4; } // form integral number of 6-bit groups dataIndex = i * 3; if (fewerThan24bits == EIGHTBIT) { b1 = binaryData[dataIndex]; k = (byte) (b1 & 0x03); //log.debug("b1=" + b1); //log.debug("b1<<2 = " + (b1>>2) ); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4]; } else if (fewerThan24bits == SIXTEENBIT) { b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2]; } return encodedData; } /** * Decodes Base64 data into octects * * @param base64Data Byte array containing Base64 data * @return Array containing decoded data. */ public static byte[] decodeBase64(byte[] base64Data) { // RFC 2045 requires that we discard ALL non-Base64 characters base64Data = discardNonBase64(base64Data); // handle the edge case, so we don"t have to worry about it later if (base64Data.length == 0) { return new byte[0]; } int numberQuadruple = (base64Data.length + 3) / FOURBYTE; byte decodedData[] = new byte[base64Data.length - numberQuadruple]; byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0; // Throw away anything not in base64Data int encodedIndex = 0; int dataIndex = 0; for (int i = 0; i < numberQuadruple; i++) { dataIndex = i * 4; b1 = base64Alphabet[base64Data[dataIndex]]; b2 = base64Alphabet[base64Data[dataIndex + 1]]; if ((dataIndex + 3) < base64Data.length) { //No PAD e.g 3cQl b3 = base64Alphabet[base64Data[dataIndex + 2]]; b4 = base64Alphabet[base64Data[dataIndex + 3]]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4); } else if ((dataIndex + 2) < base64Data.length) { //One PAD e.g. 3cQ[Pad] b3 = base64Alphabet[base64Data[dataIndex + 2]]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); } else if ((dataIndex + 1) < base64Data.length) { //Two PAD e.g. 3c[Pad][Pad] decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); } encodedIndex += 3; } return decodedData; } /** * Discards any whitespace from a base-64 encoded block. * * @param data The base-64 encoded data to discard the whitespace * from. * @return The data, less whitespace (see RFC 2045). */ static byte[] discardWhitespace(byte[] data) { byte groomedData[] = new byte[data.length]; int bytesCopied = 0; for (int i = 0; i < data.length; i++) { switch (data[i]) { case (byte) " " : case (byte) "\n" : case (byte) "\r" : case (byte) "\t" : break; default: groomedData[bytesCopied++] = data[i]; } } byte packedData[] = new byte[bytesCopied]; System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); return packedData; } /** * Discards any characters outside of the base64 alphabet, per * the requirements on page 25 of RFC 2045 - "Any characters * outside of the base64 alphabet are to be ignored in base64 * encoded data." * * @param data The base-64 encoded data to groom * @return The data, less non-base64 characters (see RFC 2045). */ static byte[] discardNonBase64(byte[] data) { byte groomedData[] = new byte[data.length]; int bytesCopied = 0; for (int i = 0; i < data.length; i++) { if (isBase64(data[i])) { groomedData[bytesCopied++] = data[i]; } } byte packedData[] = new byte[bytesCopied]; System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); return packedData; } // Implementation of the Encoder Interface /** * Encodes an Object using the base64 algorithm. This method * is provided in order to satisfy the requirements of the * Encoder interface, and will throw an EncoderException if the * supplied object is not of type byte[]. * * @param pObject Object to encode * @return An object (of type byte[]) containing the * base64 encoded data which corresponds to the byte[] supplied. * @throws IllegalArgumentException if the parameter supplied is not * of type byte[] */ public Object encode(Object pObject) { if (!(pObject instanceof byte[])) { throw new IllegalArgumentException( "Parameter supplied to Base64 encode is not a byte[]"); } return encode((byte[]) pObject); } /** * Encodes a byte[] containing binary data, into a byte[] containing * characters in the Base64 alphabet. * * @param pArray a byte array containing binary data * @return A byte array containing only Base64 character data */ public byte[] encode(byte[] pArray) { return encodeBase64(pArray); }
}
</source>
Provides utility methods to Base64 encode data
<source lang="java">
/*
* * * Copyright 2005 Vincent Massol. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * */
import java.io.ByteArrayOutputStream; /**
* Provides utility methods to Base64 encode data. This class uses the Base64 encoding as specified * in RFC 2045, 6.8. Base64 Content-Transfer-Encoding. * * @version $Id: Base64.java 1705 2008-09-02 13:14:55Z adriana $ */
public final class Base64 {
// constants -------------------------------------------------------------- /** * The Base64 character set look-up table. This consists of the following ordered alphanumerics: * A-Z, a-z, 0-9, + and /. */ private static final char[] ENCODE = new char[64]; /** * The character to pad the output with if not a multiple of 24-bits. */ private static final char PAD_CHAR = "="; // static ----------------------------------------------------------------- static { // create Base64 character look-up table for (int i = 0; i < 26; i++) { ENCODE[i] = (char) ("A" + i); ENCODE[i + 26] = (char) ("a" + i); } for (int i = 0; i < 10; i++) { ENCODE[i + 52] = (char) ("0" + i); } ENCODE[62] = "+"; ENCODE[63] = "/"; } // constructors ----------------------------------------------------------- /** * Private to prevent unnecessary instantation. */ private Base64() { // Private to prevent unnecessary instantation } // public methods --------------------------------------------------------- /** * Base64 encodes the specified bytes. This method is provided for signature compatibility with * commons-codec. * * @param bytes the bytes to encode * @return the encoded bytes */ public static byte[] encodeBase64(byte[] bytes) { return encode(bytes); } /** * Base64 encodes the specified string using the platform"s default encoding. * * @param string the string to encode * @return the encoded string */ public static String encode(String string) { return new String(encode(string.getBytes())); } /** * Base64 encodes the specified bytes. * * @param bytes the bytes to encode * @return the encoded bytes */ public static byte[] encode(byte[] bytes) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int count = 0; int carry = 0; for (int i = 0; i < bytes.length; i++) { byte b = bytes[i]; switch (count++ % 3) { // first byte of 24-bits: write 6-bits and carry 2-bits case 0: out.write(ENCODE[b >> 2]); carry = b & 0x03; break; // second byte of 24-bits: write carry + 4-bits, carry 4-bits case 1: out.write(ENCODE[(carry << 4) + (b >> 4)]); carry = b & 0x0F; break; // third byte of 24-bits: write carry + 2-bits, write 6-bits case 2: out.write(ENCODE[(carry << 2) + (b >> 6)]); out.write(ENCODE[b & 0x3F]); break; default: throw new InternalError(); } } switch (count % 3) { // third byte of 24-bits: 24-bit aligned case 0: break; // first byte of 24-bits: write 4-bit carry and pad 16-bits case 1: out.write(ENCODE[carry << 4]); out.write(PAD_CHAR); out.write(PAD_CHAR); break; // second byte of 24-bits: write 2-bit carry and pad 8-bits case 2: out.write(ENCODE[carry << 2]); out.write(PAD_CHAR); break; default: throw new InternalError(); } return out.toByteArray(); }
}
</source>
QP Decoder Stream
<source lang="java">
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can obtain * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. * Sun designates this particular file as subject to the "Classpath" exception * as provided by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the License * Header, with the fields enclosed by brackets [] replaced by your own * identifying information: "Portions Copyrighted [year] * [name of copyright owner]" * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don"t indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */
/*
* @(#)QPDecoderStream.java 1.11 07/05/04 */
import java.io.*; /**
* This class implements a QP Decoder. It is implemented as * a FilterInputStream, so one can just wrap this class around * any input stream and read bytes from this filter. The decoding * is done as the bytes are read out. * * @author John Mani */
public class QPDecoderStream extends FilterInputStream {
protected byte[] ba = new byte[2]; protected int spaces = 0; /** * Create a Quoted Printable decoder that decodes the specified * input stream. * @param in the input stream */ public QPDecoderStream(InputStream in) { super(new PushbackInputStream(in, 2)); // pushback of size=2 } /** * Read the next decoded byte from this input stream. The byte * is returned as an*int
in the range0
* to255
. If no byte is available because the end of * the stream has been reached, the value-1
is returned. * This method blocks until input data is available, the end of the * stream is detected, or an exception is thrown. * * @return the next byte of data, or-1
if the end of the * stream is reached. * @exception IOException if an I/O error occurs. */ public int read() throws IOException { if (spaces > 0) { // We have cached space characters, return one spaces--; return " "; } int c = in.read(); if (c == " ") { // Got space, keep reading till we get a non-space char while ((c = in.read()) == " ") spaces++; if (c == "\r" || c == "\n" || c == -1) // If the non-space char is CR/LF/EOF, the spaces we got // so far is junk introduced during transport. Junk "em. spaces = 0; else { // The non-space char is NOT CR/LF, the spaces are valid. ((PushbackInputStream)in).unread(c); c = " "; } return c; // return either <SPACE> or <CR/LF> } else if (c == "=") { // QP Encoded atom. Decode the next two bytes int a = in.read(); if (a == "\n") { /* Hmm ... not really confirming QP encoding, but lets * allow this as a LF terminated encoded line .. and * consider this a soft linebreak and recurse to fetch * the next char. */ return read(); } else if (a == "\r") { // Expecting LF. This forms a soft linebreak to be ignored. int b = in.read(); if (b != "\n") /* Not really confirming QP encoding, but * lets allow this as well. */ ((PushbackInputStream)in).unread(b); return read(); } else if (a == -1) { // Not valid QP encoding, but we be nice and tolerant here ! return -1; } else { ba[0] = (byte)a; ba[1] = (byte)in.read(); try { return ASCIIUtility.parseInt(ba, 0, 2, 16); } catch (NumberFormatException nex) { /* System.err.println( "Illegal characters in QP encoded stream: " + ASCIIUtility.toString(ba, 0, 2) ); */ ((PushbackInputStream)in).unread(ba); return c; } } } return c; } /** * Reads up tolen
decoded bytes of data from this input stream * into an array of bytes. This method blocks until some input is * available.
*
* @param buf the buffer into which the data is read.
* @param off the start offset of the data.
* @param len the maximum number of bytes read.
* @return the total number of bytes read into the buffer, or
* -1
if there is no more data because the end of
* the stream has been reached.
* @exception IOException if an I/O error occurs.
*/
public int read(byte[] buf, int off, int len) throws IOException {
int i, c;
for (i = 0; i < len; i++) {
if ((c = read()) == -1) {
if (i == 0) // At end of stream, so we should
i = -1; // return -1 , NOT 0.
break;
}
buf[off+i] = (byte)c;
}
return i;
}
/**
* Tests if this input stream supports marks. Currently this class
* does not support marks
*/
public boolean markSupported() {
return false;
}
/**
* Returns the number of bytes that can be read from this input
* stream without blocking. The QP algorithm does not permit
* a priori knowledge of the number of bytes after decoding, so
* this method just invokes the available
method
* of the original input stream.
*/
public int available() throws IOException {
// This is bogus ! We don"t really know how much
// bytes are available *after* decoding
return in.available();
}
/**** begin TEST program
public static void main(String argv[]) throws Exception {
FileInputStream infile = new FileInputStream(argv[0]);
QPDecoderStream decoder = new QPDecoderStream(infile);
int c;
while ((c = decoder.read()) != -1)
System.out.print((char)c);
System.out.println();
}
*** end TEST program ****/
}
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don"t indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
/*
* @(#)ASCIIUtility.java 1.11 07/05/04
*/
class ASCIIUtility {
// Private constructor so that this class is not instantiated
private ASCIIUtility() { }
/**
* Convert the bytes within the specified range of the given byte
* array into a signed integer in the given radix . The range extends
* from start
till, but not including end
. <p>
*
* Based on java.lang.Integer.parseInt()
*/
public static int parseInt(byte[] b, int start, int end, int radix)
throws NumberFormatException {
if (b == null)
throw new NumberFormatException("null");
int result = 0;
boolean negative = false;
int i = start;
int limit;
int multmin;
int digit;
if (end > start) {
if (b[i] == "-") {
negative = true;
limit = Integer.MIN_VALUE;
i++;
} else {
limit = -Integer.MAX_VALUE;
}
multmin = limit / radix;
if (i < end) {
digit = Character.digit((char)b[i++], radix);
if (digit < 0) {
throw new NumberFormatException(
"illegal number: " + toString(b, start, end)
);
} else {
result = -digit;
}
}
while (i < end) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit((char)b[i++], radix);
if (digit < 0) {
throw new NumberFormatException("illegal number");
}
if (result < multmin) {
throw new NumberFormatException("illegal number");
}
result *= radix;
if (result < limit + digit) {
throw new NumberFormatException("illegal number");
}
result -= digit;
}
} else {
throw new NumberFormatException("illegal number");
}
if (negative) {
if (i > start + 1) {
return result;
} else { /* Only got "-" */
throw new NumberFormatException("illegal number");
}
} else {
return -result;
}
}
/**
* Convert the bytes within the specified range of the given byte
* array into a signed integer . The range extends from
* start
till, but not including end
. <p>
*/
public static int parseInt(byte[] b, int start, int end)
throws NumberFormatException {
return parseInt(b, start, end, 10);
}
/**
* Convert the bytes within the specified range of the given byte
* array into a signed long in the given radix . The range extends
* from start
till, but not including end
. <p>
*
* Based on java.lang.Long.parseLong()
*/
public static long parseLong(byte[] b, int start, int end, int radix)
throws NumberFormatException {
if (b == null)
throw new NumberFormatException("null");
long result = 0;
boolean negative = false;
int i = start;
long limit;
long multmin;
int digit;
if (end > start) {
if (b[i] == "-") {
negative = true;
limit = Long.MIN_VALUE;
i++;
} else {
limit = -Long.MAX_VALUE;
}
multmin = limit / radix;
if (i < end) {
digit = Character.digit((char)b[i++], radix);
if (digit < 0) {
throw new NumberFormatException(
"illegal number: " + toString(b, start, end)
);
} else {
result = -digit;
}
}
while (i < end) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit((char)b[i++], radix);
if (digit < 0) {
throw new NumberFormatException("illegal number");
}
if (result < multmin) {
throw new NumberFormatException("illegal number");
}
result *= radix;
if (result < limit + digit) {
throw new NumberFormatException("illegal number");
}
result -= digit;
}
} else {
throw new NumberFormatException("illegal number");
}
if (negative) {
if (i > start + 1) {
return result;
} else { /* Only got "-" */
throw new NumberFormatException("illegal number");
}
} else {
return -result;
}
}
/**
* Convert the bytes within the specified range of the given byte
* array into a signed long . The range extends from
* start
till, but not including end
. <p>
*/
public static long parseLong(byte[] b, int start, int end)
throws NumberFormatException {
return parseLong(b, start, end, 10);
}
/**
* Convert the bytes within the specified range of the given byte
* array into a String. The range extends from start
* till, but not including end
. <p>
*/
public static String toString(byte[] b, int start, int end) {
int size = end - start;
char[] theChars = new char[size];
for (int i = 0, j = start; i < size; )
theChars[i++] = (char)(b[j++]&0xff);
return new String(theChars);
}
public static String toString(ByteArrayInputStream is) {
int size = is.available();
char[] theChars = new char[size];
byte[] bytes = new byte[size];
is.read(bytes, 0, size);
for (int i = 0; i < size;)
theChars[i] = (char)(bytes[i++]&0xff);
return new String(theChars);
}
public static byte[] getBytes(String s) {
char [] chars= s.toCharArray();
int size = chars.length;
byte[] bytes = new byte[size];
for (int i = 0; i < size;)
bytes[i] = (byte) chars[i++];
return bytes;
}
public static byte[] getBytes(InputStream is) throws IOException {
int len;
int size = 1024;
byte [] buf;
if (is instanceof ByteArrayInputStream) {
size = is.available();
buf = new byte[size];
len = is.read(buf, 0, size);
}
else {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
buf = new byte[size];
while ((len = is.read(buf, 0, size)) != -1)
bos.write(buf, 0, len);
buf = bos.toByteArray();
}
return buf;
}
}
</source>
QP Encoder Stream
<source lang="java">
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can obtain * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. * Sun designates this particular file as subject to the "Classpath" exception * as provided by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the License * Header, with the fields enclosed by brackets [] replaced by your own * identifying information: "Portions Copyrighted [year] * [name of copyright owner]" * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don"t indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */
/*
* @(#)QPEncoderStream.java 1.8 07/05/04 */
import java.io.*; /**
* This class implements a Quoted Printable Encoder. It is implemented as * a FilterOutputStream, so one can just wrap this class around * any output stream and write bytes into this filter. The Encoding * is done as the bytes are written out. * * @author John Mani */
public class QPEncoderStream extends FilterOutputStream {
private int count = 0; // number of bytes that have been output private int bytesPerLine; // number of bytes per line private boolean gotSpace = false; private boolean gotCR = false; /** * Create a QP encoder that encodes the specified input stream * @param out the output stream * @param bytesPerLine the number of bytes per line. The encoder * inserts a CRLF sequence after this many number * of bytes. */ public QPEncoderStream(OutputStream out, int bytesPerLine) { super(out); // Subtract 1 to account for the "=" in the soft-return // at the end of a line this.bytesPerLine = bytesPerLine - 1; } /** * Create a QP encoder that encodes the specified input stream. * Inserts the CRLF sequence after outputting 76 bytes. * @param out the output stream */ public QPEncoderStream(OutputStream out) { this(out, 76); } /** * Encodeslen
bytes from the specified *byte
array starting at offsetoff
to * this output stream. * * @param b the data. * @param off the start offset in the data. * @param len the number of bytes to write. * @exception IOException if an I/O error occurs. */ public void write(byte[] b, int off, int len) throws IOException { for (int i = 0; i < len; i++) write(b[off + i]); } /** * Encodesb.length
bytes to this output stream. * @param b the data to be written. * @exception IOException if an I/O error occurs. */ public void write(byte[] b) throws IOException { write(b, 0, b.length); } /** * Encodes the specifiedbyte
to this output stream. * @param c thebyte
. * @exception IOException if an I/O error occurs. */ public void write(int c) throws IOException { c = c & 0xff; // Turn off the MSB. if (gotSpace) { // previous character was <SPACE> if (c == "\r" || c == "\n") // if CR/LF, we need to encode the <SPACE> char output(" ", true); else // no encoding required, just output the char output(" ", false); gotSpace = false; } if (c == "\r") { gotCR = true; outputCRLF(); } else { if (c == "\n") { if (gotCR) // This is a CRLF sequence, we already output the // corresponding CRLF when we got the CR, so ignore this ; else outputCRLF(); } else if (c == " ") { gotSpace = true; } else if (c < 040 || c >= 0177 || c == "=") // Encoding required. output(c, true); else // No encoding required output(c, false); // whatever it was, it wasn"t a CR gotCR = false; } } /** * Flushes this output stream and forces any buffered output bytes * to be encoded out to the stream. * @exception IOException if an I/O error occurs. */ public void flush() throws IOException { out.flush(); } /** * Forces any buffered output bytes to be encoded out to the stream * and closes this output stream */ public void close() throws IOException { out.close(); } private void outputCRLF() throws IOException { out.write("\r"); out.write("\n"); count = 0; } // The encoding table private final static char hex[] = { "0","1", "2", "3", "4", "5", "6", "7", "8","9", "A", "B", "C", "D", "E", "F" }; protected void output(int c, boolean encode) throws IOException { if (encode) { if ((count += 3) > bytesPerLine) { out.write("="); out.write("\r"); out.write("\n"); count = 3; // set the next line"s length } out.write("="); out.write(hex[c >> 4]); out.write(hex[c & 0xf]); } else { if (++count > bytesPerLine) { out.write("="); out.write("\r"); out.write("\n"); count = 1; // set the next line"s length } out.write(c); } } /**** begin TEST program *** public static void main(String argv[]) throws Exception { FileInputStream infile = new FileInputStream(argv[0]); QPEncoderStream encoder = new QPEncoderStream(System.out); int c; while ((c = infile.read()) != -1) encoder.write(c); encoder.close(); } *** end TEST program ***/
} /*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can obtain * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. * Sun designates this particular file as subject to the "Classpath" exception * as provided by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the License * Header, with the fields enclosed by brackets [] replaced by your own * identifying information: "Portions Copyrighted [year] * [name of copyright owner]" * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don"t indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */
/*
* @(#)ASCIIUtility.java 1.11 07/05/04 */ class ASCIIUtility { // Private constructor so that this class is not instantiated private ASCIIUtility() { } /** * Convert the bytes within the specified range of the given byte * array into a signed integer in the given radix . The range extends * fromstart
till, but not includingend
. <p> * * Based on java.lang.Integer.parseInt() */ public static int parseInt(byte[] b, int start, int end, int radix) throws NumberFormatException { if (b == null) throw new NumberFormatException("null"); int result = 0; boolean negative = false; int i = start; int limit; int multmin; int digit; if (end > start) { if (b[i] == "-") { negative = true; limit = Integer.MIN_VALUE; i++; } else { limit = -Integer.MAX_VALUE; } multmin = limit / radix; if (i < end) { digit = Character.digit((char)b[i++], radix); if (digit < 0) { throw new NumberFormatException( "illegal number: " + toString(b, start, end) ); } else { result = -digit; } } while (i < end) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit((char)b[i++], radix); if (digit < 0) { throw new NumberFormatException("illegal number"); } if (result < multmin) { throw new NumberFormatException("illegal number"); } result *= radix; if (result < limit + digit) { throw new NumberFormatException("illegal number"); } result -= digit; } } else { throw new NumberFormatException("illegal number"); } if (negative) { if (i > start + 1) { return result; } else { /* Only got "-" */ throw new NumberFormatException("illegal number"); } } else { return -result; } } /** * Convert the bytes within the specified range of the given byte * array into a signed integer . The range extends from *start
till, but not includingend
. <p> */ public static int parseInt(byte[] b, int start, int end) throws NumberFormatException { return parseInt(b, start, end, 10); } /** * Convert the bytes within the specified range of the given byte * array into a signed long in the given radix . The range extends * fromstart
till, but not includingend
. <p> * * Based on java.lang.Long.parseLong() */ public static long parseLong(byte[] b, int start, int end, int radix) throws NumberFormatException { if (b == null) throw new NumberFormatException("null"); long result = 0; boolean negative = false; int i = start; long limit; long multmin; int digit; if (end > start) { if (b[i] == "-") { negative = true; limit = Long.MIN_VALUE; i++; } else { limit = -Long.MAX_VALUE; } multmin = limit / radix; if (i < end) { digit = Character.digit((char)b[i++], radix); if (digit < 0) { throw new NumberFormatException( "illegal number: " + toString(b, start, end) ); } else { result = -digit; } } while (i < end) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit((char)b[i++], radix); if (digit < 0) { throw new NumberFormatException("illegal number"); } if (result < multmin) { throw new NumberFormatException("illegal number"); } result *= radix; if (result < limit + digit) { throw new NumberFormatException("illegal number"); } result -= digit; } } else { throw new NumberFormatException("illegal number"); } if (negative) { if (i > start + 1) { return result; } else { /* Only got "-" */ throw new NumberFormatException("illegal number"); } } else { return -result; } } /** * Convert the bytes within the specified range of the given byte * array into a signed long . The range extends from *start
till, but not includingend
. <p> */ public static long parseLong(byte[] b, int start, int end) throws NumberFormatException { return parseLong(b, start, end, 10); } /** * Convert the bytes within the specified range of the given byte * array into a String. The range extends fromstart
* till, but not includingend
. <p> */ public static String toString(byte[] b, int start, int end) { int size = end - start; char[] theChars = new char[size]; for (int i = 0, j = start; i < size; ) theChars[i++] = (char)(b[j++]&0xff); return new String(theChars); } public static String toString(ByteArrayInputStream is) { int size = is.available(); char[] theChars = new char[size]; byte[] bytes = new byte[size]; is.read(bytes, 0, size); for (int i = 0; i < size;) theChars[i] = (char)(bytes[i++]&0xff); return new String(theChars); }
public static byte[] getBytes(String s) { char [] chars= s.toCharArray(); int size = chars.length; byte[] bytes = new byte[size]; for (int i = 0; i < size;) bytes[i] = (byte) chars[i++]; return bytes; } public static byte[] getBytes(InputStream is) throws IOException { int len; int size = 1024; byte [] buf;
if (is instanceof ByteArrayInputStream) { size = is.available(); buf = new byte[size]; len = is.read(buf, 0, size); } else { ByteArrayOutputStream bos = new ByteArrayOutputStream(); buf = new byte[size]; while ((len = is.read(buf, 0, size)) != -1) bos.write(buf, 0, len); buf = bos.toByteArray(); } return buf; }
}
</source>
Represents a collection of 64 boolean (on/off) flags.
<source lang="java">
/*
* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
import java.io.Serializable; /**
* Represents a collection of 64 boolean (on/off) flags. Individual flags * are represented by powers of 2. For example,*
* Flag 1 = 1
* Flag 2 = 2
* Flag 3 = 4
* Flag 4 = 8
* or using shift operator to make numbering easier:
* Flag 1 = 1 << 0
* Flag 2 = 1 << 1
* Flag 3 = 1 << 2
* Flag 4 = 1 << 3
* * <p> * There cannot be a flag with a value of 3 because that represents Flag 1 * and Flag 2 both being on/true.
* * @version $Revision: 478334 $ $Date: 2006-11-22 21:31:54 +0000 (Wed, 22 Nov 2006) $ */
public class Flags implements Serializable {
/**
* Represents the current flag state.
*/
private long flags = 0;
/**
* Create a new Flags object.
*/
public Flags() {
super();
}
/**
* Initialize a new Flags object with the given flags.
*
* @param flags collection of boolean flags to represent.
*/
public Flags(long flags) {
super();
this.flags = flags;
}
/**
* Returns the current flags.
*
* @return collection of boolean flags represented.
*/
public long getFlags() {
return this.flags;
}
/**
* Tests whether the given flag is on. If the flag is not a power of 2
* (ie. 3) this tests whether the combination of flags is on.
*
* @param flag Flag value to check.
*
* @return whether the specified flag value is on.
*/
public boolean isOn(long flag) {
return (this.flags & flag) > 0;
}
/**
* Tests whether the given flag is off. If the flag is not a power of 2
* (ie. 3) this tests whether the combination of flags is off.
*
* @param flag Flag value to check.
*
* @return whether the specified flag value is off.
*/
public boolean isOff(long flag) {
return (this.flags & flag) == 0;
}
/**
* Turns on the given flag. If the flag is not a power of 2 (ie. 3) this
* turns on multiple flags.
*
* @param flag Flag value to turn on.
*/
public void turnOn(long flag) {
this.flags |= flag;
}
/**
* Turns off the given flag. If the flag is not a power of 2 (ie. 3) this
* turns off multiple flags.
*
* @param flag Flag value to turn off.
*/
public void turnOff(long flag) {
this.flags &= ~flag;
}
/**
* Turn off all flags.
*/
public void turnOffAll() {
this.flags = 0;
}
/**
* Turn off all flags. This is a synonym for turnOffAll()
.
* @since Validator 1.1.1
*/
public void clear() {
this.flags = 0;
}
/**
* Turn on all 64 flags.
*/
public void turnOnAll() {
this.flags = Long.MAX_VALUE;
}
/**
* Clone this Flags object.
*
* @return a copy of this object.
* @see java.lang.Object#clone()
*/
public Object clone() {
try {
return super.clone();
} catch(CloneNotSupportedException e) {
throw new RuntimeException("Couldn"t clone Flags object.");
}
}
/**
* Tests if two Flags objects are in the same state.
* @param obj object being tested
* @see java.lang.Object#equals(java.lang.Object)
*
* @return whether the objects are equal.
*/
public boolean equals(Object obj) {
if (!(obj instanceof Flags)) {
return false;
}
if (obj == this) {
return true;
}
Flags f = (Flags) obj;
return this.flags == f.flags;
}
/**
* The hash code is based on the current state of the flags.
* @see java.lang.Object#hashCode()
*
* @return the hash code for this object.
*/
public int hashCode() {
return (int) this.flags;
}
/**
* Returns a 64 length String with the first flag on the right and the
* 64th flag on the left. A 1 indicates the flag is on, a 0 means it"s
* off.
*
* @return string representation of this object.
*/
public String toString() {
StringBuffer bin = new StringBuffer(Long.toBinaryString(this.flags));
for (int i = 64 - bin.length(); i > 0; i--) {
bin.insert(0, "0");
}
return bin.toString();
}
}
</source>
to Base64
<source lang="java">
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one * * or more contributor license agreements. See the NOTICE file * * distributed with this work for additional information * * regarding copyright ownership. The ASF licenses this file * * to you under the Apache License, Version 2.0 (the * * "License"); you may not use this file except in compliance * * with the License. You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, * * software distributed under the License is distributed on an * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * * KIND, either express or implied. See the License for the * * specific language governing permissions and limitations * * under the License. * ****************************************************************/
public class EncodeUtils {
public static final int MASK = 0x3F; public static final int FIRST_MASK = MASK << 18; public static final int SECOND_MASK = MASK << 12; public static final int THIRD_MASK = MASK << 6; public static final int FORTH_MASK = MASK; public static final byte[] ENCODING = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P" ,"Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"}; public static final void main(String[] args) throws Exception { byte[] bytes = {(byte) 0, (byte) 128, (byte) 0}; System.out.println(new String(toBase64(bytes))); System.out.println(new String(toBase64("Hello, World".getBytes()))); System.out.println(new String(toBase64("Monday".getBytes()))); System.out.println(new String(toBase64("M\u00F6nchengladbach\r\n".getBytes("ISO-8859-1")))); } public static byte[] toBase64(byte[] in) { int inputLength = in.length; int outputLength = (int) Math.floor((4*inputLength) / 3f) + 3; outputLength = outputLength + 2 * (int) Math.floor(outputLength / 76f); byte[] results = new byte[outputLength]; int inputIndex = 0; int outputIndex = 0; while (inputLength - inputIndex > 2) { int one = (toInt(in[inputIndex++]) << 16); int two = (toInt(in[inputIndex++]) << 8); int three = toInt(in[inputIndex++]); int quantum = one | two | three; int index = (quantum & FIRST_MASK) >> 18; outputIndex = setResult(results, outputIndex, ENCODING[index]); index = (quantum & SECOND_MASK) >> 12; outputIndex = setResult(results, outputIndex, ENCODING[index]); index = (quantum & THIRD_MASK) >> 6; outputIndex = setResult(results, outputIndex, ENCODING[index]); index = (quantum & FORTH_MASK); outputIndex = setResult(results, outputIndex, ENCODING[index]); } switch (inputLength - inputIndex) { case 1: int quantum = in[inputIndex++] << 16; int index = (quantum & FIRST_MASK) >> 18; outputIndex = setResult(results, outputIndex, ENCODING[index]); index = (quantum & SECOND_MASK) >> 12; outputIndex = setResult(results, outputIndex, ENCODING[index]); outputIndex = setResult(results, outputIndex, (byte) "="); outputIndex = setResult(results, outputIndex, (byte) "="); break; case 2: quantum = (in[inputIndex++] << 16) + (in[inputIndex++] << 8); index = (quantum & FIRST_MASK) >> 18; outputIndex = setResult(results, outputIndex, ENCODING[index]); index = (quantum & SECOND_MASK) >> 12; outputIndex = setResult(results, outputIndex, ENCODING[index]); index = (quantum & THIRD_MASK) >> 6; outputIndex = setResult(results, outputIndex, ENCODING[index]); outputIndex = setResult(results, outputIndex, (byte) "="); break; } return results; } private static int toInt(byte b) { return 255 & b; }
private static int setResult(byte[] results, int outputIndex, byte value) { results[outputIndex++] = value; outputIndex = checkLineLength(results, outputIndex); return outputIndex; }
private static int checkLineLength(byte[] results, int outputIndex) { if (outputIndex == 76 || outputIndex > 76 && (outputIndex - 2*Math.floor(outputIndex/76f - 1)) % 76 == 0) { results[outputIndex++] = "\r"; results[outputIndex++] = "\n"; } return outputIndex; }
}
</source>