1package org.bouncycastle.asn1; 2 3import java.io.IOException; 4 5/** 6 * DER PrintableString object. 7 */ 8public 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