/* DERReader.java -- parses ASN.1 DER sequences
   Copyright (C) 2003 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.security.der;

import gnu.java.security.OID;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * This class decodes DER sequences into Java objects. The methods of
 * this class do not have knowledge of higher-levels of structure in the
 * DER stream -- such as ASN.1 constructions -- and it is therefore up
 * to the calling application to determine if the data are structured
 * properly by inspecting the {@link DERValue} that is returned.
 *
 * @author Casey Marshall (csm@gnu.org)
 */
public class DERReader implements DER
{

  // Fields.
  // ------------------------------------------------------------------------

  protected InputStream in;

  protected final ByteArrayOutputStream encBuf;

  // Constructor.
  // ------------------------------------------------------------------------

  /**
   * Create a new DER reader from a byte array.
   *
   * @param in The encoded bytes.
   */
  public DERReader(byte[] in)
  {
    this(new ByteArrayInputStream(in));
  }

  public DERReader (byte[] in, int off, int len)
  {
    this (new ByteArrayInputStream (in, off, len));
  }

  /**
   * Create a new DER readed from an input stream.
   *
   * @param in The encoded bytes.
   */
  public DERReader(InputStream in)
  {
    if (!in.markSupported())
      this.in = new BufferedInputStream(in, 16384);
    else
      this.in = in;
    encBuf = new ByteArrayOutputStream(2048);
  }

  // Class methods.
  // ------------------------------------------------------------------------

  /**
   * Convenience method for reading a single primitive value from the
   * given byte array.
   *
   * @param encoded The encoded bytes.
   * @throws IOException If the bytes do not represent an encoded
   * object.
   */
  public static DERValue read(byte[] encoded) throws IOException
  {
    return new DERReader(encoded).read();
  }

  // Instance methods.
  // ------------------------------------------------------------------------

  public void skip (int bytes) throws IOException
  {
    in.skip (bytes);
  }

  /**
   * Decode a single value from the input stream, returning it in a new
   * {@link DERValue}. By "single value" we mean any single type in its
   * entirety -- including constructed types such as SEQUENCE and all
   * the values they contain. Usually it is sufficient to call this
   * method once to parse and return the top-level structure, then to
   * inspect the returned value for the proper contents.
   *
   * @return The parsed DER structure.
   * @throws IOException If an error occurs reading from the input
   * stream.
   * @throws DEREncodingException If the input does not represent a
   * valid DER stream.
   */
  public DERValue read() throws IOException
  {
    int tag = in.read();
    if (tag == -1)
      throw new EOFException();
    encBuf.write(tag);
    int len = readLength();
    DERValue value = null;
    if ((tag & CONSTRUCTED) == CONSTRUCTED)
      {
        in.mark(2048);
        byte[] encoded = new byte[len];
        in.read(encoded);
        encBuf.write(encoded);
        value = new DERValue(tag, len, CONSTRUCTED_VALUE, encBuf.toByteArray());
        in.reset();
        encBuf.reset();
        return value;
      }
    switch (tag & 0xC0)
      {
        case UNIVERSAL:
          value = new DERValue(tag, len, readUniversal(tag, len),
            encBuf.toByteArray());
          encBuf.reset();
          break;
        case CONTEXT:
          byte[] encoded = new byte[len];
          in.read(encoded);
          encBuf.write(encoded);
          value = new DERValue(tag, len, encoded, encBuf.toByteArray());
          encBuf.reset();
          break;
        case APPLICATION:
          // This should not be reached, since (I think) APPLICATION is
          // always constructed.
          throw new DEREncodingException("non-constructed APPLICATION data");
        default:
          throw new DEREncodingException("PRIVATE class not supported");
      }
    return value;
  }

  protected int readLength() throws IOException
  {
    int i = in.read();
    if (i == -1)
      throw new EOFException();
    encBuf.write(i);
    if ((i & ~0x7F) == 0)
      {
        return i;
      }
    else if (i < 0xFF)
      {
        byte[] octets = new byte[i & 0x7F];
        in.read(octets);
        encBuf.write(octets);
        return new BigInteger(1, octets).intValue();
      }
    throw new DEREncodingException();
  }

