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