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

org.overture.util.Base64 Maven / Gradle / Ivy

/*******************************************************************************
 *
 *	Copyright (C) 2008 Fujitsu Services Ltd.
 *
 *	Author: Nick Battle
 *
 *	This file is part of VDMJ.
 *
 *	VDMJ is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	VDMJ 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 General Public License
 *	along with VDMJ.  If not, see .
 *
 ******************************************************************************/

package org.overture.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A class to manage base64 encoding and decoding.
 */

public class Base64
{
	/**
	 * Return the 6-bit value corresponding to a base64 encoded char. If the character is the base64 padding character,
	 * '=', -1 is returned.
	 * 
	 * @param c
	 *            The character to decode
	 * @return The decoded 6-bit value, or -1 for padding.
	 */

	private static int b64decode(char c)
	{
		int i = c;

		if (i >= 'A' && i <= 'Z')
		{
			return i - 'A';
		}

		if (i >= 'a' && i <= 'z')
		{
			return i - 'a' + 26;
		}

		if (i >= '0' && i <= '9')
		{
			return i - '0' + 52;
		}

		if (i == '+')
		{
			return 62;
		}

		if (i == '/')
		{
			return 63;
		}

		return -1; // padding '='
	}

	/**
	 * Encode a 6-bit quantity as a base64 character.
	 * 
	 * @param b
	 *            The 6-bit quantity. return The character.
	 */

	private static char b64encode(int b)
	{
		if (b >= 0 && b <= 25)
		{
			return (char) ('A' + b);
		}

		if (b >= 26 && b <= 51)
		{
			return (char) ('a' + b - 26);
		}

		if (b >= 52 && b <= 61)
		{
			return (char) ('0' + b - 52);
		}

		if (b == 62)
		{
			return '+';
		}

		if (b == 63)
		{
			return '/';
		}

		return '?';
	}

	/**
	 * Base64 decode a string into a byte array.
	 * 
	 * @param text
	 *            The encoded base64 text.
	 * @return a byte array of the decoded data.
	 * @throws Exception
	 */

	public static byte[] decode(String text) throws Exception
	{
		if (text.length() % 4 != 0)
		{
			throw new Exception("Base64 not a multiple of 4 bytes");
		}

		byte[] result = new byte[text.length() / 4 * 3];
		int p = 0;

		for (int i = 0; i < text.length();)
		{
			if (text.charAt(i) == '\n')
			{
				continue;
			}

			int b1 = b64decode(text.charAt(i++));
			int b2 = b64decode(text.charAt(i++));
			int b3 = b64decode(text.charAt(i++));
			int b4 = b64decode(text.charAt(i++));

			if (b4 >= 0)
			{
				int three = b4 | b3 << 6 | b2 << 12 | b1 << 18;
				result[p++] = (byte) ((three & 0xff0000) >> 16);
				result[p++] = (byte) ((three & 0xff00) >> 8);
				result[p++] = (byte) (three & 0xff);
			} else if (b3 >= 0)
			{
				int two = b3 << 6 | b2 << 12 | b1 << 18;
				result[p++] = (byte) ((two & 0xff0000) >> 16);
				result[p++] = (byte) ((two & 0xff00) >> 8);
			} else
			{
				int one = b2 << 12 | b1 << 18;
				result[p++] = (byte) ((one & 0xff0000) >> 16);
			}
		}

		byte[] output = new byte[p];
		System.arraycopy(result, 0, output, 0, p);

		return output;
	}

	/**
	 * Base64 encode a byte array.
	 * 
	 * @param data
	 *            the data to encode.
	 * @return a StringBuffer containing the encoded lines.
	 */

	public static StringBuffer encode(byte[] data)
	{
		int rem = data.length % 3;
		int num = data.length / 3;
		StringBuffer result = new StringBuffer();
		int p = 0;
		// int c=0;

		for (int i = 0; i < num; i++)
		{
			int b1 = (data[p] & 0xfc) >> 2;
			int b2 = (data[p] & 0x03) << 4 | (data[p + 1] & 0xf0) >> 4;
			int b3 = (data[p + 1] & 0x0f) << 2 | (data[p + 2] & 0xc0) >> 6;
			int b4 = data[p + 2] & 0x3f;

			result.append(b64encode(b1));
			result.append(b64encode(b2));
			result.append(b64encode(b3));
			result.append(b64encode(b4));

			p += 3;
			// c += 4;
		}

		switch (rem)
		{
			case 0:
				break;

			case 1:
			{
				int b1 = (data[p] & 0xfc) >> 2;
				int b2 = (data[p] & 0x03) << 4;

				result.append(b64encode(b1));
				result.append(b64encode(b2));
				result.append('=');
				result.append('=');
				break;
			}

			case 2:
			{
				int b1 = (data[p] & 0xfc) >> 2;
				int b2 = (data[p] & 0x03) << 4 | (data[p + 1] & 0xf0) >> 4;
				int b3 = (data[p + 1] & 0x0f) << 2;

				result.append(b64encode(b1));
				result.append(b64encode(b2));
				result.append(b64encode(b3));
				result.append('=');
				break;
			}
		}

		return result;
	}

	public static void main(String[] args) throws Exception
	{
		BufferedReader bir = new BufferedReader(new InputStreamReader(System.in));
		String charset = Charset.defaultCharset().name();
		System.out.println("Default charset = " + charset);
		Pattern pattern = Pattern.compile("(\\w+)\\s*?(.*)?$");

		while (true)
		{
			System.out.print("> ");
			String line = bir.readLine();
			Matcher m = pattern.matcher(line);

			if (!m.matches())
			{
				System.out.println("[encode|decode] ");
				System.out.println("charset ");
				System.out.println("quit");
				continue;
			}

			String cmd = m.group(1);
			String data = m.groupCount() == 2 ? m.group(2) : "";

			if (cmd.equals("decode"))
			{
				try
				{
					System.out.println(new String(decode(data)));
				} catch (Exception e)
				{
					System.out.println("Oops! " + e.getMessage());
				}
			} else if (cmd.equals("encode"))
			{
				System.out.println(encode(data.getBytes(charset)));
			} else if (cmd.equals("charset"))
			{
				charset = data;
				System.out.println("Charset now " + charset);
			} else if (cmd.equals("quit"))
			{
				break;
			}
		}

		bir.close();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy