package com.FitBank.common; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; /** * Clase que decodifica un stream. * * @author FitBank * @version 1.0 */ public class Base64InputStream extends FilterInputStream { private static final char[] BASE_64 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; private int i = 0; private byte[] outbuf = new byte[3]; /** * Crea un nuevo objeto Base64InputStream. * * @param in Stream de entrada */ public Base64InputStream(InputStream in) { super(in); } /** * Decodifica un array de bytes codificado. * * @param contenido Array de bytes * * @return array de bytes decodificado */ public static byte[] decodificar(String contenido) { ByteArrayOutputStream o = new ByteArrayOutputStream(); ByteArrayInputStream i = new ByteArrayInputStream(contenido.replaceAll("\n", "").getBytes()); Base64InputStream in = new Base64InputStream(i); try { while (in.available() > 0) { o.write(in.read()); } } catch (IOException e) { Debug.imprimirError(e); } return o.toByteArray(); } /** * Lee un caracter. * * @return int con el caracter * * @throws IOException en caso de error */ @Override public int read() throws IOException { if (i == 0) { int a = byteDesdeChar(); int b = byteDesdeChar(); int c = byteDesdeChar(); int d = byteDesdeChar(); int j = i--; if (i > 0) { outbuf[2 - --i] = (byte) (a << 2 | b >> 4); } if (i > 0) { outbuf[2 - --i] = (byte) (b << 4 | c >> 2); } if (i > 0) { outbuf[2 - --i] = (byte) (c << 6 | d >> 0); } i += j - 1; } return outbuf[2 - --i]; } private int byteDesdeChar() throws IOException { char c = (char) super.read(); while (c == '\n' && super.available() > 0) { c = (char) super.read(); // se salta las lineas } while (c == '=' && super.available() > 0) { c = (char) super.read(); // se salta los iguales del final } for (int a = 0; a < BASE_64.length; a++) { if (BASE_64[a] == c) { i++; return a; } } return 0; } /** * Lee un array de bytes. * * @param b Array * * @return entero con el resultado * * @throws IOException en caso de error */ @Override public int read(byte[] b) throws IOException { throw new IOException("Metodo no implementado"); } /** * Lee un array de caracteres con un offset y longitud. * * @param b Array * @param off Offset * @param len Longitud * * @return entero con el resultado * * @throws IOException en caso de error */ @Override public int read(byte[] b, int off, int len) throws IOException { throw new IOException("Metodo no implementado"); } /** * Se salta n bytes del stream. No implementado. * * @param n Numero de bytes * * @return long con el resultado * * @throws IOException en caso de error */ @Override public long skip(long n) throws IOException { throw new IOException("Metodo no implementado"); } /** * Esta es una implementacion especial que devuelve 1 si hay aun por leer y 0 si ya se acabo. * * @return 1 si hay aun bytes por leer o 0 si no. * * @throws IOException En caso de que no se haya abierto el inputstream */ @Override public int available() throws IOException { return in.available() + (i > 0 ? 1 : 0); } /** * Indica si se soporta marcas. * * @return false siempre */ @Override public boolean markSupported() { return false; } }