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