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