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}