    001package org.apache.commons.ssl.asn1;
    002
    003import java.io.ByteArrayOutputStream;
    004import java.io.EOFException;
    005import java.io.IOException;
    006import java.io.InputStream;
    007import java.util.Vector;
    008
    009/** @deprecated use ASN1InputStream */
    010public class BERInputStream
    011    extends DERInputStream {
    012    private static final DERObject END_OF_STREAM = new DERObject() {
    013        void encode(
    014            DEROutputStream out)
    015            throws IOException {
    016            throw new IOException("Eeek!");
    017        }
    018        public int hashCode() {
    019            return 0;
    020        }
    021        public boolean equals(
    022            Object o) {
    023            return o == this;
    024        }
    025    };
    026    public BERInputStream(
    027        InputStream is) {
    028        super(is);
    029    }
    030
    031    /** read a string of bytes representing an indefinite length object. */
    032    private byte[] readIndefiniteLengthFully()
    033        throws IOException {
    034        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    035        int b, b1;
    036
    037        b1 = read();
    038
    039        while ((b = read()) >= 0) {
    040            if (b1 == 0 && b == 0) {
    041                break;
    042            }
    043
    044            bOut.write(b1);
    045            b1 = b;
    046        }
    047
    048        return bOut.toByteArray();
    049    }
    050
    051    private BERConstructedOctetString buildConstructedOctetString()
    052        throws IOException {
    053        Vector octs = new Vector();
    054
    055        for (; ;) {
    056            DERObject o = readObject();
    057
    058            if (o == END_OF_STREAM) {
    059                break;
    060            }
    061
    062            octs.addElement(o);
    063        }
    064
    065        return new BERConstructedOctetString(octs);
    066    }
    067
    068    public DERObject readObject()
    069        throws IOException {
    070        int tag = read();
    071        if (tag == -1) {
    072            throw new EOFException();
    073        }
    074
    075        int length = readLength();
    076
    077        if (length < 0)    // indefinite length method
    078        {
    079            switch (tag) {
    080                case NULL:
    081                    return null;
    082                case SEQUENCE | CONSTRUCTED:
    083                    BERConstructedSequence seq = new BERConstructedSequence();
    084
    085                    for (; ;) {
    086                        DERObject obj = readObject();
    087
    088                        if (obj == END_OF_STREAM) {
    089                            break;
    090                        }
    091
    092                        seq.addObject(obj);
    093                    }
    094                    return seq;
    095                case OCTET_STRING | CONSTRUCTED:
    096                    return buildConstructedOctetString();
    097                case SET | CONSTRUCTED:
    098                    ASN1EncodableVector v = new ASN1EncodableVector();
    099
    100                    for (; ;) {
    101                        DERObject obj = readObject();
    102
    103                        if (obj == END_OF_STREAM) {
    104                            break;
    105                        }
    106
    107                        v.add(obj);
    108                    }
    109                    return new BERSet(v);
    110                default:
    111                    //
    112                    // with tagged object tag number is bottom 5 bits
    113                    //
    114                    if ((tag & TAGGED) != 0) {
    115                        if ((tag & 0x1f) == 0x1f) {
    116                            throw new IOException("unsupported high tag encountered");
    117                        }
    118
    119                        //
    120                        // simple type - implicit... return an octet string
    121                        //
    122                        if ((tag & CONSTRUCTED) == 0) {
    123                            byte[] bytes = readIndefiniteLengthFully();
    124
    125                            return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
    126                        }
    127
    128                        //
    129                        // either constructed or explicitly tagged
    130                        //
    131                        DERObject dObj = readObject();
    132
    133                        if (dObj == END_OF_STREAM)     // empty tag!
    134                        {
    135                            return new DERTaggedObject(tag & 0x1f);
    136                        }
    137
    138                        DERObject next = readObject();
    139
    140                        //
    141                        // explicitly tagged (probably!) - if it isn't we'd have to
    142                        // tell from the context
    143                        //
    144                        if (next == END_OF_STREAM) {
    145                            return new BERTaggedObject(tag & 0x1f, dObj);
    146                        }
    147
    148                        //
    149                        // another implicit object, we'll create a sequence...
    150                        //
    151                        seq = new BERConstructedSequence();
    152
    153                        seq.addObject(dObj);
    154
    155                        do {
    156                            seq.addObject(next);
    157                            next = readObject();
    158                        }
    159                        while (next != END_OF_STREAM);
    160
    161                        return new BERTaggedObject(false, tag & 0x1f, seq);
    162                    }
    163
    164                    throw new IOException("unknown BER object encountered");
    165            }
    166        } else {
    167            if (tag == 0 && length == 0)    // end of contents marker.
    168            {
    169                return END_OF_STREAM;
    170            }
    171
    172            byte[] bytes = new byte[length];
    173
    174            readFully(bytes);
    175
    176            return buildObject(tag, bytes);
    177        }
    178    }
    179}