/* GNU Lesser General Public License Base64Codec - Base64 Document Encoding/Decoding Class Copyright (C) 2003 Howard Kistler & other contributors 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 */ package com.hexidec.util; import java.util.Vector; public class Base64Codec { // Constants -------------------------------------------------------------------------------/ public static Vector<String> Base64Tokens = new Vector<String>(64); static { Base64Tokens.add("A"); Base64Tokens.add("B"); Base64Tokens.add("C"); Base64Tokens.add("D"); Base64Tokens.add("E"); Base64Tokens.add("F"); Base64Tokens.add("G"); Base64Tokens.add("H"); Base64Tokens.add("I"); Base64Tokens.add("J"); Base64Tokens.add("K"); Base64Tokens.add("L"); Base64Tokens.add("M"); Base64Tokens.add("N"); Base64Tokens.add("O"); Base64Tokens.add("P"); Base64Tokens.add("Q"); Base64Tokens.add("R"); Base64Tokens.add("S"); Base64Tokens.add("T"); Base64Tokens.add("U"); Base64Tokens.add("V"); Base64Tokens.add("W"); Base64Tokens.add("X"); Base64Tokens.add("Y"); Base64Tokens.add("Z"); Base64Tokens.add("a"); Base64Tokens.add("b"); Base64Tokens.add("c"); Base64Tokens.add("d"); Base64Tokens.add("e"); Base64Tokens.add("f"); Base64Tokens.add("g"); Base64Tokens.add("h"); Base64Tokens.add("i"); Base64Tokens.add("j"); Base64Tokens.add("k"); Base64Tokens.add("l"); Base64Tokens.add("m"); Base64Tokens.add("n"); Base64Tokens.add("o"); Base64Tokens.add("p"); Base64Tokens.add("q"); Base64Tokens.add("r"); Base64Tokens.add("s"); Base64Tokens.add("t"); Base64Tokens.add("u"); Base64Tokens.add("v"); Base64Tokens.add("w"); Base64Tokens.add("x"); Base64Tokens.add("y"); Base64Tokens.add("z"); Base64Tokens.add("0"); Base64Tokens.add("1"); Base64Tokens.add("2"); Base64Tokens.add("3"); Base64Tokens.add("4"); Base64Tokens.add("5"); Base64Tokens.add("6"); Base64Tokens.add("7"); Base64Tokens.add("8"); Base64Tokens.add("9"); Base64Tokens.add("+"); Base64Tokens.add("/"); } public static final char BASE64PAD = '='; public static final char LINEFEED = (char)10; public static final char CARRIAGE = (char)13; public static final int LINEMAX = 75; // Constructors ----------------------------------------------------------------------------/ public Base64Codec() { } // Processor Methods -----------------------------------------------------------------------/ public static String encode(byte[] sourceBytes) { int byteTriad = sourceBytes.length % 3; StringBuffer encoding = new StringBuffer(); int bitOffset = 7; int b64Offset = 5; int bytePlace = 0; byte tokenValue = (byte)0; int lineLength = 0; while(bytePlace < sourceBytes.length) { tokenValue = (byte)((byte)tokenValue | (byte)((sourceBytes[bytePlace] & (1 << bitOffset)) > 0 ? (1 << b64Offset) : (byte)0)); bitOffset--; if(bitOffset < 0) { bitOffset = 7; bytePlace++; } b64Offset--; if(b64Offset < 0) { b64Offset = 5; encoding.append(Base64Tokens.elementAt(tokenValue)); tokenValue = (byte)0; lineLength++; if(lineLength > LINEMAX) { encoding.append(CARRIAGE); encoding.append(LINEFEED); lineLength = 0; } } } if(b64Offset != 5) { bytePlace--; for(int i = b64Offset; i >= 0; i--) { if(bitOffset >= 0) { tokenValue = (byte)((byte)tokenValue | (byte)((sourceBytes[bytePlace] & (1 << bitOffset)) > 0 ? (1 << i) : (byte)0)); } bitOffset--; } encoding.append(Base64Tokens.elementAt(tokenValue)); } if(byteTriad == 2) { encoding.append(BASE64PAD); } else if(byteTriad == 1) { encoding.append(BASE64PAD); encoding.append(BASE64PAD); } return encoding.toString(); } public static String encode(String source) { return encode(source.getBytes()); } public static byte[] decodeBytes(byte[] source) { int bitOffset = 7; int b64Offset = 5; int bytePlace = 0; byte charValue = (byte)0; byte[] byteBack = new byte[source.length]; int bytecount = 0; while(bytePlace < source.length) { if((char)(source[bytePlace]) == BASE64PAD) { // end processing when encountering special end-padding character break; } if((char)(source[bytePlace]) == LINEFEED || (char)(source[bytePlace]) == CARRIAGE) { // ignore standard line break characters bytePlace++; continue; } else { if(!Base64Tokens.contains("" + (char)(source[bytePlace]))) { // ignore unknown characters (mostly implemented to deal with other line break character sequences) bytePlace++; continue; } else { byte currentByte = source[bytePlace]; charValue = (byte)((byte)charValue | (byte)((currentByte & (1 << b64Offset)) > 0 ? (1 << bitOffset) : (byte)0)); bitOffset--; if(bitOffset < 0) { bitOffset = 7; byteBack[bytecount] = charValue; bytecount++; charValue = (byte)0; } b64Offset--; if(b64Offset < 0) { b64Offset = 5; bytePlace++; } } } } return byteBack; } public static byte[] decodeBytes(String source) { return decodeBytes(source.getBytes()); } public static String decode(String source) { return new String(decodeBytes(source)); } }