package org.cdlib.xtf.util;
/**
* Copyright (c) 2004, Regents of the University of California
* 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 University of California 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.
*/
/**
* Utility class that decodes Base64 data.
*/
public class Base64
{
/**
* Given a character in the Base64 set, figure out the decimal
* equivalent.
*
* @param c The character to decode
* @return The decimal equivalent (also maps invalid chars to zero)
*/
private static int decodeChar(char c) {
if (c >= 'A' && c <= 'Z')
return c - 'A';
else if (c >= 'a' && c <= 'z')
return c - 'a' + 26;
else if (c >= '0' && c <= '9')
return c - '0' + 52;
else if (c == '+')
return 62;
else if (c == '/')
return 63;
else
return 0;
} // decodeChar()
/**
* Combines bits from two different bytes into a single character.
*/
private static String decodeBits(int bits1, int pos1, int count1, int bits2,
int pos2, int count2)
{
int num1 = (bits1 >> pos1) & (0xFF >> (8 - count1));
int num2 = (bits2 >> pos2) & (0xFF >> (8 - count2));
char c = (char)((num1 << count2) + num2);
return Character.toString(c);
} // decodeBits()
/**
* Decodes a 4-character Base64 'quantum' into a 3-character string.
*/
private static String decodeQuantum(String quantum)
{
int[] bits = new int[4];
for (int i = 0; i < 4; i++)
bits[i] = decodeChar(quantum.charAt(i));
String ch1 = decodeBits(bits[0], 0, 6, bits[1], 4, 2);
String ch2 = decodeBits(bits[1], 0, 4, bits[2], 2, 4);
String ch3 = decodeBits(bits[2], 0, 2, bits[3], 0, 6);
if (quantum.endsWith("=="))
return ch1;
else if (quantum.endsWith("="))
return ch1 + ch2;
else
return ch1 + ch2 + ch3;
} // decodeQuantum()
/**
* Decodes a full Base64 string to the corresponding normal string.
*
* @param base64 The base64 string to decode (e.g. "HX1+9/6fE97=")
* @return Decoded version of the string.
*/
public static String decodeString(String base64)
{
String out = "";
while (base64.length() >= 4) {
String quantum = base64.substring(0, 4);
base64 = base64.substring(4);
String str = decodeQuantum(quantum);
out += str;
}
return out;
} // decodeString()
} // class Base64