package com.jcomeau; public class Base64 { public static String base64code = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/"; public static int splitLinesAt = 76; public static String encode(String string) { String encoded = ""; byte[] stringArray; try { stringArray = string.getBytes("UTF-8"); // necessary for wchars } catch (Exception ignored) { stringArray = string.getBytes(); // use default locale } // determine how many padding bytes to add to the output int paddingCount = (3 - (stringArray.length % 3)) % 3; // add any necessary padding to the input stringArray = zeroPad(stringArray.length + paddingCount, stringArray); // process 3 bytes at a time, churning out 4 output bytes // worry about CRLF insertions later for (int i = 0; i < stringArray.length; i += 3) { int j = (stringArray[i] << 16) + (stringArray[i + 1] << 8) + stringArray[i + 2]; encoded = encoded + base64code.charAt((j >> 18) & 0x3f) + base64code.charAt((j >> 12) & 0x3f) + base64code.charAt((j >> 6) & 0x3f) + base64code.charAt(j & 0x3f); } // replace encoded padding nulls with "=" return splitLines(encoded.substring(0, encoded.length() - paddingCount) + "==".substring(0, paddingCount)); } public static byte[] zeroPad(int length, byte[] bytes) { byte[] padded = new byte[length]; // initialized to zero by JVM System.arraycopy(bytes, 0, padded, 0, bytes.length); return padded; } public static byte[] appendBytes(byte[] byteArray1, byte[] byteArray2) { byte[] arraySum = new byte[byteArray1.length + byteArray2.length]; System.arraycopy(byteArray1, 0, arraySum, 0, byteArray1.length); System.arraycopy(byteArray2, 0, arraySum, byteArray1.length, byteArray2.length); return arraySum; } public static String splitLines(String string) { String lines = ""; for (int i = 0; i < string.length(); i += splitLinesAt) { lines += string.substring(i, Math.min(string.length(), i + splitLinesAt)); lines += "\r\n"; } return lines; } public static String filterOut(String chars, String target) { int index; for (int i = 0; i < chars.length(); i++) { while ((index = target.indexOf(chars.charAt(i))) >= 0) { target = target.substring(0, index) + target.substring(index + 1); } } return target; } public static String decode(String encoded) { int paddingCount = 0, extra = 0; String decoded = ""; encoded = filterOut(" \r\n", encoded); while(encoded.endsWith("=")) { encoded = encoded.substring(0, encoded.length() - 1); paddingCount++; } encoded = encoded + "AA".substring(0, paddingCount); // add nulls if ((extra = encoded.length() % 4) > 0) { System.err.println("Code string \"" + encoded + "\" length not a multiple of 4, chopping " + extra + " extra bytes"); encoded = encoded.substring(0, encoded.length() - extra); } for (int i = 0, k = 0; i < encoded.length(); i += 4, k = 0) { for (int j = 0, c = 0; j < 4; j++) { c = encoded.charAt(i + j); if (base64code.indexOf(c) >= 0) c = base64code.indexOf(c); else c = 0; k = (k << 6) | c; } decoded = decoded + (char)(k >> 16) + (char)((k >> 8) & 0xff) + (char)(k & 0xff); } return decoded.substring(0, decoded.length() - paddingCount); } public static void encodeFilter() { Common.debug("Base64 encoding stdin"); byte[] text = new byte[3]; try { while (System.in.read(text, 0, 3) == 3) System.out.print(encode(new String(text))); } catch (Exception exception) { System.err.println("aborted: " + exception); } } public static void decodeFilter() { Common.debug("Base64 decoding stdin"); byte[] code = new byte[76]; try { for (int found = code.length + 1, soFar = 0; found > -1;) { found = System.in.read(code, soFar, 1); if (found > 0 && code[soFar] >= ' ') soFar += found; if (found <= 0 || soFar == code.length) { Common.debug("decoding: " + new String(code)); System.out.print(decode(new String(code).substring(0, soFar))); soFar = 0; } } } catch (Exception exception) { System.err.println("aborted: " + exception); } } public static void main(String args[]) { if (args.length == 1 && args[0].startsWith("base64") && args[0].endsWith("codeFilter")) { Common.debug("filter invoked"); if (args[0].equals("encodeFilter")) encodeFilter(); else if (args[0].equals("decodeFilter")) decodeFilter(); else System.err.println("no such filter " + args[0]); } else { String encoded; for (int i = 0; i < args.length; i++) { System.err.println("encoding \"" + args[i] + "\""); encoded = encode(args[i]); System.out.println("encoded: " + encoded); System.out.println("decoded: " + decode(encoded)); } } } }