alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (BerDecoder.java)

This example Java source code file (BerDecoder.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

berdecoder, decodeexception, encountered, indefinite, insufficient, integer, string, the, unsupportedencodingexception, utf8

The BerDecoder.java Java example source code

/*
 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jndi.ldap;

import java.io.UnsupportedEncodingException;

/**
  * A BER decoder. Contains methods to parse a BER buffer.
  *
  * @author Jagane Sundar
  * @author Vincent Ryan
  */
public final class BerDecoder extends Ber {

    private int origOffset;  // The start point in buf to decode

    /**
     * Creates a BER decoder that reads bytes from the specified buffer.
     */
    public BerDecoder(byte buf[], int offset, int bufsize) {

        this.buf = buf;         // shared buffer, be careful to use this class
        this.bufsize = bufsize;
        this.origOffset = offset;

        reset();
    }

    /**
     * Resets this decode to start parsing from the initial offset
     * (ie., same state as after calling the constructor).
     */
    public void reset() {
        offset = origOffset;
    }

    /**
      * Returns the current parse position.
      * It points to the byte that will be parsed next.
      * Useful for parsing sequences.
      */
    public int getParsePosition() {
        return offset;
    }

    /**
      * Parses a possibly variable length field.
      */
    public int parseLength() throws DecodeException {

        int lengthbyte = parseByte();

        if ((lengthbyte & 0x80) == 0x80) {

            lengthbyte &= 0x7f;

            if (lengthbyte == 0) {
                throw new DecodeException(
                    "Indefinite length not supported");
            }

            if (lengthbyte > 4) {
                throw new DecodeException("encoding too long");
            }

            if (bufsize - offset < lengthbyte) {
                throw new DecodeException("Insufficient data");
            }

            int retval = 0;

            for( int i = 0; i < lengthbyte; i++) {
                retval = (retval << 8) + (buf[offset++] & 0xff);
            }
            return retval;
        } else {
            return lengthbyte;
        }
    }

    /**
     * Parses the next sequence in this BER buffer.
     * @param rlen An array for returning size of the sequence in bytes. If null,
     *          the size is not returned.
     * @return The sequence's tag.
     */
    public int parseSeq(int rlen[]) throws DecodeException {

        int seq = parseByte();
        int len = parseLength();
        if (rlen != null) {
            rlen[0] = len;
        }
        return seq;
    }

    /**
     * Used to skip bytes. Usually used when trying to recover from parse error.
     * Don't need to be public right now?
     * @param i The number of bytes to skip
     */
    void seek(int i) throws DecodeException {
        if (offset + i > bufsize || offset + i < 0) {
            throw new DecodeException("array index out of bounds");
        }
        offset += i;
    }

    /**
     * Parses the next byte in this BER buffer.
     * @return The byte parsed.
     */
    public int parseByte() throws DecodeException {
        if (bufsize - offset < 1) {
            throw new DecodeException("Insufficient data");
        }
        return buf[offset++] & 0xff;
    }


    /**
     * Returns the next byte in this BER buffer without consuming it.
     * @return The next byte.
     */
    public int peekByte() throws DecodeException {
        if (bufsize - offset < 1) {
            throw new DecodeException("Insufficient data");
        }
        return buf[offset] & 0xff;
    }

    /**
     * Parses an ASN_BOOLEAN tagged integer from this BER buffer.
     * @return true if the tagged integer is 0; false otherwise.
     */
    public boolean parseBoolean() throws DecodeException {
        return ((parseIntWithTag(ASN_BOOLEAN) == 0x00) ? false : true);
    }

    /**
     * Parses an ASN_ENUMERATED tagged integer from this BER buffer.
     * @return The tag of enumeration.
     */
    public int parseEnumeration() throws DecodeException {
        return parseIntWithTag(ASN_ENUMERATED);
    }

    /**
     * Parses an ASN_INTEGER tagged integer from this BER buffer.
     * @return The value of the integer.
     */
    public int parseInt() throws DecodeException {
        return parseIntWithTag(ASN_INTEGER);
    }

    /**
      * Parses an integer that's preceded by a tag.
      *<blockquote>
      * BER integer ::= tag length byte {byte}*
      *</pre>
      */
    private int parseIntWithTag(int tag) throws DecodeException {


        if (parseByte() != tag) {
            throw new DecodeException("Encountered ASN.1 tag " +
                Integer.toString(buf[offset - 1] & 0xff) +
                " (expected tag " + Integer.toString(tag) + ")");
        }

        int len = parseLength();

        if (len > 4) {
            throw new DecodeException("INTEGER too long");
        } else if (len > bufsize - offset) {
            throw new DecodeException("Insufficient data");
        }

        byte fb = buf[offset++];
        int value = 0;

        value = fb & 0x7F;
        for( int i = 1 /* first byte already read */ ; i < len; i++) {
            value <<= 8;
            value |= (buf[offset++] & 0xff);
        }

        if ((fb & 0x80) == 0x80) {
            value = -value;
        }

        return value;
    }

    /**
      * Parses a string.
      */
    public String parseString(boolean decodeUTF8) throws DecodeException {
        return parseStringWithTag(ASN_SIMPLE_STRING, decodeUTF8, null);
    }

    /**
      * Parses a string of a given tag from this BER buffer.
      *<blockquote>
      *BER simple string ::= tag length {byte}*
      *</pre>
      * @param rlen An array for holding the relative parsed offset; if null
      *  offset not set.
      * @param decodeUTF8 If true, use UTF-8 when decoding the string; otherwise
      * use ISO-Latin-1 (8859_1). Use true for LDAPv3; false for LDAPv2.
      * @param tag The tag that precedes the string.
      * @return The non-null parsed string.
      */
    public String parseStringWithTag(int tag, boolean decodeUTF8, int rlen[])
        throws DecodeException {

        int st;
        int origOffset = offset;

        if ((st = parseByte()) != tag) {
            throw new DecodeException("Encountered ASN.1 tag " +
                Integer.toString((byte)st) + " (expected tag " + tag + ")");
        }

        int len = parseLength();

        if (len > bufsize - offset) {
            throw new DecodeException("Insufficient data");
        }

        String retstr;
        if (len == 0) {
            retstr = "";
        } else {
            byte[] buf2 = new byte[len];

            System.arraycopy(buf, offset, buf2, 0, len);
            if (decodeUTF8) {
                try {
                    retstr = new String(buf2, "UTF8");
                } catch (UnsupportedEncodingException e) {
                    throw new DecodeException("UTF8 not available on platform");
                }
            } else {
                try {
                    retstr = new String(buf2, "8859_1");
                } catch (UnsupportedEncodingException e) {
                    throw new DecodeException("8859_1 not available on platform");
                }
            }
            offset += len;
        }

        if (rlen != null) {
            rlen[0] = offset - origOffset;
        }

        return retstr;
    }

    /**
     * Parses an octet string of a given type(tag) from this BER buffer.
     * <blockquote>
     * BER Binary Data of type "tag" ::= tag length {byte}*
     *</pre>
     *
     * @param tag The tag to look for.
     * @param rlen An array for returning the relative parsed position. If null,
     *          the relative parsed position is not returned.
     * @return A non-null array containing the octet string.
     * @throws DecodeException If the next byte in the BER buffer is not
     * <tt>tag, or if length specified in the BER buffer exceeds the
     * number of bytes left in the buffer.
     */
    public byte[] parseOctetString(int tag, int rlen[]) throws DecodeException {

        int origOffset = offset;
        int st;
        if ((st = parseByte()) != tag) {

            throw new DecodeException("Encountered ASN.1 tag " +
                Integer.toString(st) +
                " (expected tag " + Integer.toString(tag) + ")");
        }

        int len = parseLength();

        if (len > bufsize - offset) {
            throw new DecodeException("Insufficient data");
        }

        byte retarr[] = new byte[len];
        if (len > 0) {
            System.arraycopy(buf, offset, retarr, 0, len);
            offset += len;
        }

        if (rlen != null) {
            rlen[0] = offset - origOffset;
        }

        return retarr;
    }

    /**
     * Returns the number of unparsed bytes in this BER buffer.
     */
    public int bytesLeft() {
        return bufsize - offset;
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java BerDecoder.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.