All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cxf.common.util.Base64Utility Maven / Gradle / Ivy

There is a newer version: 3.0.0-milestone2
Show newest version
/**
 * 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.
 */

package org.apache.cxf.common.util;

/**
 * Base64Utility - this static class provides useful base64 
 *                 encoding utilities.
 * 

* @author Darach Ennis * @author Craig Ryan */ // Java imports import java.io.IOException; import java.io.OutputStream; import java.io.Writer; import java.util.logging.Logger; import org.apache.cxf.common.i18n.Message; import org.apache.cxf.common.logging.LogUtils; /** * This class converts to/from base64. The alternative conversions include: * * encode: * byte[] into String * byte[] into char[] * byte[] into OutStream * byte[] into Writer * decode: * char[] into byte[] * String into byte[] * char[] into OutStream * String into OutStream * */ public final class Base64Utility { private static final Logger LOG = LogUtils.getL7dLogger(Base64Utility.class); // base 64 character set // private static final char[] BCS = { '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', '+', '/' }; // base 64 wadding private static final char PAD = '='; // size of base 64 decode table private static final int BDTSIZE = 128; // base 64 decode table private static final byte[] BDT = new byte[128]; private static final int PAD_SIZE0 = 1; private static final int PAD_SIZE4 = 2; private static final int PAD_SIZE8 = 3; // class static intializer for building decode table static { for (int i = 0; i < BDTSIZE; i++) { BDT[i] = Byte.MAX_VALUE; } for (int i = 0; i < BCS.length; i++) { BDT[BCS[i]] = (byte)i; } } private Base64Utility() { //utility class, never constructed } /** * The decode_chunk routine decodes a chunk of data * into its native encoding. * * base64 encodes each 3 octets of data into 4 characters from a * limited 64 character set. The 3 octets are joined to form * 24 bits which are then split into 4 x 6bit values. Each 6 bit * value is then used as an index into the 64 character table of * base64 chars. If the total data length is not a 3 octet multiple * the '=' char is used as padding for the final 4 char group, * either 1 octet + '==' or 2 octets + '='. * * @param id The input data to be processed * @param o The offset from which to begin processing * @param l The length (bound) at which processing is to end * @return The decoded data * @exception Base64Exception Thrown is processing fails due to * formatting exceptions in the encoded data */ public static byte[] decodeChunk(char[] id, int o, int l) throws Base64Exception { // Keep it simple - must be >= 4. Unpadded // base64 data contain < 3 octets is invalid. // if ((l - o) < 4) { return null; } char[] ib = new char[4]; int ibcount = 0; // cryan. Calc the num of octets. Each 4 chars of base64 chars // (representing 24 bits) encodes 3 octets. // int octetCount = 3 * (l / 4); // Final 4 chars may contain 3 octets or padded to contain // 1 or 2 octets. // if (id[l - 1] == PAD) { // TT== means last 4 chars encode 8 bits (ie subtract 2) // TTT= means last 4 chars encode 16 bits (ie subtract 1) octetCount -= (id[l - 2] == PAD) ? 2 : 1; } byte[] ob = new byte[octetCount]; int obcount = 0; for (int i = o; i < o + l && i < id.length; i++) { if (id[i] == PAD || id[i] < BDT.length && BDT[id[i]] != Byte.MAX_VALUE) { ib[ibcount++] = id[i]; // Decode each 4 char sequence. // if (ibcount == ib.length) { ibcount = 0; obcount += processEncodeme(ib, ob, obcount); } } } if (obcount != ob.length) { byte []tmp = new byte[obcount]; System.arraycopy(ob, 0, tmp, 0, obcount); ob = tmp; } return ob; } public static byte[] decode(String id) throws Base64Exception { try { char[] cd = id.toCharArray(); return decodeChunk(cd, 0, cd.length); } catch (Exception e) { LOG.warning("Invalid base64 encoded string : " + id); throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG), e); } } public static void decode(char[] id, int o, int l, OutputStream ostream) throws Base64Exception { try { ostream.write(decodeChunk(id, o, l)); } catch (Exception e) { LOG.warning("Invalid base64 encoded string : " + new String(id)); throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG), e); } } public static void decode(String id, OutputStream ostream) throws Base64Exception { try { char[] cd = id.toCharArray(); ostream.write(decodeChunk(cd, 0, cd.length)); } catch (IOException ioe) { throw new Base64Exception(new Message("BASE64_DECODE_IOEXCEPTION", LOG), ioe); } catch (Exception e) { LOG.warning("Invalid base64 encoded string : " + id); throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG), e); } } // Returns base64 representation of specified byte array. // public static String encode(byte[] id) { char[] cd = encodeChunk(id, 0, id.length); return new String(cd, 0, cd.length); } // Returns base64 representation of specified byte array. // public static char[] encodeChunk(byte[] id, int o, int l) { if (l <= 0) { return null; } char[] out; // If not a multiple of 3 octets then a final padded 4 char // slot is needed. // if ((l - o) % 3 == 0) { out = new char[l / 3 * 4]; } else { out = new char[l / 3 * 4 + 4]; } int rindex = o; int windex = 0; int rest = l - o; while (rest >= 3) { int i = ((id[rindex] & 0xff) << 16) + ((id[rindex + 1] & 0xff) << 8) + (id[rindex + 2] & 0xff); out[windex++] = BCS[i >> 18]; out[windex++] = BCS[(i >> 12) & 0x3f]; out[windex++] = BCS[(i >> 6) & 0x3f]; out[windex++] = BCS[i & 0x3f]; rindex += 3; rest -= 3; } if (rest == 1) { int i = id[rindex] & 0xff; out[windex++] = BCS[i >> 2]; out[windex++] = BCS[(i << 4) & 0x3f]; out[windex++] = PAD; out[windex++] = PAD; } else if (rest == 2) { int i = ((id[rindex] & 0xff) << 8) + (id[rindex + 1] & 0xff); out[windex++] = BCS[i >> 10]; out[windex++] = BCS[(i >> 4) & 0x3f]; out[windex++] = BCS[(i << 2) & 0x3f]; out[windex++] = PAD; } return out; } // // Outputs base64 representation of the specified byte array // to a byte stream. // public static void encodeChunk(byte[] id, int o, int l, OutputStream ostream) throws Base64Exception { try { ostream.write(new String(encodeChunk(id, o, l)).getBytes()); } catch (IOException e) { throw new Base64Exception(new Message("BASE64_ENCODE_IOEXCEPTION", LOG), e); } } // Outputs base64 representation of the specified byte // array to a character stream. // public static void encode(byte[] id, int o, int l, Writer writer) throws Base64Exception { try { writer.write(encodeChunk(id, o, l)); } catch (IOException e) { throw new Base64Exception(new Message("BASE64_ENCODE_WRITER_IOEXCEPTION", LOG), e); } } //---- Private static methods -------------------------------------- /** * The process routine processes an atomic base64 * unit of encoding (encodeme) into its native encoding. This class is * used by decode routines to do the grunt work of decoding * base64 encoded information * * @param ib Input character buffer of encoded bytes * @param ob Output byte buffer of decoded bytes * @param p Pointer to the encodeme of interest * @return The decoded encodeme * @exception Base64Exception Thrown is processing fails due to * formatting exceptions in the encoded data */ private static int processEncodeme(char[] ib, byte[] ob, int p) throws Base64Exception { int spad = PAD_SIZE8; if (ib[3] == PAD) { spad = PAD_SIZE4; } if (ib[2] == PAD) { spad = PAD_SIZE0; } int b0 = BDT[ib[0]]; int b1 = BDT[ib[1]]; int b2 = BDT[ib[2]]; int b3 = BDT[ib[3]]; switch (spad) { case PAD_SIZE0: ob[p] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); return PAD_SIZE0; case PAD_SIZE4: ob[p++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); ob[p] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf); return PAD_SIZE4; case PAD_SIZE8: ob[p++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); ob[p++] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf); ob[p] = (byte)(b2 << 6 & 0xc0 | b3 & 0x3f); return PAD_SIZE8; default: // We should never get here throw new IllegalStateException(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy