Home | History | Annotate | Download | only in asn1
      1 package org.bouncycastle.asn1;
      2 
      3 import java.io.IOException;
      4 
      5 import org.bouncycastle.util.Arrays;
      6 import org.bouncycastle.util.Strings;
      7 
      8 /**
      9  * DER PrintableString object.
     10  */
     11 public class DERPrintableString
     12     extends ASN1Primitive
     13     implements ASN1String
     14 {
     15     private final byte[]  string;
     16 
     17     /**
     18      * return a printable string from the passed in object.
     19      *
     20      * @param obj a DERPrintableString or an object that can be converted into one.
     21      * @exception IllegalArgumentException if the object cannot be converted.
     22      * @return a DERPrintableString instance, or null.
     23      */
     24     public static DERPrintableString getInstance(
     25         Object  obj)
     26     {
     27         if (obj == null || obj instanceof DERPrintableString)
     28         {
     29             return (DERPrintableString)obj;
     30         }
     31 
     32         if (obj instanceof byte[])
     33         {
     34             try
     35             {
     36                 return (DERPrintableString)fromByteArray((byte[])obj);
     37             }
     38             catch (Exception e)
     39             {
     40                 throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
     41             }
     42         }
     43 
     44         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
     45     }
     46 
     47     /**
     48      * return a Printable String from a tagged object.
     49      *
     50      * @param obj the tagged object holding the object we want
     51      * @param explicit true if the object is meant to be explicitly
     52      *              tagged false otherwise.
     53      * @exception IllegalArgumentException if the tagged object cannot
     54      *               be converted.
     55      * @return a DERPrintableString instance, or null.
     56      */
     57     public static DERPrintableString getInstance(
     58         ASN1TaggedObject obj,
     59         boolean          explicit)
     60     {
     61         ASN1Primitive o = obj.getObject();
     62 
     63         if (explicit || o instanceof DERPrintableString)
     64         {
     65             return getInstance(o);
     66         }
     67         else
     68         {
     69             return new DERPrintableString(ASN1OctetString.getInstance(o).getOctets());
     70         }
     71     }
     72 
     73     /**
     74      * basic constructor - byte encoded string.
     75      */
     76     DERPrintableString(
     77         byte[]   string)
     78     {
     79         this.string = string;
     80     }
     81 
     82     /**
     83      * basic constructor - this does not validate the string
     84      */
     85     public DERPrintableString(
     86         String   string)
     87     {
     88         this(string, false);
     89     }
     90 
     91     /**
     92      * Constructor with optional validation.
     93      *
     94      * @param string the base string to wrap.
     95      * @param validate whether or not to check the string.
     96      * @throws IllegalArgumentException if validate is true and the string
     97      * contains characters that should not be in a PrintableString.
     98      */
     99     public DERPrintableString(
    100         String   string,
    101         boolean  validate)
    102     {
    103         if (validate && !isPrintableString(string))
    104         {
    105             throw new IllegalArgumentException("string contains illegal characters");
    106         }
    107 
    108         this.string = Strings.toByteArray(string);
    109     }
    110 
    111     public String getString()
    112     {
    113         return Strings.fromByteArray(string);
    114     }
    115 
    116     public byte[] getOctets()
    117     {
    118         return Arrays.clone(string);
    119     }
    120 
    121     boolean isConstructed()
    122     {
    123         return false;
    124     }
    125 
    126     int encodedLength()
    127     {
    128         return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
    129     }
    130 
    131     void encode(
    132         ASN1OutputStream out)
    133         throws IOException
    134     {
    135         out.writeEncoded(BERTags.PRINTABLE_STRING, string);
    136     }
    137 
    138     public int hashCode()
    139     {
    140         return Arrays.hashCode(string);
    141     }
    142 
    143     boolean asn1Equals(
    144         ASN1Primitive o)
    145     {
    146         if (!(o instanceof DERPrintableString))
    147         {
    148             return false;
    149         }
    150 
    151         DERPrintableString  s = (DERPrintableString)o;
    152 
    153         return Arrays.areEqual(string, s.string);
    154     }
    155 
    156     public String toString()
    157     {
    158         return getString();
    159     }
    160 
    161     /**
    162      * return true if the passed in String can be represented without
    163      * loss as a PrintableString, false otherwise.
    164      *
    165      * @return true if in printable set, false otherwise.
    166      */
    167     public static boolean isPrintableString(
    168         String  str)
    169     {
    170         for (int i = str.length() - 1; i >= 0; i--)
    171         {
    172             char    ch = str.charAt(i);
    173 
    174             if (ch > 0x007f)
    175             {
    176                 return false;
    177             }
    178 
    179             if ('a' <= ch && ch <= 'z')
    180             {
    181                 continue;
    182             }
    183 
    184             if ('A' <= ch && ch <= 'Z')
    185             {
    186                 continue;
    187             }
    188 
    189             if ('0' <= ch && ch <= '9')
    190             {
    191                 continue;
    192             }
    193 
    194             switch (ch)
    195             {
    196             case ' ':
    197             case '\'':
    198             case '(':
    199             case ')':
    200             case '+':
    201             case '-':
    202             case '.':
    203             case ':':
    204             case '=':
    205             case '?':
    206             case '/':
    207             case ',':
    208                 continue;
    209             }
    210 
    211             return false;
    212         }
    213 
    214         return true;
    215     }
    216 }
    217