/* ***************************************************************** *
 * Copyright 1998 International Business Machines Corporation. All   *
 * Rights Reserved.                                                  *
 *                                                                   *
 * Please read this carefully.  Your use of this reference           *
 * implementation of certain of the IETF public-key infrastructure   *
 * specifications ("Software") indicates your acceptance of the      *
 * following.  If you do not agree to the following, do not install  *
 * or use any of the Software.                                       *
 *                                                                   *
 * Permission to use, reproduce, distribute and create derivative    *
 * works from the Software ("Software Derivative Works"), and to     *
 * distribute such Software Derivative Works is hereby granted to    *
 * you by International Business Machines Corporation ("IBM").  This *
 * permission includes a license under the patents of IBM that are   *
 * necessarily infringed by your use of the Software as provided by  *
 * IBM.                                                              *
 *                                                                   *
 * IBM licenses the Software to you on an "AS IS" basis, without     *
 * warranty of any kind.  IBM HEREBY EXPRESSLY DISCLAIMS ALL         *
 * WARRANTIES OR CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,   *
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF       *
 * MERCHANTABILITY, NON INFRINGEMENT AND FITNESS FOR A PARTICULAR    *
 * PURPOSE.  You are solely responsible for determining the          *
 * appropriateness of using this Software and assume all risks       *
 * associated with the use of this Software, including but not       *
 * limited to the risks of program errors, damage to or loss of      *
 * data, programs or equipment, and unavailability or interruption   *
 * of operations.                                                    *
 *                                                                   *
 * IBM WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, *
 * INCIDENTAL, OR  INDIRECT DAMAGES OR FOR ANY ECONOMIC              *
 * CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), EVEN   *
 * IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  IBM  *
 * will not be liable for the loss of, or damage to, your records or *
 * data, or any damages claimed by you based on a third party claim. *
 *                                                                   *
 * IBM wishes to obtain your feedback to assist in improving the     *
 * Software.  You grant IBM a world-wide, royalty-free right to use, *
 * copy, distribute, sublicense and prepare derivative works based   *
 * upon any feedback, including materials, error corrections,        *
 * Software Derivatives, enhancements, suggestions and the like that *
 * you provide to IBM relating to the Software (this does not        *
 * include products for which you charge a royalty and distribute to *
 * IBM under other terms and conditions).                            *
 *                                                                   *
 * You agree to distribute the Software and any Software Derivatives *
 * under a license agreement that: 1) is sufficient to notify all    *
 * licensees of the Software and Software Derivatives that IBM       *
 * assumes no liability for any claim that may arise regarding the   *
 * Software or Software Derivatives, and 2) that disclaims all       *
 * warranties, both express and implied, from IBM regarding the      *
 * Software and Software Derivatives.  (If you include this          *
 * Agreement with any distribution of the Software or Software       *
 * Derivatives you will have met this requirement.)  You agree that  *
 * you will not delete any copyright notices in the Software.        *
 *                                                                   *
 * This Agreement is the exclusive statement of your rights in the   *
 * Software as provided by IBM.   Except for the rights granted to   *
 * you in the second paragraph above, You are not granted any other  *
 * patent rights, including but not limited to the right to make     *
 * combinations of the Software with products that infringe IBM      *
 * patents. You agree to comply with all applicable laws and         *
 * regulations, including all export and import laws and regulation. *
 * This Agreement is governed by the laws of the State of New York.  *
 * This Agreement supersedes all other communications,               *
 * understandings or agreements we may have had prior to this        *
 * Agreement.                                                        *
 * ***************************************************************** */

#ifndef ASN_STRINGS_H_
#define ASN_STRINGS_H_

// This module defines ASN classes concerned with storing character strings.
// It handles conversion between codesets, comparison etc.

// there is limited support for native "C" strings - A C string is assumed to have 
// a character-set that is a subset of IA5 (or more strictly, the string must contain only 
// characters from the IA5 subset of the C character-set), although the encoding of C strings
// doesn't have to be IA5.

#include <asnbase.h>

#define PRINTABLE_STRING_TAG 19
#define TELETEX_STRING_TAG 20
#define IA5_STRING_TAG 22
#define UNIVERSAL_STRING_TAG 28
// The next defs are temporary placeholders until I find the correct values
#define BMP_STRING_TAG 30
#define VISIBLE_STRING_TAG 31
#define UTF8_STRING_TAG 12

typedef struct T61codepage_struct {
  int primary;
  int supplementary;
} T61codepage_t;


int IA52T61(const r_buffer_t & src, buffer_t & dest);
int T612IA5(const r_buffer_t & src, buffer_t & dest);
int T612BMP(const r_buffer_t & src, buffer_t & dest);

int U2IA5(const r_buffer_t & src, buffer_t & dest);
int U2BMP(const r_buffer_t & src, buffer_t & dest);

int BMP2IA5(const r_buffer_t & src, buffer_t & dest);
int BMP2U(const r_buffer_t & src, buffer_t & dest);

int IA52BMP(const r_buffer_t & src, buffer_t & dest);
int IA52U(const r_buffer_t & src, buffer_t & dest);

int U2UTF8(r_buffer_t src, buffer_t & dest);
int BMP2UTF8(r_buffer_t src, buffer_t & dest);
int IA52UTF8(r_buffer_t src, buffer_t & dest);
int UTF82U(r_buffer_t src, buffer_t & dest);
int UTF82BMP(r_buffer_t src, buffer_t & dest);
int UTF82IA5(r_buffer_t src, buffer_t & dest);

unsigned char toupper_IA5(unsigned char c);
unsigned toupper_BMP(unsigned c);
uint32 toupper_UNIV(uint32 c);

class EXPORTCLASS asn_charstring : public asn_octetstring {
// asn_charstring is an abstract type that encapsulates a string potentially expressed 
// in several different codesets.
protected:
  uint32 codeset_tag;
  int set_value_uninterpreted(unsigned char * s, uint32 len);
  int set_value_uninterpreted(r_buffer_t & value);

// Returns true if the specified codeset is permitted.
// By default, codesets are named using the ASN class number that represents a 
// string written in that codeset.
  virtual bool check_codeset(uint32 codeset) const = 0;

// The following two routines update both the codeset tag and the ASN encoding tag.  
// If derived string types de-couple the encoding tag from the codeset semantics, 
// these routines must be overridden to map between the different tags.  Note that
// the routines only changes the tag(s); no codeset conversion is performed.
  virtual int set_codeset(uint32 tag);  
public:
  virtual void set_tag(uint32 tag);  

public:
  asn_charstring(security_t s = ASN_PUBLIC) : asn_octetstring(s) {};


// If an IA5 character can't be represented in a C string, it will be replaced by the 'splat'
// character.  If splat is zero, the presence of such a character will cause get_value_C to
// fail with an ASN_CANT_CONVERT status.
  virtual int get_value_C(buffer_t & s, char splat = '?') const;

  virtual int set_value_C(char * s);

// The following pairs of routines get/set the value of the charstring according
// to a string in the specified codeset.  

  virtual int get_value_IA5(buffer_t &s) const;
  virtual int set_value_IA5(char * s);
  virtual int set_value_IA5(r_buffer_t &s);

  virtual int get_value_printable(buffer_t &s) const;
  virtual int set_value_printable(char * s);
  virtual int set_value_printable(r_buffer_t &s);

  virtual int get_value_T61(buffer_t &s) const;
  virtual int set_value_T61(char * s);
  virtual int set_value_T61(r_buffer_t &s);

  virtual int get_value_BMP(buffer_t &s) const;
  virtual int set_value_BMP(uint16 * s);
  virtual int set_value_BMP(r_buffer_t &s);

  virtual int get_value_Univ(buffer_t &s) const;
  virtual int set_value_Univ(uint32 * s);
  virtual int set_value_Univ(r_buffer_t &s);