  // Own methods.
  // ------------------------------------------------------------------------

  private Object readUniversal(int tag, int len) throws IOException
  {
    byte[] value = new byte[len];
    in.read(value);
    encBuf.write(value);
    switch (tag & 0x1F)
      {
        case BOOLEAN:
          if (value.length != 1)
            throw new DEREncodingException();
          return Boolean.valueOf(value[0] != 0);
        case NULL:
          if (len != 0)
            throw new DEREncodingException();
          return null;
        case INTEGER:
        case ENUMERATED:
          return new BigInteger(value);
        case BIT_STRING:
          byte[] bits = new byte[len - 1];
          System.arraycopy(value, 1, bits, 0, bits.length);
          return new BitString(bits, value[0] & 0xFF);
        case OCTET_STRING:
          return value;
        case NUMERIC_STRING:
        case PRINTABLE_STRING:
        case T61_STRING:
        case VIDEOTEX_STRING:
        case IA5_STRING:
        case GRAPHIC_STRING:
        case ISO646_STRING:
        case GENERAL_STRING:
        case UNIVERSAL_STRING:
        case BMP_STRING:
        case UTF8_STRING:
          return makeString(tag, value);
        case UTC_TIME:
        case GENERALIZED_TIME:
          return makeTime(tag, value);
        case OBJECT_IDENTIFIER:
          return new OID(value);
        case RELATIVE_OID:
          return new OID(value, true);
        default:
          throw new DEREncodingException("unknown tag " + tag);
      }
  }

  private static String makeString(int tag, byte[] value)
    throws IOException
  {
    switch (tag & 0x1F)
      {
        case NUMERIC_STRING:
        case PRINTABLE_STRING:
        case T61_STRING:
        case VIDEOTEX_STRING:
        case IA5_STRING:
        case GRAPHIC_STRING:
        case ISO646_STRING:
        case GENERAL_STRING:
          return fromIso88591(value);

        case UNIVERSAL_STRING:
          // XXX The docs say UniversalString is encoded in four bytes
          // per character, but Java has no support (yet) for UTF-32.
          //return new String(buf, "UTF-32");
        case BMP_STRING:
          return fromUtf16Be(value);

        case UTF8_STRING:
          return fromUtf8(value);

        default:
          throw new DEREncodingException("unknown string tag");
      }
  }

  private static String fromIso88591(byte[] bytes)
  {
    StringBuffer str = new StringBuffer(bytes.length);
    for (int i = 0; i < bytes.length; i++)
      str.append((char) (bytes[i] & 0xFF));
    return str.toString();
  }

  private static String fromUtf16Be(byte[] bytes) throws IOException
  {
    if ((bytes.length & 0x01) != 0)
      throw new IOException("UTF-16 bytes are odd in length");
    StringBuffer str = new StringBuffer(bytes.length / 2);
    for (int i = 0; i < bytes.length; i += 2)
      {
        char c = (char) ((bytes[i] << 8) & 0xFF);
        c |= (char) (bytes[i+1] & 0xFF);
        str.append(c);
      }
    return str.toString();
  }

