001: /*
002:
003: ============================================================================
004: The Apache Software License, Version 1.1
005: ============================================================================
006:
007: Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
008:
009: Redistribution and use in source and binary forms, with or without modifica-
010: tion, are permitted provided that the following conditions are met:
011:
012: 1. Redistributions of source code must retain the above copyright notice,
013: this list of conditions and the following disclaimer.
014:
015: 2. Redistributions in binary form must reproduce the above copyright notice,
016: this list of conditions and the following disclaimer in the documentation
017: and/or other materials provided with the distribution.
018:
019: 3. The end-user documentation included with the redistribution, if any, must
020: include the following acknowledgment: "This product includes software
021: developed by the Apache Software Foundation (http://www.apache.org/)."
022: Alternately, this acknowledgment may appear in the software itself, if
023: and wherever such third-party acknowledgments normally appear.
024:
025: 4. The names "Batik" and "Apache Software Foundation" must not be
026: used to endorse or promote products derived from this software without
027: prior written permission. For written permission, please contact
028: apache@apache.org.
029:
030: 5. Products derived from this software may not be called "Apache", nor may
031: "Apache" appear in their name, without prior written permission of the
032: Apache Software Foundation.
033:
034: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
035: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
036: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
037: APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
038: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
039: DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
040: OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
041: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
042: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
043: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
044:
045: This software consists of voluntary contributions made by many individuals
046: on behalf of the Apache Software Foundation. For more information on the
047: Apache Software Foundation, please see <http://www.apache.org/>.
048:
049: */
050:
051: package org.apache.batik.util;
052:
053: import java.io.IOException;
054: import java.io.InputStream;
055:
056: /**
057: * This class implements a Base64 Character decoder as specified in RFC1113.
058: * Unlike some other encoding schemes there is nothing in this encoding that
059: * tells the decoder where a buffer starts or stops, so to use it you will need
060: * to isolate your encoded data into a single chunk and then feed them
061: * this decoder. The simplest way to do that is to read all of the encoded
062: * data into a string and then use:
063: * <pre>
064: * byte data[];
065: * InputStream is = new ByteArrayInputStream(data);
066: * is = new Base64DecodeStream(is);
067: * </pre>
068: *
069: * On errors, this class throws a IOException with the following detail
070: * strings:
071: * <pre>
072: * "Base64DecodeStream: Bad Padding byte (2)."
073: * "Base64DecodeStream: Bad Padding byte (1)."
074: * </pre>
075: *
076: * @author <a href="thomas.deweese@kodak.com">Thomas DeWeese</a>
077: * @author <a href="vincent.hardy@eng.sun.com">Vincent Hardy</a>
078: * @author Chuck McManis
079: * @version $Id$
080: */
081:
082: public class Base64DecodeStream extends InputStream {
083:
084: InputStream src;
085:
086: public Base64DecodeStream(InputStream src) {
087: this .src = src;
088: }
089:
090: private final static byte pem_array[] = new byte[256];
091: static {
092: for (int i = 0; i < pem_array.length; i++)
093: pem_array[i] = -1;
094:
095: int idx = 0;
096: for (char c = 'A'; c <= 'Z'; c++) {
097: pem_array[c] = (byte) idx++;
098: }
099: for (char c = 'a'; c <= 'z'; c++) {
100: pem_array[c] = (byte) idx++;
101: }
102:
103: for (char c = '0'; c <= '9'; c++) {
104: pem_array[c] = (byte) idx++;
105: }
106:
107: pem_array['+'] = (byte) idx++;
108: pem_array['/'] = (byte) idx++;
109: }
110:
111: public boolean markSupported() {
112: return false;
113: }
114:
115: public void close() throws IOException {
116: EOF = true;
117: }
118:
119: public int available() throws IOException {
120: return 3 - out_offset;
121: }
122:
123: byte decode_buffer[] = new byte[4];
124: byte out_buffer[] = new byte[3];
125: int out_offset = 3;
126: boolean EOF = false;
127:
128: public int read() throws IOException {
129:
130: if (out_offset == 3) {
131: if (EOF || getNextAtom()) {
132: EOF = true;
133: return -1;
134: }
135: }
136:
137: return ((int) out_buffer[out_offset++]) & 0xFF;
138: }
139:
140: public int read(byte[] out, int offset, int len) throws IOException {
141:
142: int idx = 0;
143: while (idx < len) {
144: if (out_offset == 3) {
145: if (EOF || getNextAtom()) {
146: EOF = true;
147: if (idx == 0)
148: return -1;
149: else
150: return idx;
151: }
152: }
153:
154: out[offset + idx] = out_buffer[out_offset++];
155:
156: idx++;
157: }
158: return idx;
159: }
160:
161: final boolean getNextAtom() throws IOException {
162: int count, a, b, c, d;
163:
164: int off = 0;
165: while (off != 4) {
166: count = src.read(decode_buffer, off, 4 - off);
167: if (count == -1)
168: return true;
169:
170: int in = off, out = off;
171: while (in < off + count) {
172: if ((decode_buffer[in] != '\n')
173: && (decode_buffer[in] != '\r')
174: && (decode_buffer[in] != ' '))
175: decode_buffer[out++] = decode_buffer[in];
176: in++;
177: }
178:
179: off = out;
180: }
181:
182: a = pem_array[((int) decode_buffer[0]) & 0xFF];
183: b = pem_array[((int) decode_buffer[1]) & 0xFF];
184: c = pem_array[((int) decode_buffer[2]) & 0xFF];
185: d = pem_array[((int) decode_buffer[3]) & 0xFF];
186:
187: out_buffer[0] = (byte) ((a << 2) | (b >>> 4));
188: out_buffer[1] = (byte) ((b << 4) | (c >>> 2));
189: out_buffer[2] = (byte) ((c << 6) | d);
190:
191: if (decode_buffer[3] != '=') {
192: // All three bytes are good.
193: out_offset = 0;
194: } else if (decode_buffer[2] == '=') {
195: // Only one byte of output.
196: out_buffer[2] = out_buffer[0];
197: out_offset = 2;
198: EOF = true;
199: } else {
200: // Only two bytes of output.
201: out_buffer[2] = out_buffer[1];
202: out_buffer[1] = out_buffer[0];
203: out_offset = 1;
204: EOF = true;
205: }
206:
207: return false;
208: }
209: }
|