//////////////////////////////////////////////////////////////////////////// 
// 
// Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1993, 1994, 1995.
// Unpublished work.  All Rights Reserved.
// 
// The software contained on this media is the property of the
// DSTC Pty Ltd.  Use of this software is strictly in accordance
// with the license agreement in the accompanying LICENSE.DOC 
// file. If your distribution of this software does not contain 
// a LICENSE.DOC file then you have no rights to use this 
// software in any manner and should contact DSTC at the address 
// below to determine an appropriate licensing arrangement.
// 
//      DSTC Pty Ltd
//      Level 7, GP South
//      University of Queensland
//      St Lucia, 4072
//      Australia
//      Tel: +61 7 3365 4310
//      Fax: +61 7 3365 4311
//      Email: jcsi@dstc.qut.edu.au
// 
// This software is being provided "AS IS" without warranty of
// any kind.  In no event shall DSTC Pty Ltd be liable for
// damage of any kind arising out of or in connection with
// the use or performance of this software.
// 
//////////////////////////////////////////////////////////////////////////// 

package com.dstc.security.kerberos.gssapi;

import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import com.dstc.security.asn1.Constructed;

abstract class Token extends Constructed
{
  public static final String kerberosMechType = "1.2.840.113554.1.2.2";
  public static final byte[] KRB_AP_REQ = {0x01, 0x00};
  public static final byte[] KRB_AP_REP = {0x02, 0x00};
  public static final byte[] KRB_ERROR = {0x03, 0x00};
  public static final byte[] MIC = {0x01, 0x01};
  public static final byte[] DEL_CTX = {0x01, 0x02};
  public static final byte[] WRAP = {0x02, 0x01};

  protected byte[] tokenId;

  /**
   * Reads a token's bytes from an InputStream
   */
  static byte[] readToken(InputStream in) throws IOException
  {
    int length = readLength(in);
    byte data[] = new byte[length];
    in.read(data);
    return data;
  }

  /**
   * Writes the Token out to the OutputStream
   */
  void write(OutputStream os) throws IOException
  {
    os.write(this.encode());
  }

  /**
   * Returns the length of the encoding
   */
  static int readLength(InputStream in) throws IOException
  {
    byte[] temp = new byte[5];
    in.mark(5);
    in.read(temp);
    in.reset();

    byte firstOct = temp[1]; //assumes low tag number
    int tagLength = 1;

    //Check if it is an indefinite-length encoding
    if (firstOct == (byte)0x80)
    {
      return -1;
    }

    //It is definite-length. Short or long form?
    if ((firstOct & 0x80) == 0) 
    {
      //Short. Only one length octet present.
      return (tagLength + 1 + firstOct);
    } 
    else 
    {
      //Long. Additional length octets present
      int additional = firstOct & 0x7f;
      return (tagLength + 1 + additional + 
        bytesToInt(temp, tagLength + 1, additional));
    }
  } 

  /**
   * Returns the token-id for this Token
   */
  byte[] getTokenId()
  {
    return this.tokenId;
  }

  protected static void debug(String msg, byte bytes[])
  {
    System.out.print(msg);
    for (int i=0; i<bytes.length; i++)
    {
      System.out.print(java.lang.Integer.toHexString(bytes[i] & 0xff) + " ");
    }
    System.out.println(" ");
  }
}