  private static String fromUtf8(byte[] bytes) throws IOException
  {
    StringBuffer str = new StringBuffer((int)(bytes.length / 1.5));
    for (int i = 0; i < bytes.length; )
      {
        char c = 0;
        if ((bytes[i] & 0xE0) == 0xE0)
          {
            if ((i + 2) >= bytes.length)
              throw new IOException("short UTF-8 input");
            c = (char) ((bytes[i++] & 0x0F) << 12);
            if ((bytes[i] & 0x80) != 0x80)
              throw new IOException("malformed UTF-8 input");
            c |= (char) ((bytes[i++] & 0x3F) << 6);
            if ((bytes[i] & 0x80) != 0x80)
              throw new IOException("malformed UTF-8 input");
            c |= (char) (bytes[i++] & 0x3F);
          }
        else if ((bytes[i] & 0xC0) == 0xC0)
          {
            if ((i + 1) >= bytes.length)
              throw new IOException("short input");
            c = (char) ((bytes[i++] & 0x1F) << 6);
            if ((bytes[i] & 0x80) != 0x80)
              throw new IOException("malformed UTF-8 input");
            c |= (char) (bytes[i++] & 0x3F);
          }
        else if ((bytes[i] & 0xFF) < 0x80)
          {
            c = (char) (bytes[i++] & 0xFF);
          }
        else
          throw new IOException("badly formed UTF-8 sequence");
        str.append(c);
      }
    return str.toString();
  }

  private Date makeTime(int tag, byte[] value) throws IOException
  {
    Calendar calendar = Calendar.getInstance();
    String str = makeString(PRINTABLE_STRING, value);

    // Classpath's SimpleDateFormat does not work for parsing these
    // types of times, so we do this by hand.
    String date = str;
    String tz = "";
    if (str.indexOf("+") > 0)
      {
        date = str.substring(0, str.indexOf("+"));
        tz = str.substring(str.indexOf("+"));
      }
    else if (str.indexOf("-") > 0)
      {
        date = str.substring(0, str.indexOf("-"));
        tz = str.substring(str.indexOf("-"));
      }
    else if (str.endsWith("Z"))
      {
        date = str.substring(0, str.length()-2);
        tz = "Z";
      }
    if (!tz.equals("Z") && tz.length() > 0)
      calendar.setTimeZone(TimeZone.getTimeZone(tz));
    else
      calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
    if ((tag & 0x1F) == UTC_TIME)
      {
        if (date.length() < 10)  // must be at least 10 chars long
          throw new DEREncodingException("cannot parse date");
        // UTCTime is of the form "yyMMddHHmm[ss](Z|(+|-)hhmm)"
        try
          {
            int year = Integer.parseInt(str.substring(0, 2));
            if (year < 50)
              year += 2000;
            else
              year += 1900;
            calendar.set(year,
              Integer.parseInt(str.substring( 2,  4))-1,  // month
              Integer.parseInt(str.substring( 4,  6)),    // day
              Integer.parseInt(str.substring( 6,  8)),    // hour
              Integer.parseInt(str.substring( 8, 10)));   // minute
            if (date.length() == 12)
              calendar.set(Calendar.SECOND,
                Integer.parseInt(str.substring(10, 12)));
          }
        catch (NumberFormatException nfe)
          {
            throw new DEREncodingException("cannot parse date");
          }
      }
    else
      {
        if (date.length() < 10)  // must be at least 10 chars long
          throw new DEREncodingException("cannot parse date");
        // GeneralTime is of the form "yyyyMMddHH[mm[ss[(.|,)SSSS]]]"
        // followed by "Z" or "(+|-)hh[mm]"
        try
          {
            calendar.set(
              Integer.parseInt(date.substring(0, 4)),      // year
              Integer.parseInt(date.substring(4, 6))-1,    // month
              Integer.parseInt(date.substring(6, 8)),      // day
              Integer.parseInt(date.substring(8, 10)), 0); // hour, min
            switch (date.length())
              {
                case 19:
                case 18:
                case 17:
                case 16:
                  calendar.set(Calendar.MILLISECOND,
                    Integer.parseInt(date.substring(15)));
                case 14:
                  calendar.set(Calendar.SECOND,
                    Integer.parseInt(date.substring(12, 14)));
                case 12:
                  calendar.set(Calendar.MINUTE,
                    Integer.parseInt(date.substring(10, 12)));
              }
          }
        catch (NumberFormatException nfe)
          {
            throw new DEREncodingException("cannot parse date");
          }
      }
    return calendar.getTime();
  }
}
