001    package org.apache.commons.ssl.asn1;
002    
003    import java.io.ByteArrayOutputStream;
004    import java.io.EOFException;
005    import java.io.IOException;
006    import java.io.InputStream;
007    import java.util.Vector;
008    
009    /** @deprecated use ASN1InputStream */
010    public 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    }