001/*
002 * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Base64InputStream.java $
003 * $Revision: 121 $
004 * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
005 *
006 * ====================================================================
007 * Licensed to the Apache Software Foundation (ASF) under one
008 * or more contributor license agreements.  See the NOTICE file
009 * distributed with this work for additional information
010 * regarding copyright ownership.  The ASF licenses this file
011 * to you under the Apache License, Version 2.0 (the
012 * "License"); you may not use this file except in compliance
013 * with the License.  You may obtain a copy of the License at
014 *
015 *   http://www.apache.org/licenses/LICENSE-2.0
016 *
017 * Unless required by applicable law or agreed to in writing,
018 * software distributed under the License is distributed on an
019 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
020 * KIND, either express or implied.  See the License for the
021 * specific language governing permissions and limitations
022 * under the License.
023 * ====================================================================
024 *
025 * This software consists of voluntary contributions made by many
026 * individuals on behalf of the Apache Software Foundation.  For more
027 * information on the Apache Software Foundation, please see
028 * <http://www.apache.org/>.
029 *
030 */
031
032package org.apache.commons.ssl;
033
034import java.io.FilterInputStream;
035import java.io.IOException;
036import java.io.InputStream;
037
038/**
039 * @author Credit Union Central of British Columbia
040 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
041 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
042 * @since 22-Feb-2007
043 */
044public class Base64InputStream extends FilterInputStream {
045    private final static byte[] LINE_ENDING =
046        System.getProperty("line.separator").getBytes();
047
048    final boolean decodeMode;
049
050    byte[] currentLine = null;
051    int pos = 0;
052
053    public Base64InputStream(InputStream base64, boolean decodeMode) {
054        super(base64);
055        this.decodeMode = decodeMode;
056    }
057
058    public int read() throws IOException {
059        getLine();
060        if (currentLine == null) {
061            return -1;
062        } else {
063            byte b = currentLine[pos++];
064            if (pos >= currentLine.length) {
065                currentLine = null;
066            }
067            return b;
068        }
069    }
070
071    public int read(byte b[], int off, int len) throws IOException {
072        if (b == null) {
073            throw new NullPointerException();
074        } else if ((off < 0) || (off > b.length) || (len < 0) ||
075                   ((off + len) > b.length) || ((off + len) < 0)) {
076            throw new IndexOutOfBoundsException();
077        } else if (len == 0) {
078            return 0;
079        }
080
081        getLine();
082        if (currentLine == null) {
083            return -1;
084        }
085        int size = Math.min(currentLine.length - pos, len);
086        System.arraycopy(currentLine, pos, b, off, size);
087        if (size >= currentLine.length - pos) {
088            currentLine = null;
089        } else {
090            pos += size;
091        }
092        return size;
093    }
094
095    private void getLine() throws IOException {
096        if (currentLine == null) {
097            if (decodeMode) {
098                String line = Util.readLine(in);
099                if (line != null) {
100                    byte[] b = line.getBytes();
101                    currentLine = Base64.decodeBase64(b);
102                    pos = 0;
103                }
104            } else {
105                // It will expand to 64 bytes (16 * 4) after base64 encoding!
106                byte[] b = Util.streamToBytes(in, 16 * 3);
107                if (b.length > 0) {
108                    b = Base64.encodeBase64(b);
109
110                    int lfLen = LINE_ENDING.length;
111                    currentLine = new byte[b.length + lfLen];
112                    System.arraycopy(b, 0, currentLine, 0, b.length);
113                    System.arraycopy(LINE_ENDING, 0, currentLine, b.length, lfLen);
114                }
115            }
116        }
117    }
118
119
120}