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 IA5String object - this is an ascii string.
10  */
11 public class DERIA5String
12     extends ASN1Primitive
13     implements ASN1String
14 {
15     private final byte[]  string;
16 
17     /**
18      * return a IA5 string from the passed in object
19      *
20      * @param obj a DERIA5String or an object that can be converted into one.
21      * @exception IllegalArgumentException if the object cannot be converted.
22      * @return a DERIA5String instance, or null.
23      */
getInstance( Object obj)24     public static DERIA5String getInstance(
25         Object  obj)
26     {
27         if (obj == null || obj instanceof DERIA5String)
28         {
29             return (DERIA5String)obj;
30         }
31 
32         if (obj instanceof byte[])
33         {
34             try
35             {
36                 return (DERIA5String)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 an IA5 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 DERIA5String instance, or null.
56      */
getInstance( ASN1TaggedObject obj, boolean explicit)57     public static DERIA5String getInstance(
58         ASN1TaggedObject obj,
59         boolean          explicit)
60     {
61         ASN1Primitive o = obj.getObject();
62 
63         if (explicit || o instanceof DERIA5String)
64         {
65             return getInstance(o);
66         }
67         else
68         {
69             return new DERIA5String(((ASN1OctetString)o).getOctets());
70         }
71     }
72 
73     /**
74      * basic constructor - with bytes.
75      * @param string the byte encoding of the characters making up the string.
76      */
DERIA5String( byte[] string)77     DERIA5String(
78         byte[]   string)
79     {
80         this.string = string;
81     }
82 
83     /**
84      * basic constructor - without validation.
85      * @param string the base string to use..
86      */
DERIA5String( String string)87     public DERIA5String(
88         String   string)
89     {
90         this(string, false);
91     }
92 
93     /**
94      * Constructor with optional validation.
95      *
96      * @param string the base string to wrap.
97      * @param validate whether or not to check the string.
98      * @throws IllegalArgumentException if validate is true and the string
99      * contains characters that should not be in an IA5String.
100      */
DERIA5String( String string, boolean validate)101     public DERIA5String(
102         String   string,
103         boolean  validate)
104     {
105         if (string == null)
106         {
107             throw new NullPointerException("string cannot be null");
108         }
109         if (validate && !isIA5String(string))
110         {
111             throw new IllegalArgumentException("string contains illegal characters");
112         }
113 
114         this.string = Strings.toByteArray(string);
115     }
116 
getString()117     public String getString()
118     {
119         return Strings.fromByteArray(string);
120     }
121 
toString()122     public String toString()
123     {
124         return getString();
125     }
126 
getOctets()127     public byte[] getOctets()
128     {
129         return Arrays.clone(string);
130     }
131 
isConstructed()132     boolean isConstructed()
133     {
134         return false;
135     }
136 
encodedLength()137     int encodedLength()
138     {
139         return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
140     }
141 
encode( ASN1OutputStream out)142     void encode(
143         ASN1OutputStream out)
144         throws IOException
145     {
146         out.writeEncoded(BERTags.IA5_STRING, string);
147     }
148 
hashCode()149     public int hashCode()
150     {
151         return Arrays.hashCode(string);
152     }
153 
asn1Equals( ASN1Primitive o)154     boolean asn1Equals(
155         ASN1Primitive o)
156     {
157         if (!(o instanceof DERIA5String))
158         {
159             return false;
160         }
161 
162         DERIA5String  s = (DERIA5String)o;
163 
164         return Arrays.areEqual(string, s.string);
165     }
166 
167     /**
168      * return true if the passed in String can be represented without
169      * loss as an IA5String, false otherwise.
170      *
171      * @param str the string to check.
172      * @return true if character set in IA5String set, false otherwise.
173      */
isIA5String( String str)174     public static boolean isIA5String(
175         String  str)
176     {
177         for (int i = str.length() - 1; i >= 0; i--)
178         {
179             char    ch = str.charAt(i);
180 
181             if (ch > 0x007f)
182             {
183                 return false;
184             }
185         }
186 
187         return true;
188     }
189 }
190