001: package org.bouncycastle.asn1;
002:
003: import java.io.IOException;
004:
005: /**
006: * DER PrintableString object.
007: */
008: public class DERPrintableString extends ASN1Object implements DERString {
009: String string;
010:
011: /**
012: * return a printable string from the passed in object.
013: *
014: * @exception IllegalArgumentException if the object cannot be converted.
015: */
016: public static DERPrintableString getInstance(Object obj) {
017: if (obj == null || obj instanceof DERPrintableString) {
018: return (DERPrintableString) obj;
019: }
020:
021: if (obj instanceof ASN1OctetString) {
022: return new DERPrintableString(((ASN1OctetString) obj)
023: .getOctets());
024: }
025:
026: if (obj instanceof ASN1TaggedObject) {
027: return getInstance(((ASN1TaggedObject) obj).getObject());
028: }
029:
030: throw new IllegalArgumentException(
031: "illegal object in getInstance: "
032: + obj.getClass().getName());
033: }
034:
035: /**
036: * return a Printable String from a tagged object.
037: *
038: * @param obj the tagged object holding the object we want
039: * @param explicit true if the object is meant to be explicitly
040: * tagged false otherwise.
041: * @exception IllegalArgumentException if the tagged object cannot
042: * be converted.
043: */
044: public static DERPrintableString getInstance(ASN1TaggedObject obj,
045: boolean explicit) {
046: return getInstance(obj.getObject());
047: }
048:
049: /**
050: * basic constructor - byte encoded string.
051: */
052: public DERPrintableString(byte[] string) {
053: char[] cs = new char[string.length];
054:
055: for (int i = 0; i != cs.length; i++) {
056: cs[i] = (char) (string[i] & 0xff);
057: }
058:
059: this .string = new String(cs);
060: }
061:
062: /**
063: * basic constructor - this does not validate the string
064: */
065: public DERPrintableString(String string) {
066: this (string, false);
067: }
068:
069: /**
070: * Constructor with optional validation.
071: *
072: * @param string the base string to wrap.
073: * @param validate whether or not to check the string.
074: * @throws IllegalArgumentException if validate is true and the string
075: * contains characters that should not be in a PrintableString.
076: */
077: public DERPrintableString(String string, boolean validate) {
078: if (validate && !isPrintableString(string)) {
079: throw new IllegalArgumentException(
080: "string contains illegal characters");
081: }
082:
083: this .string = string;
084: }
085:
086: public String getString() {
087: return string;
088: }
089:
090: public byte[] getOctets() {
091: char[] cs = string.toCharArray();
092: byte[] bs = new byte[cs.length];
093:
094: for (int i = 0; i != cs.length; i++) {
095: bs[i] = (byte) cs[i];
096: }
097:
098: return bs;
099: }
100:
101: void encode(DEROutputStream out) throws IOException {
102: out.writeEncoded(PRINTABLE_STRING, this .getOctets());
103: }
104:
105: public int hashCode() {
106: return this .getString().hashCode();
107: }
108:
109: boolean asn1Equals(DERObject o) {
110: if (!(o instanceof DERPrintableString)) {
111: return false;
112: }
113:
114: DERPrintableString s = (DERPrintableString) o;
115:
116: return this .getString().equals(s.getString());
117: }
118:
119: public String toString() {
120: return string;
121: }
122:
123: /**
124: * return true if the passed in String can be represented without
125: * loss as a PrintableString, false otherwise.
126: *
127: * @return true if in printable set, false otherwise.
128: */
129: public static boolean isPrintableString(String str) {
130: for (int i = str.length() - 1; i >= 0; i--) {
131: char ch = str.charAt(i);
132:
133: if (ch > 0x007f) {
134: return false;
135: }
136:
137: if ('a' <= ch && ch <= 'z') {
138: continue;
139: }
140:
141: if ('A' <= ch && ch <= 'Z') {
142: continue;
143: }
144:
145: if ('0' <= ch && ch <= '9') {
146: continue;
147: }
148:
149: switch (ch) {
150: case ' ':
151: case '\'':
152: case '(':
153: case ')':
154: case '+':
155: case '-':
156: case '.':
157: case ':':
158: case '=':
159: case '?':
160: case '/':
161: case ',':
162: continue;
163: }
164:
165: return false;
166: }
167:
168: return true;
169: }
170: }
|