package com.fp.common.base64; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import com.fp.common.logger.APPLogger; /** * Clase que se encarga de * @author Jorge Vaca. * @version 2.1 */ public class Base64Input 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', '+', '/' }; /** * Decodifica un array de bytes codificado. * * @param contenido Array de bytes * @return array de bytes decodificado */ public static String decodificar(String contenido) { ByteArrayOutputStream o = new ByteArrayOutputStream(); ByteArrayInputStream i = new ByteArrayInputStream(contenido.replaceAll("\n", "").getBytes()); Base64Input in = new Base64Input(i); try { while (in.available() > 0) { o.write(in.read()); } } catch (IOException e) { APPLogger.getLogger().error(e.getMessage(), e); } return o.toString(); } private int i = 0; private byte[] outbuf = new byte[3]; /** * Crea un nuevo objeto Base64InputStream. * * @param in Stream de entrada */ public Base64Input(InputStream in) { super(in); } /** * 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 (this.in.available() + this.i > 0) ? 1 : 0; } 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) { this.i++; return a; } } return 0; } /** * Indica si se soporta marcas. * * @return false siempre */ @Override public boolean markSupported() { return false; } /** * Lee un caracter. * * @return int con el caracter * @throws IOException en caso de error */ @Override public int read() throws IOException { if (this.i == 0) { int a = this.byteDesdeChar(); int b = this.byteDesdeChar(); int c = this.byteDesdeChar(); int d = this.byteDesdeChar(); int j = this.i--; if (this.i > 0) { this.outbuf[2 - --this.i] = (byte) (a << 2 | b >> 4); } if (this.i > 0) { this.outbuf[2 - --this.i] = (byte) (b << 4 | c >> 2); } if (this.i > 0) { this.outbuf[2 - --this.i] = (byte) (c << 6 | d >> 0); } this.i += j - 1; } return this.outbuf[2 - --this.i]; } /** * 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"); } }