  virtual int get_value_UTF8(buffer_t &s) const;
  virtual int set_value_UTF8(char * s);
  virtual int set_value_UTF8(r_buffer_t &s);

  virtual uint32 get_codeset(void) const;
  
// The following routines attempts to convert the string to the requested codeset.
  int convert2IA5(void);
  int convert2printable(void);
  int convert2T61(void);
  int convert2BMP(void);
  int convert2Univ(void);
  int convert2UTF8(void);

  int convert2IA5(buffer_t & s) const;
  int convert2printable(buffer_t & s) const;
  int convert2T61(buffer_t & s) const;
  int convert2BMP(buffer_t & s) const;
  int convert2Univ(buffer_t & s) const;
  int convert2UTF8(buffer_t & s) const;
};


class EXPORTCLASS asn_directoryString : public asn_charstring {
protected:
  virtual bool check_type(uint32 tagRead, int classRead) const;
  virtual bool check_codeset(uint32 codeset) const;
public:
  virtual int normalize(void);
  asn_directoryString(security_t s = ASN_PUBLIC) : asn_charstring(s) {};
};


class EXPORTCLASS asn_ia5String : public asn_charstring {
protected:
  virtual bool check_codeset(uint32 codeset) const;
public:
  asn_ia5String(security_t s = ASN_PUBLIC) : asn_charstring(s) {
    asn_class = CLASS_UNIVERSAL;
    set_codeset(IA5_STRING_TAG);
  };
};


class EXPORTCLASS asn_printableString : public asn_ia5String {
protected:
  virtual bool check_codeset(uint32 codeset) const;
public:
  asn_printableString(security_t s = ASN_PUBLIC) : asn_ia5String(s) {
    asn_class = CLASS_UNIVERSAL;
    set_codeset(PRINTABLE_STRING_TAG);
  };
};

class EXPORTCLASS asn_teletexString : public asn_charstring {
protected:
  virtual bool check_codeset(uint32 codeset) const;
public:
  asn_teletexString(security_t s = ASN_PUBLIC) : asn_charstring(s) {
    asn_class = CLASS_UNIVERSAL;
    set_codeset(TELETEX_STRING_TAG);
  };
};

class EXPORTCLASS asn_bmpString : public asn_charstring {
protected:
  virtual bool check_codeset(uint32 codeset) const;
public:
  asn_bmpString(security_t s = ASN_PUBLIC) : asn_charstring(s) {
    asn_class = CLASS_UNIVERSAL;
    set_codeset(BMP_STRING_TAG);
  };
};

class EXPORTCLASS asn_universalString : public asn_charstring {
protected:
  virtual bool check_codeset(uint32 codeset) const;
public:
  asn_universalString(security_t s = ASN_PUBLIC) : asn_charstring(s) {
    asn_class = CLASS_UNIVERSAL;
    set_codeset(UNIVERSAL_STRING_TAG);
  };
};

class EXPORTCLASS asn_UTF8String : public asn_charstring {
protected:
  virtual bool check_codeset(uint32 codeset) const;
public:
  asn_UTF8String(security_t s = ASN_PUBLIC) : asn_charstring(s) {
    asn_class = CLASS_UNIVERSAL;
    set_codeset(UTF8_STRING_TAG);
  };
};


// Conversion functions to go between null-terminated arrays and the canonical big-endian
// byte array form used by the ASN classes.  The first two routines should be passed allocated
// arrays of the correct size ( (src.data_len / char_size) + 1, where char_size is 2 for BMP 
// strings and 4 for Universal strings).
EXPORTFN(int,
						 BMP2Array,
						 (r_buffer_t & src, uint16 * dst));
EXPORTFN(int,
				 Univ2Array,
				 (r_buffer_t & src, uint32 * dst));
EXPORTFN(int,
				 Array2BMP,
				 (uint16 src[], buffer_t & dst));
EXPORTFN(int,
				 Array2Univ,
				 (uint32 src[], buffer_t & dst));


#endif
