001: // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
002: // Released under the terms of the GNU General Public License version 2 or later.
003: package fitnesse.components;
004:
005: public class Base64 {
006: private static final byte[] base64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
007: .getBytes();
008:
009: private static final byte pad = '=';
010:
011: public static String decode(String value) throws Exception {
012: return new String(decode(value.getBytes("UTF-8")));
013: }
014:
015: public static byte[] decode(byte[] bytes) {
016: int lengthOfDecoding = getLengthOfDecoding(bytes);
017: byte[] decoding = new byte[lengthOfDecoding];
018: int decodingIndex = 0;
019:
020: for (int index = 0; index < bytes.length; index += 4) {
021: byte v1 = getValueFor(bytes[index]);
022: byte v2 = getValueFor(bytes[index + 1]);
023: byte v3 = getValueFor(bytes[index + 2]);
024: byte v4 = getValueFor(bytes[index + 3]);
025:
026: byte c1 = (byte) ((v1 << 2) + (v2 >> 4));
027: byte c2 = (byte) ((v2 << 4) + (v3 >> 2));
028: byte c3 = (byte) ((v3 << 6) + v4);
029:
030: decoding[decodingIndex++] = c1;
031: if (c2 != 0)
032: decoding[decodingIndex++] = c2;
033: if (c3 != 0)
034: decoding[decodingIndex++] = c3;
035: }
036: return decoding;
037: }
038:
039: public static String encode(String value) throws Exception {
040: return new String(encode(value.getBytes()));
041: }
042:
043: public static byte[] encode(byte[] bytes) {
044: int inputLength = bytes.length;
045:
046: int lengthOfEncoding = getLengthOfEncoding(bytes);
047: byte[] encoding = new byte[lengthOfEncoding];
048: int encodingIndex = 0;
049:
050: int index = 0;
051: while (index < inputLength) {
052: byte c1 = bytes[index++];
053: byte c2 = index >= inputLength ? 0 : bytes[index++];
054: byte c3 = index >= inputLength ? 0 : bytes[index++];
055:
056: byte v1 = abs((byte) (c1 >> 2));
057: byte v2 = abs((byte) (((c1 << 4) & 63) + (c2 >> 4)));
058: byte v3 = abs((byte) (((c2 << 2) & 63) + (c3 >> 6)));
059: byte v4 = abs((byte) (c3 & 63));
060:
061: encoding[encodingIndex++] = base64Alphabet[v1];
062: encoding[encodingIndex++] = base64Alphabet[v2];
063: if (v3 != 0)
064: encoding[encodingIndex++] = base64Alphabet[v3];
065: else
066: encoding[encodingIndex++] = '=';
067: if (v4 != 0)
068: encoding[encodingIndex++] = base64Alphabet[v4];
069: else
070: encoding[encodingIndex++] = '=';
071: }
072: return encoding;
073: }
074:
075: private static int getLengthOfDecoding(byte[] bytes) {
076: if (bytes.length == 0)
077: return 0;
078:
079: int lengthOfOutput = (int) (bytes.length * .75);
080:
081: for (int i = bytes.length - 1; bytes[i] == pad; i--)
082: lengthOfOutput--;
083:
084: return lengthOfOutput;
085: }
086:
087: private static int getLengthOfEncoding(byte[] bytes) {
088: boolean needsPadding = (bytes.length % 3 != 0);
089:
090: int length = ((int) (bytes.length / 3)) * 4;
091: if (needsPadding)
092: length += 4;
093:
094: return length;
095: }
096:
097: public static byte getValueFor(byte b) {
098: if (b == pad)
099: return (byte) 0;
100: for (int i = 0; i < base64Alphabet.length; i++) {
101: if (base64Alphabet[i] == b)
102: return (byte) i;
103: }
104: return -1;
105: }
106:
107: private static byte abs(byte b) {
108: return (byte) Math.abs(b);
109: }
110: }
|