/* * #! * Ontopia Engine * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ package net.ontopia.net; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * INTERNAL: This class contains methods for decoding base64 * streams. Base64 decoding is described in section 6.8 of RFC 2045. */ public class Base64Encoder { private static final int BUFFER_SIZE = 1024; private static byte[] map = {'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', '+', '/'}; /** * INTERNAL: Encode string and return result as a string. */ public static String encode(String string) throws IOException { ByteArrayOutputStream ostream = new ByteArrayOutputStream(); encode(string, ostream); return ostream.toString("ISO-8859-1"); } /** * INTERNAL: Encode string and write result to output stream. */ public static void encode(String string, OutputStream ostream) throws IOException { encode(new ByteArrayInputStream(string.getBytes("ISO-8859-1")), ostream); } /** * INTERNAL: Encode input stream and write result to output stream. */ public static void encode(InputStream istream, OutputStream ostream) throws IOException { byte buffer[] = new byte[BUFFER_SIZE] ; int got = -1 ; int off = 0 ; int count = 0 ; while ((got = istream.read(buffer, off, BUFFER_SIZE-off)) > 0) { if ( got >= 3 ) { got += off; off = 0; while (off + 3 <= got) { int c1 = get1(buffer,off) ; int c2 = get2(buffer,off) ; int c3 = get3(buffer,off) ; int c4 = get4(buffer,off) ; switch (count) { case 73: ostream.write(map[c1]); ostream.write(map[c2]); ostream.write(map[c3]); ostream.write ('\n') ; ostream.write(map[c4]) ; count = 1 ; break ; case 74: ostream.write(map[c1]); ostream.write(map[c2]); ostream.write ('\n') ; ostream.write(map[c3]); ostream.write(map[c4]) ; count = 2 ; break ; case 75: ostream.write(map[c1]); ostream.write ('\n') ; ostream.write(map[c2]); ostream.write(map[c3]); ostream.write(map[c4]) ; count = 3 ; break ; case 76: ostream.write('\n') ; ostream.write(map[c1]); ostream.write(map[c2]); ostream.write(map[c3]); ostream.write(map[c4]) ; count = 4 ; break ; default: ostream.write(map[c1]); ostream.write(map[c2]); ostream.write(map[c3]); ostream.write(map[c4]) ; count += 4 ; break ; } off += 3 ; } for ( int i = 0 ; i < 3 ;i++) buffer[i] = (i < got-off) ? buffer[off+i] : ((byte) 0) ; off = got-off ; } else { off += got; } } switch (off) { case 1: ostream.write(map[get1(buffer, 0)]) ; ostream.write(map[get2(buffer, 0)]) ; ostream.write('=') ; ostream.write('=') ; break ; case 2: ostream.write(map[get1(buffer, 0)]); ostream.write(map[get2(buffer, 0)]); ostream.write(map[get3(buffer, 0)]); ostream.write('='); } ostream.flush(); } private static final int get1(byte buf[], int off) { return (buf[off] & 0xfc) >> 2 ; } private static final int get2(byte buf[], int off) { return ((buf[off]&0x3) << 4) | ((buf[off+1]&0xf0) >>> 4) ; } private static final int get3(byte buf[], int off) { return ((buf[off+1] & 0x0f) << 2) | ((buf[off+2] & 0xc0) >>> 6) ; } private static final int get4(byte buf[], int off) { return buf[off+2] & 0x3f ; } }