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