From edcb24f65cc3700e75d0a1d14dc2483f210b0ee4 Mon Sep 17 00:00:00 2001 From: Endi Sukma Dewata Date: Mon, 12 Dec 2011 22:55:14 -0600 Subject: Replaced byte-to-char & char-to-byte converters. The byte-to-char and char-to-byte converters have been replaced with a set of charsets, each having its own decoders and encoders. Ticket #3 --- pki/base/util/src/CMakeLists.txt | 39 +++-- .../netscape/security/util/ASN1CharStrConvMap.java | 190 +++++++-------------- .../security/util/ASN1CharsetProvider.java | 30 ++++ .../netscape/security/util/DerOutputStream.java | 49 ++---- .../util/src/netscape/security/util/DerValue.java | 73 ++++---- .../src/netscape/security/util/IA5Charset.java | 24 +++ .../netscape/security/util/IA5CharsetDecoder.java | 66 ++++--- .../netscape/security/util/IA5CharsetEncoder.java | 86 ++++------ .../netscape/security/util/PrintableCharset.java | 46 +++++ .../security/util/PrintableCharsetDecoder.java | 84 ++++----- .../security/util/PrintableCharsetEncoder.java | 120 ++++--------- .../netscape/security/util/UniversalCharset.java | 24 +++ .../security/util/UniversalCharsetDecoder.java | 130 +++++++------- .../security/util/UniversalCharsetEncoder.java | 78 ++++----- pki/base/util/src/netscape/security/x509/AVA.java | 42 ++--- .../netscape/security/x509/DirStrConverter.java | 83 ++++----- .../security/x509/GenericValueConverter.java | 78 ++++----- .../netscape/security/x509/IA5StringConverter.java | 44 +++-- .../security/x509/LdapV3DNStrConverter.java | 68 ++++---- .../netscape/security/x509/PrintableConverter.java | 46 +++-- 20 files changed, 637 insertions(+), 763 deletions(-) create mode 100644 pki/base/util/src/netscape/security/util/ASN1CharsetProvider.java create mode 100644 pki/base/util/src/netscape/security/util/IA5Charset.java create mode 100644 pki/base/util/src/netscape/security/util/PrintableCharset.java create mode 100644 pki/base/util/src/netscape/security/util/UniversalCharset.java (limited to 'pki') diff --git a/pki/base/util/src/CMakeLists.txt b/pki/base/util/src/CMakeLists.txt index dffa341b0..919b593e7 100644 --- a/pki/base/util/src/CMakeLists.txt +++ b/pki/base/util/src/CMakeLists.txt @@ -157,30 +157,33 @@ set(pki-nsutil_java_SRCS netscape/security/x509/PolicyConstraint.java netscape/security/x509/RevokedCertImpl.java netscape/security/x509/OtherName.java + netscape/security/util/ASN1CharsetProvider.java + netscape/security/util/ASN1CharStrConvMap.java netscape/security/util/BigInt.java + netscape/security/util/BitArray.java + netscape/security/util/ByteArrayLexOrder.java + netscape/security/util/ByteArrayTagOrder.java + netscape/security/util/CertPrettyPrint.java + netscape/security/util/CrlPrettyPrint.java + netscape/security/util/DerEncoder.java + netscape/security/util/DerInputBuffer.java + netscape/security/util/DerInputStream.java netscape/security/util/DerOutputStream.java - netscape/security/util/ASN1CharStrConvMap.java - netscape/security/util/ByteToCharUnicode.java netscape/security/util/DerValue.java - netscape/security/util/CharToByteIA5String.java - netscape/security/util/DerInputBuffer.java - netscape/security/util/CharToBytePrintable.java - netscape/security/util/ObjectIdentifier.java - netscape/security/util/DerEncoder.java netscape/security/util/ExtPrettyPrint.java - netscape/security/util/ByteArrayLexOrder.java - netscape/security/util/BitArray.java - netscape/security/util/CrlPrettyPrint.java - netscape/security/util/CertPrettyPrint.java - netscape/security/util/ByteArrayTagOrder.java - netscape/security/util/PrettyPrintResources.java + netscape/security/util/IA5Charset.java + netscape/security/util/IA5CharsetDecoder.java + netscape/security/util/IA5CharsetEncoder.java + netscape/security/util/ObjectIdentifier.java netscape/security/util/PrettyPrintFormat.java - netscape/security/util/CharToByteUniversalString.java - netscape/security/util/ByteToCharIA5String.java + netscape/security/util/PrettyPrintResources.java + netscape/security/util/PrintableCharset.java + netscape/security/util/PrintableCharsetDecoder.java + netscape/security/util/PrintableCharsetEncoder.java netscape/security/util/PubKeyPrettyPrint.java - netscape/security/util/ByteToCharPrintable.java - netscape/security/util/DerInputStream.java - netscape/security/util/ByteToCharUniversalString.java + netscape/security/util/UniversalCharset.java + netscape/security/util/UniversalCharsetDecoder.java + netscape/security/util/UniversalCharsetEncoder.java netscape/security/provider/DSA.java netscape/security/provider/DSAPrivateKey.java netscape/security/provider/DSAParameters.java diff --git a/pki/base/util/src/netscape/security/util/ASN1CharStrConvMap.java b/pki/base/util/src/netscape/security/util/ASN1CharStrConvMap.java index 4fa7b4ea4..9defa7646 100644 --- a/pki/base/util/src/netscape/security/util/ASN1CharStrConvMap.java +++ b/pki/base/util/src/netscape/security/util/ASN1CharStrConvMap.java @@ -17,16 +17,16 @@ // --- END COPYRIGHT BLOCK --- package netscape.security.util; -import java.util.Enumeration; -import java.util.Hashtable; - -import sun.io.ByteToCharConverter; -import sun.io.ByteToCharUTF8; -import sun.io.CharToByteConverter; -import sun.io.CharToByteUTF8; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CodingErrorAction; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; /** - * Maps a ASN.1 character string type to a CharToByte and ByteToChar converter. + * Maps a ASN.1 character string type to a charset encoder and decoder. * The converter is used to convert a DerValue of a ASN.1 character string type * from bytes to unicode characters and vice versa. * @@ -50,102 +50,61 @@ public class ASN1CharStrConvMap } /** - * Get a Character to Byte converter for the specified DER tag. + * Get an encoder for the specified DER tag. * * @param tag A DER tag of a ASN.1 character string type, * for example DerValue.tag_PrintableString. * - * @return A CharToByteConverter for the DER tag. - * - * @exception InstantiationException - * if error occurs when instantiating the CharToByteConverter. - * @exception IllegalAccessException - * if error occurs when loading the CharToByteConverter class. + * @return An encoder for the DER tag. */ - public CharToByteConverter getCBC(byte tag) - throws IllegalAccessException, InstantiationException - { - Byte tagObj = Byte.valueOf(tag); - CharToByteConverter cbc = null; - Class cbcClass; - cbcClass = (Class)tag2CBC.get(tagObj); - if (cbcClass == null) - return null; - cbc = (CharToByteConverter)cbcClass.newInstance(); - cbc.setSubstitutionMode(false); - return cbc; + public CharsetEncoder getEncoder(byte tag) { + Charset charset = charsets.get(tag); + if (charset == null) return null; + return charset.newEncoder(); } /** - * Get a Byte to Character converter for the given DER tag. + * Get a decoder for the given DER tag. * * @param tag A DER tag of a ASN.1 character string type, * for example DerValue.tag_PrintableString. * - * @return A ByteToCharConverter for the DER tag. - * - * @exception InstantiationException - * if error occurs when instantiationg the ByteToCharConverter. - * @exception IllegalAccessException - * if error occurs when loading the ByteToCharConverter class. + * @return A decoder for the DER tag. */ - public ByteToCharConverter getBCC(byte tag) - throws IllegalAccessException, InstantiationException - { - Byte tagObj = Byte.valueOf(tag); - ByteToCharConverter bcc = null; - Class bccClass = tag2BCC.get(tagObj); - if (bccClass == null) - return null; - bcc = (ByteToCharConverter)bccClass.newInstance(); - bcc.setSubstitutionMode(false); - return bcc; + public CharsetDecoder getDecoder(byte tag) { + Charset charset = charsets.get(tag); + if (charset == null) return null; + return charset.newDecoder(); } /** - * Add a tag-CharToByteConverter-ByteToCharConverter entry in the map. + * Add a tag-charset entry in the map. * * @param tag A DER tag of a ASN.1 character string type, * ex. DerValue.tag_IA5String - * @param cbc A CharToByteConverter for the tag. - * @param bcc A ByteToCharConverter for the tag. + * @param charset A charset for the tag. */ - @SuppressWarnings("unchecked") - public void addEntry(byte tag, Class cbc, Class bcc) - { - Class current_cbc; - Class current_bcc; - Byte tagByte = Byte.valueOf(tag); - - current_cbc = (Class)tag2CBC.get(tagByte); - current_bcc = (Class)tag2BCC.get(tagByte); - if (current_cbc != null || current_bcc != null) - { - if (current_cbc != cbc || current_bcc != bcc) - { - throw new IllegalArgumentException( - "a DER tag to converter entry already exists."); - } - else { - return; - } - } - if (!CharToByteConverter.class.isAssignableFrom(cbc) || - !ByteToCharConverter.class.isAssignableFrom(bcc)) { - throw new IllegalArgumentException( - "arguments not a CharToByteConverter or ByteToCharConverter"); - } - tag2CBC.put(tagByte, (Class) cbc); - tag2BCC.put(tagByte, (Class) bcc); - } + public void addEntry(byte tag, Charset charset) { + Charset currentCharset = charsets.get(tag); + + if (currentCharset != null) { + if (currentCharset != charset) { + throw new IllegalArgumentException( + "a DER tag to converter entry already exists."); + } else { + return; + } + } + + charsets.put(tag, charset); + } /** - * Get and enumeration of all tags in the map. - * @return An Enumeration of DER tags in the map as Bytes. + * Get an iterator of all tags in the map. + * @return An Iterator of DER tags in the map as Bytes. */ - public Enumeration getTags() - { - return tag2CBC.keys(); + public Iterator getTags() { + return charsets.keySet().iterator(); } // static public methods. @@ -173,8 +132,7 @@ public class ASN1CharStrConvMap // private methods and variables. - private Hashtable> tag2CBC = new Hashtable>(); - private Hashtable> tag2BCC = new Hashtable>(); + private Map charsets = new HashMap(); private static ASN1CharStrConvMap defaultMap; @@ -182,50 +140,28 @@ public class ASN1CharStrConvMap * Create the default converter map on initialization */ static { - defaultMap = new ASN1CharStrConvMap(); - defaultMap.addEntry(DerValue.tag_PrintableString, - PrintableCharsetEncoder.class, PrintableCharsetDecoder.class); - defaultMap.addEntry(DerValue.tag_VisibleString, - PrintableCharsetEncoder.class, PrintableCharsetDecoder.class); - defaultMap.addEntry(DerValue.tag_IA5String, - IA5CharsetEncoder.class, IA5CharsetDecoder.class); - defaultMap.addEntry(DerValue.tag_BMPString, - // Changed by bskim - //sun.io.CharToByteUnicode.class, - //netscape.security.util.ByteToCharUnicode.class); - sun.io.CharToByteUnicodeBig.class, - sun.io.ByteToCharUnicodeBig.class); - // Change end - defaultMap.addEntry(DerValue.tag_UniversalString, - UniversalCharsetEncoder.class, - UniversalCharsetDecoder.class); - // XXX this is an oversimplified implementation of T.61 strings, it - // doesn't handle all cases - defaultMap.addEntry(DerValue.tag_T61String, - latin1CBC.class, latin1BCC.class); - // UTF8String added to ASN.1 in 1998 - defaultMap.addEntry(DerValue.tag_UTF8String, - CharToByteUTF8.class, - ByteToCharUTF8.class); - defaultMap.addEntry(DerValue.tag_GeneralString, - CharToByteUTF8.class, - ByteToCharUTF8.class); + ASN1CharsetProvider provider = new ASN1CharsetProvider(); + + defaultMap = new ASN1CharStrConvMap(); + defaultMap.addEntry(DerValue.tag_PrintableString, + provider.charsetForName("ASN.1-Printable")); + defaultMap.addEntry(DerValue.tag_VisibleString, + provider.charsetForName("ASN.1-Printable")); + defaultMap.addEntry(DerValue.tag_IA5String, + provider.charsetForName("ASN.1-IA5")); + defaultMap.addEntry(DerValue.tag_BMPString, + Charset.forName("UnicodeBig")); + defaultMap.addEntry(DerValue.tag_UniversalString, + provider.charsetForName("ASN.1-Universal")); + // XXX this is an oversimplified implementation of T.61 strings, it + // doesn't handle all cases + defaultMap.addEntry(DerValue.tag_T61String, + Charset.forName("ISO-8859-1")); + // UTF8String added to ASN.1 in 1998 + defaultMap.addEntry(DerValue.tag_UTF8String, + Charset.forName("UTF-8")); + defaultMap.addEntry(DerValue.tag_GeneralString, + Charset.forName("UTF-8")); }; }; - -class latin1CBC extends sun.io.CharToByteISO8859_1 { - public latin1CBC() { - super(); - subMode = false; - } -} - -class latin1BCC extends sun.io.ByteToCharISO8859_1 { - public latin1BCC() { - super(); - subMode = false; - } -} - - diff --git a/pki/base/util/src/netscape/security/util/ASN1CharsetProvider.java b/pki/base/util/src/netscape/security/util/ASN1CharsetProvider.java new file mode 100644 index 000000000..1de1c3c48 --- /dev/null +++ b/pki/base/util/src/netscape/security/util/ASN1CharsetProvider.java @@ -0,0 +1,30 @@ +package netscape.security.util; + +import java.nio.charset.Charset; +import java.nio.charset.spi.CharsetProvider; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class ASN1CharsetProvider extends CharsetProvider { + + protected Map charsets = new HashMap(); + + public ASN1CharsetProvider() { + addCharset(new PrintableCharset()); + addCharset(new IA5Charset()); + addCharset(new UniversalCharset()); + } + + public Iterator charsets() { + return charsets.values().iterator(); + } + + public Charset charsetForName(String charsetName) { + return charsets.get(charsetName); + } + + public void addCharset(Charset cs) { + charsets.put(cs.name(), cs); + } +} diff --git a/pki/base/util/src/netscape/security/util/DerOutputStream.java b/pki/base/util/src/netscape/security/util/DerOutputStream.java index be42322fa..3348ce874 100644 --- a/pki/base/util/src/netscape/security/util/DerOutputStream.java +++ b/pki/base/util/src/netscape/security/util/DerOutputStream.java @@ -20,6 +20,10 @@ package netscape.security.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetEncoder; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; @@ -28,8 +32,6 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; -import sun.io.CharToByteConverter; - /** * Output stream marshaling DER-encoded data. This is eventually provided * in the form of a byte array; there is no advance limit on the size of @@ -541,36 +543,21 @@ extends ByteArrayOutputStream implements DerEncoder { putStringType(DerValue.tag_UTF8String, s); } - public void putStringType(byte tag, String s) throws IOException - { - int next_byte_index; - CharToByteConverter cbc; - byte buf[]; - try { - cbc = ASN1CharStrConvMap.getDefault().getCBC(tag); - if (cbc == null) - throw new IOException("No character to byte converter for tag"); - buf= new byte[cbc.getMaxBytesPerChar()*s.length()]; - // Don't use convertAll() here b/c it does not throw - // UnknownCharacterException. - next_byte_index = cbc.convert(s.toCharArray(), 0, s.length(), buf, 0, buf.length); - } - catch (java.io.CharConversionException e) { - throw new IOException("Not a valid string type "+ tag); - } - catch (IllegalAccessException e) { - throw new IOException("Cannot load CharToByteConverter class "+ - "for DER tag "+tag); - } - catch (InstantiationException e) { - throw new IOException("Cannot instantiate CharToByteConverter "+ - "class for DER tag "+tag); - } + public void putStringType(byte tag, String s) throws IOException { + try { + CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(tag); + if (encoder == null) throw new IOException("No encoder for tag"); - //next_byte_index = cbc.nextByteIndex(); - write(tag); - putLength(next_byte_index); - write(buf, 0, next_byte_index); + CharBuffer charBuffer = CharBuffer.wrap(s.toCharArray()); + ByteBuffer byteBuffer = encoder.encode(charBuffer); + + write(tag); + putLength(byteBuffer.limit()); + write(byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); + + } catch (CharacterCodingException e) { + throw new IOException("Not a valid string type "+tag, e); + } } private void put2DateBytes(byte[] buffer, int value, int offset) diff --git a/pki/base/util/src/netscape/security/util/DerValue.java b/pki/base/util/src/netscape/security/util/DerValue.java index 93ca21240..dac49a4ff 100644 --- a/pki/base/util/src/netscape/security/util/DerValue.java +++ b/pki/base/util/src/netscape/security/util/DerValue.java @@ -21,10 +21,14 @@ import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetDecoder; +import java.util.Arrays; import netscape.security.x509.AVAValueConverter; import netscape.security.x509.GenericValueConverter; -import sun.io.ByteToCharConverter; /** * Represents a single DER-encoded value. DER encoding rules are a subset @@ -198,11 +202,23 @@ public class DerValue { * @param data the DER-encoded data */ public DerValue(byte tag, byte[] data) { - this.tag = tag; - buffer = new DerInputBuffer((byte[])data.clone()); - length = data.length; - this.data = new DerInputStream (buffer); - this.data.mark (Integer.MAX_VALUE); + this.tag = tag; + buffer = new DerInputBuffer(data.clone()); + length = data.length; + this.data = new DerInputStream(buffer); + this.data.mark(Integer.MAX_VALUE); + } + + /** + * Creates a DerValue from a tag and some DER-encoded data. + * + * @param tag the DER type tag + * @param data the DER-encoded data + * @param offset offset of the data + * @param length length of the data + */ + public DerValue(byte tag, byte[] data, int offset, int length) { + this(tag, Arrays.copyOfRange(data, offset, offset+length)); } /* @@ -491,37 +507,24 @@ public class DerValue { /* * @eturns a string if the DerValue is a ASN.1 character string type and - * if there is a ByteToChar converter for the type. Returns null otherwise. + * if there is a decoder for the type. Returns null otherwise. */ - public String getASN1CharString() - throws IOException - { - ByteToCharConverter bcc; - int ret; - byte buf[]; - char cbuf[]; + public String getASN1CharString() throws IOException { + try { + CharsetDecoder decoder = ASN1CharStrConvMap.getDefault().getDecoder(tag); + if (decoder == null) return null; - try { - bcc = ASN1CharStrConvMap.getDefault().getBCC(tag); - if (bcc == null) - return null; - - buf = new byte[length]; - cbuf = new char[bcc.getMaxCharsPerByte()*length]; - data.reset(); - data.getBytes(buf); - ret = bcc.convert(buf, 0, buf.length, cbuf, 0, cbuf.length); - } - catch (java.io.CharConversionException e) { - throw new IOException("Misformed DER value"); - } - catch (IllegalAccessException e) { - throw new IOException("Illegal Access loading ByteToCharConverter"); - } - catch (InstantiationException e) { - throw new IOException("Cannot instantiate ByteToCharConverter"); - } - return new String(cbuf, 0, ret); + ByteBuffer byteBuffer = ByteBuffer.allocate(length); + + data.reset(); + data.getBytes(byteBuffer.array()); + + CharBuffer charBuffer = decoder.decode(byteBuffer); + return charBuffer.toString(); + + } catch (CharacterCodingException e) { + throw new IOException("Misformed DER value", e); + } } /** diff --git a/pki/base/util/src/netscape/security/util/IA5Charset.java b/pki/base/util/src/netscape/security/util/IA5Charset.java new file mode 100644 index 000000000..db6da2331 --- /dev/null +++ b/pki/base/util/src/netscape/security/util/IA5Charset.java @@ -0,0 +1,24 @@ +package netscape.security.util; + +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; + +public class IA5Charset extends Charset { + + public IA5Charset() { + super("ASN.1-IA5", null); + } + + public boolean contains(Charset cs) { + return false; + } + + public CharsetDecoder newDecoder() { + return new IA5CharsetDecoder(this); + } + + public CharsetEncoder newEncoder() { + return new IA5CharsetEncoder(this); + } +} diff --git a/pki/base/util/src/netscape/security/util/IA5CharsetDecoder.java b/pki/base/util/src/netscape/security/util/IA5CharsetDecoder.java index d884b9e8c..70f16a876 100644 --- a/pki/base/util/src/netscape/security/util/IA5CharsetDecoder.java +++ b/pki/base/util/src/netscape/security/util/IA5CharsetDecoder.java @@ -17,53 +17,45 @@ // --- END COPYRIGHT BLOCK --- package netscape.security.util; -import sun.io.ByteToCharConverter; -import sun.io.ConversionBufferFullException; -import sun.io.UnknownCharacterException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; /** - * Converts bytes in ASN.1 IA5String character set to unicode - * characters. + * Converts bytes in ASN.1 IA5String character set to IA5String characters. * * @author Lily Hsiao * @author Slava Galperin */ -public class IA5CharsetDecoder extends ByteToCharConverter -{ - public String getCharacterEncoding() { - return "ASN.1 IA5String"; - } +public class IA5CharsetDecoder extends CharsetDecoder { - public int convert(byte[] input, int inStart, int inEnd, - char[] output, int outStart, int outEnd) - throws ConversionBufferFullException, - UnknownCharacterException - { - int j = outStart; - for (int i = inStart; i < inEnd; i++, j++) { - if (j >= outEnd) { - byteOff = i; - charOff = j; - throw new ConversionBufferFullException(); - } - if (!subMode && (input[i] & 0x80) != 0) { - byteOff = i; - charOff = j; - badInputLength = 1; - throw new UnknownCharacterException(); - } - output[j] = (char) (input[i] & 0x7f); - } - byteOff = inEnd; - charOff = j; - return j - outStart; + public IA5CharsetDecoder(Charset cs) { + super(cs, 1, 1); } - public int flush(char[] output, int outStart, int outEnd) { - return 0; - } + protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) { + + while (true) { + + if (in.remaining() < 1) return CoderResult.UNDERFLOW; - public void reset() { } + in.mark(); + byte b = in.get(); + if (CodingErrorAction.REPORT == unmappableCharacterAction() && (b & 0x80) != 0) { + return CoderResult.unmappableForLength(1); + } + + if (out.remaining() < 1) { + in.reset(); + return CoderResult.OVERFLOW; + } + + out.put((char)(b & 0x7f)); + } + } } diff --git a/pki/base/util/src/netscape/security/util/IA5CharsetEncoder.java b/pki/base/util/src/netscape/security/util/IA5CharsetEncoder.java index 3901ec4ec..335adf71d 100644 --- a/pki/base/util/src/netscape/security/util/IA5CharsetEncoder.java +++ b/pki/base/util/src/netscape/security/util/IA5CharsetEncoder.java @@ -17,72 +17,52 @@ // --- END COPYRIGHT BLOCK --- package netscape.security.util; -import sun.io.CharToByteConverter; -import sun.io.ConversionBufferFullException; -import sun.io.UnknownCharacterException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; /** - * Converts a string of ASN.1 IA5String characters to IA5String bytes. + * Converts characters in ASN.1 IA5String character set to IA5String bytes. * * @author Lily Hsiao * @author Slava Galperin */ -public class IA5CharsetEncoder extends CharToByteConverter -{ - /* - * Returns the character set id for the conversion. - * @return the character set id. - */ - public String getCharacterEncoding () { - return "ASN.1 IA5String"; +public class IA5CharsetEncoder extends CharsetEncoder { + + public IA5CharsetEncoder(Charset cs) { + super(cs, 1, 1); } - /* + /* * Converts an array of Unicode characters into an array of IA5String - * bytes and returns the total number of characters converted. - * If conversion cannot be done, UnknownCharacterException is - * thrown. The character and byte offset will be set to the point - * of the unknown character. - * @param input character array to convert. - * @param inStart offset from which to start the conversion. - * @param inEnd where to end the conversion. - * @param output byte array to store converted bytes. - * @param outStart starting offset in the output byte array. - * @param outEnd ending offset in the output byte array. - * @return the number of characters converted. + * bytes and returns the conversion result. + * @param in input character buffer to convert. + * @param out byte buffer to store output. + * @return encoding result. */ - public int convert(char[] input, int inStart, int inEnd, - byte[] output, int outStart, int outEnd) - throws ConversionBufferFullException, - UnknownCharacterException - { - int j = outStart; - for (int i = inStart; i < inEnd; i++, j++) { - if (j >= outEnd) { - charOff = i; - byteOff = j; - throw new ConversionBufferFullException(); - } - if (!subMode && (input[i] & 0xFF80) != 0) { - charOff = i; - byteOff = j; - badInputLength = 1; - throw new UnknownCharacterException(); - } - - output[j] = (byte) (input[i] & 0x7f); - } - return j - outStart; - } + protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { - public int flush(byte[] output, int outStart, int outEnd) { - return 0; - } + while (true) { + + if (in.remaining() < 1) return CoderResult.UNDERFLOW; + + in.mark(); + char c = in.get(); + + if (CodingErrorAction.REPORT == unmappableCharacterAction() && (c & 0xFF80) != 0) { + return CoderResult.unmappableForLength(1); + } - public void reset() { } + if (out.remaining() < 1) { + in.reset(); + return CoderResult.OVERFLOW; + } - public int getMaxBytesPerChar() { - return 1; + out.put((byte)(c & 0x7f)); + } } } diff --git a/pki/base/util/src/netscape/security/util/PrintableCharset.java b/pki/base/util/src/netscape/security/util/PrintableCharset.java new file mode 100644 index 000000000..90621ccb3 --- /dev/null +++ b/pki/base/util/src/netscape/security/util/PrintableCharset.java @@ -0,0 +1,46 @@ +package netscape.security.util; + +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; + +public class PrintableCharset extends Charset { + + public PrintableCharset() { + super("ASN.1-Printable", null); + } + + public static boolean isPrintableChar(char c) { + if ((c < 'A' || c > 'Z') && + (c < 'a' || c > 'z') && + (c < '0' || c > '9') && + (c != ' ') && + (c != '\'') && + (c != '(') && + (c != ')') && + (c != '+') && + (c != ',') && + (c != '-') && + (c != '.') && + (c != '/') && + (c != ':') && + (c != '=') && + (c != '?')) { + return false; + } else { + return true; + } + } + + public boolean contains(Charset cs) { + return false; + } + + public CharsetDecoder newDecoder() { + return new PrintableCharsetDecoder(this); + } + + public CharsetEncoder newEncoder() { + return new PrintableCharsetEncoder(this); + } +} diff --git a/pki/base/util/src/netscape/security/util/PrintableCharsetDecoder.java b/pki/base/util/src/netscape/security/util/PrintableCharsetDecoder.java index 7ffd9cdc6..687366c0d 100644 --- a/pki/base/util/src/netscape/security/util/PrintableCharsetDecoder.java +++ b/pki/base/util/src/netscape/security/util/PrintableCharsetDecoder.java @@ -17,72 +17,52 @@ // --- END COPYRIGHT BLOCK --- package netscape.security.util; -import sun.io.ByteToCharConverter; -import sun.io.ConversionBufferFullException; -import sun.io.MalformedInputException; -import sun.io.UnknownCharacterException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; /** - * Converts bytes in ASN.1 Printable String character set to unicode - * characters. + * Converts bytes in ASN.1 PrintableString character set to PrintableString + * characters. * * @author Lily Hsiao * @author Slava Galperin */ -public class PrintableCharsetDecoder extends ByteToCharConverter -{ +public class PrintableCharsetDecoder extends CharsetDecoder { - public String getCharacterEncoding() - { - return "ASN.1 Printable"; + public PrintableCharsetDecoder(Charset cs) { + super(cs, 1, 1); } - public int convert(byte[] input, int inStart, int inEnd, - char[] output, int outStart, int outEnd) - throws MalformedInputException, - UnknownCharacterException, - ConversionBufferFullException - { - int j = outStart; - boolean hasNonPrintableChar = false; + protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) { - for (int i = inStart; i < inEnd; i++, j++) { - if (j >= outEnd) { - byteOff = i; - charOff = j; - throw new ConversionBufferFullException(); - } - if (!subMode && - !PrintableCharsetEncoder.isPrintableChar((char) (input[i] & 0x7f))) { - /* "bug" fix for 359010 - byteOff = i; - charOff = j; - badInputLength = 1; - throw new UnknownCharacterException(); - */ - j--; - hasNonPrintableChar = true; - } else - output[j] = (char) (input[i] & 0x7f); - } + while (true) { - if (hasNonPrintableChar == true) { - // - } + if (in.remaining() < 1) return CoderResult.UNDERFLOW; - byteOff = inEnd; - charOff = j; - return j - outStart; - } - - public int flush( char[] output, int outStart, int outEnd ) - throws MalformedInputException, ConversionBufferFullException - { - return 0; - } + in.mark(); + byte b = in.get(); + char c = (char)(b & 0x7f); - public void reset() { } + if (CodingErrorAction.REPORT == unmappableCharacterAction() && + !PrintableCharset.isPrintableChar(c)) { + /* + "bug" fix for 359010 + return CoderResult.unmappableForLength(1); + */ + continue; + } + if (out.remaining() < 1) { + in.reset(); + return CoderResult.OVERFLOW; + } + out.put(c); + } + } } diff --git a/pki/base/util/src/netscape/security/util/PrintableCharsetEncoder.java b/pki/base/util/src/netscape/security/util/PrintableCharsetEncoder.java index 351e0668e..d72f17d2d 100644 --- a/pki/base/util/src/netscape/security/util/PrintableCharsetEncoder.java +++ b/pki/base/util/src/netscape/security/util/PrintableCharsetEncoder.java @@ -17,106 +17,54 @@ // --- END COPYRIGHT BLOCK --- package netscape.security.util; -import sun.io.CharToByteConverter; -import sun.io.ConversionBufferFullException; -import sun.io.MalformedInputException; -import sun.io.UnknownCharacterException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; /** - * Converts a string of ASN.1 PrintableString characters to PrintableString + * Converts characters in ASN.1 PrintableString character set to PrintableString * bytes. * * @author Lily Hsiao * @author Slava Galperin */ -public class PrintableCharsetEncoder extends CharToByteConverter -{ - /* - * returns the character set id for the conversion. - * @return the character set id. - */ - public String getCharacterEncoding() - { - return "ASN.1 Printable"; - } +public class PrintableCharsetEncoder extends CharsetEncoder { - public static boolean isPrintableChar( char c ) - { - if ((c < 'A' || c > 'Z') && - (c < 'a' || c > 'z') && - (c < '0' || c > '9') && - (c != ' ') && - (c != '\'') && - (c != '(') && - (c != ')') && - (c != '+') && - (c != ',') && - (c != '-') && - (c != '.') && - (c != '/') && - (c != ':') && - (c != '=') && - (c != '?')) - { - return false; - } else { - return true; - } + public PrintableCharsetEncoder(Charset cs) { + super(cs, 1, 1); } - /* - * Converts an array of Unicode characters into an array of Printable - * String bytes and returns the total number of characters converted. - * If conversion cannot be done, UnknownCharacterException is - * thrown. The character and byte offset will be set to the point - * of the unknown character. - * @param input character array to convert. - * @param inStart offset from which to start the conversion. - * @param inEnd where to end the conversion. - * @param output byte array to store converted bytes. - * @param outStart starting offset in the output byte array. - * @param outEnd ending offset in the output byte array. - * @return the number of characters converted. + /* + * Converts an array of Unicode characters into an array of PrintableString + * bytes and returns the conversion result. + * @param in input character buffer to convert. + * @param out byte buffer to store output. + * @return encoding result. */ - public int convert(char[] input, int inStart, int inEnd, - byte[] output, int outStart, int outEnd) - throws MalformedInputException, UnknownCharacterException, - ConversionBufferFullException - { - int j = outStart; - int i; - for (i = inStart; i < inEnd ; i++, j++) - { - if (j >= outEnd) { - charOff = i; - byteOff = j; - throw new ConversionBufferFullException(); - } - if (!subMode && !isPrintableChar(input[i])) { - charOff = i; - byteOff = j; - badInputLength = 1; - throw new UnknownCharacterException(); - } - output[j] = (byte) (input[i] & 0x7f); - } - charOff = i; - byteOff = j; - return j - outStart; - } + protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { - public int flush(byte[] output, int outStart, int outEnd) - throws MalformedInputException, ConversionBufferFullException - { - return 0; - } + while (true) { - public void reset() { } + if (in.remaining() < 1) return CoderResult.UNDERFLOW; - public int getMaxBytesPerChar() - { - return 1; - } + in.mark(); + char c = in.get(); + + if (CodingErrorAction.REPORT == unmappableCharacterAction() && + !PrintableCharset.isPrintableChar(c)) { + return CoderResult.unmappableForLength(1); + } + if (out.remaining() < 1) { + in.reset(); + return CoderResult.OVERFLOW; + } + + out.put((byte)(c & 0x7f)); + } + } } diff --git a/pki/base/util/src/netscape/security/util/UniversalCharset.java b/pki/base/util/src/netscape/security/util/UniversalCharset.java new file mode 100644 index 000000000..59cc3c6f4 --- /dev/null +++ b/pki/base/util/src/netscape/security/util/UniversalCharset.java @@ -0,0 +1,24 @@ +package netscape.security.util; + +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; + +public class UniversalCharset extends Charset { + + public UniversalCharset() { + super("ASN.1-Universal", null); + } + + public boolean contains(Charset cs) { + return false; + } + + public CharsetDecoder newDecoder() { + return new UniversalCharsetDecoder(this); + } + + public CharsetEncoder newEncoder() { + return new UniversalCharsetEncoder(this); + } +} diff --git a/pki/base/util/src/netscape/security/util/UniversalCharsetDecoder.java b/pki/base/util/src/netscape/security/util/UniversalCharsetDecoder.java index 6a997af99..6df21e6c4 100644 --- a/pki/base/util/src/netscape/security/util/UniversalCharsetDecoder.java +++ b/pki/base/util/src/netscape/security/util/UniversalCharsetDecoder.java @@ -17,83 +17,81 @@ // --- END COPYRIGHT BLOCK --- package netscape.security.util; -import sun.io.ByteToCharConverter; -import sun.io.ConversionBufferFullException; -import sun.io.UnknownCharacterException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; /** - * Converts bytes in ASN.1 UniversalString character set to unicode + * Converts bytes in ASN.1 UniversalString character set to UniversalString * characters. * * @author Lily Hsiao * @author Slava Galperin */ -public class UniversalCharsetDecoder extends ByteToCharConverter -{ - public String getCharacterEncoding() { - return "ASN.1 UniversalString"; - } +public class UniversalCharsetDecoder extends CharsetDecoder { - public int convert(byte[] input, int inStart, int inEnd, - char[] output, int outStart, int outEnd) - throws ConversionBufferFullException, - UnknownCharacterException - { - int j = outStart; - - - int i = inStart; - while(i < inEnd) { - // XXX we do not know what to do with truly UCS-4 characters here - // we also assumed network byte order - - if ( i+3 >= inEnd || - (!((input[i] == 0 && input[i+1] == 0) || - (input[i+2] == 0 && input[i+3] == 0)))) { - byteOff = i; - charOff = j; - throw new UnknownCharacterException(); - } - if (input[i+2] == 0 && input[i+3] == 0) { - // Try to be a bit forgiving. If the byte order is - // reversed, we still try handle it. - - // Sample Date Set (1): - // 0000000 f 0 \0 \0 213 0 \0 \0 S 0 \0 \0 - // 0000014 - - // Sample Date Set (2): - // 0000000 w \0 \0 \0 w \0 \0 \0 w \0 \0 \0 . \0 \0 \0 - // 0000020 ( \0 \0 \0 t \0 \0 \0 o \0 \0 \0 b \0 \0 \0 - // 0000040 e \0 \0 \0 | \0 \0 \0 n \0 \0 \0 o \0 \0 \0 - // 0000060 t \0 \0 \0 t \0 \0 \0 o \0 \0 \0 b \0 \0 \0 - // 0000100 e \0 \0 \0 ) \0 \0 \0 . \0 \0 \0 c \0 \0 \0 - // 0000120 o \0 \0 \0 m \0 \0 \0 - // 0000130 - output[j] = (char)(((input[i+1] << 8)& 0xff00) + (input[i] & 0x00ff)); - } else { - // This should be the right order. - // - // 0000000 0000 00c4 0000 0064 0000 006d 0000 0069 - // 0000020 0000 006e 0000 0020 0000 0051 0000 0041 - // 0000040 - - // (input[i] == 0 && input[i+1] == 0) - output[j] = (char)(((input[i+2] << 8)& 0xff00) + (input[i+3] & 0x00ff)); - } - j++; - i += 4; - } - byteOff = inEnd; - charOff = j; - return j - outStart; + public UniversalCharsetDecoder(Charset cs) { + super(cs, 0.25f, 1); } - public int flush(char[] output, int outStart, int outEnd) { - return 0; - } + protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) { + + while (true) { + // XXX we do not know what to do with truly UCS-4 characters here + // we also assumed network byte order + + if (in.remaining() < 4) return CoderResult.UNDERFLOW; + + in.mark(); + byte b0 = in.get(); + byte b1 = in.get(); + byte b2 = in.get(); + byte b3 = in.get(); + + if (CodingErrorAction.REPORT == unmappableCharacterAction() && + !((b0 == 0 && b1 == 0) || (b2 == 0 && b3 == 0))) { + return CoderResult.unmappableForLength(4); + } - public void reset() { } + char c; + if (b2 == 0 && b3 == 0) { + // Try to be a bit forgiving. If the byte order is + // reversed, we still try handle it. + // Sample Date Set (1): + // 0000000 f 0 \0 \0 213 0 \0 \0 S 0 \0 \0 + // 0000014 + + // Sample Date Set (2): + // 0000000 w \0 \0 \0 w \0 \0 \0 w \0 \0 \0 . \0 \0 \0 + // 0000020 ( \0 \0 \0 t \0 \0 \0 o \0 \0 \0 b \0 \0 \0 + // 0000040 e \0 \0 \0 | \0 \0 \0 n \0 \0 \0 o \0 \0 \0 + // 0000060 t \0 \0 \0 t \0 \0 \0 o \0 \0 \0 b \0 \0 \0 + // 0000100 e \0 \0 \0 ) \0 \0 \0 . \0 \0 \0 c \0 \0 \0 + // 0000120 o \0 \0 \0 m \0 \0 \0 + // 0000130 + c = (char)(((b1 << 8) & 0xff00) + (b0 & 0x00ff)); + + } else { // (b0 == 0 && b1 == 0) + // This should be the right order. + // + // 0000000 0000 00c4 0000 0064 0000 006d 0000 0069 + // 0000020 0000 006e 0000 0020 0000 0051 0000 0041 + // 0000040 + + c = (char)(((b2 << 8) & 0xff00) + (b3 & 0x00ff)); + } + + if (out.remaining() < 1) { + in.reset(); + return CoderResult.OVERFLOW; + } + + out.put(c); + } + } } diff --git a/pki/base/util/src/netscape/security/util/UniversalCharsetEncoder.java b/pki/base/util/src/netscape/security/util/UniversalCharsetEncoder.java index 89c2a98b9..da9e6d83d 100644 --- a/pki/base/util/src/netscape/security/util/UniversalCharsetEncoder.java +++ b/pki/base/util/src/netscape/security/util/UniversalCharsetEncoder.java @@ -17,69 +17,51 @@ // --- END COPYRIGHT BLOCK --- package netscape.security.util; -import sun.io.CharToByteConverter; -import sun.io.ConversionBufferFullException; -import sun.io.UnknownCharacterException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; /** - * Converts a string of ASN.1 IA5String characters to IA5String bytes. + * Converts characters in ASN.1 UniversalString character set to UniversalString + * bytes. * * @author Lily Hsiao * @author Slava Galperin */ -public class UniversalCharsetEncoder extends CharToByteConverter -{ - /* - * Returns the character set id for the conversion. - * @return the character set id. - */ - public String getCharacterEncoding () { - return "ASN.1 UniversalString"; +public class UniversalCharsetEncoder extends CharsetEncoder { + + public UniversalCharsetEncoder(Charset cs) { + super(cs, 4, 4, new byte[] { 0, 0, 0, 0 }); } /* * Converts an array of Unicode characters into an array of UniversalString - * bytes and returns the total number of characters converted. - * If conversion cannot be done, UnknownCharacterException is - * thrown. The character and byte offset will be set to the point - * of the unknown character. - * @param input character array to convert. - * @param inStart offset from which to start the conversion. - * @param inEnd where to end the conversion. - * @param output byte array to store converted bytes. - * @param outStart starting offset in the output byte array. - * @param outEnd ending offset in the output byte array. - * @return the number of characters converted. + * bytes and returns the conversion result. + * @param in input character buffer to convert. + * @param out byte buffer to store output. + * @return encoding result. */ - public int convert(char[] input, int inStart, int inEnd, - byte[] output, int outStart, int outEnd) - throws ConversionBufferFullException, - UnknownCharacterException - { - int j = outStart; - for (int i = inStart; i < inEnd; i++) { - if (j+3 >= outEnd) { - charOff = i; - byteOff = j; - throw new ConversionBufferFullException(); - } - output[j++] = 0; - output[j++] = 0; - output[j++] = (byte) ((input[i] >> 8) & 0xff); - output[j++] = (byte) (input[i] & 0xff); - } + protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { - return j - outStart; - } + while (true) { - public int flush(byte[] output, int outStart, int outEnd) { - return 0; - } + if (in.remaining() < 1) return CoderResult.UNDERFLOW; + + in.mark(); + char c = in.get(); - public void reset() { } + if (out.remaining() < 4) { + in.reset(); + return CoderResult.OVERFLOW; + } - public int getMaxBytesPerChar() { - return 4; + out.put((byte)0); + out.put((byte)0); + out.put((byte)((c >> 8) & 0xff)); + out.put((byte)(c & 0xff)); + } } } diff --git a/pki/base/util/src/netscape/security/x509/AVA.java b/pki/base/util/src/netscape/security/x509/AVA.java index 0614f41ca..d35426d31 100644 --- a/pki/base/util/src/netscape/security/x509/AVA.java +++ b/pki/base/util/src/netscape/security/x509/AVA.java @@ -20,13 +20,17 @@ package netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.UnsupportedCharsetException; import netscape.security.util.DerEncoder; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; -import sun.io.ByteToCharConverter; /** @@ -127,28 +131,24 @@ public final class AVA implements DerEncoder * @see LdapDNStrConverter * @param in the input stream. */ - public AVA (InputStream in) throws IOException - { - StringBuffer temp = new StringBuffer (); - AVA a; - byte[] buf = new byte[in.available()]; - char[] converted_chars; - ByteToCharConverter bcc; + public AVA(InputStream in) throws IOException { + try { + // convert from UTF8 bytes to java string then parse it. + byte[] buffer = new byte[in.available()]; + in.read(buffer); - // convert from UTF8 bytes to java string then parse it. - in.read(buf); - try { - bcc = ByteToCharConverter.getConverter("UTF8"); - } - catch (java.io.UnsupportedEncodingException e) { - throw new IOException("UTF8 encoding not supported"); - } - converted_chars = bcc.convertAll(buf); - temp.append(converted_chars); + Charset charset = Charset.forName("UTF-8"); + CharsetDecoder decoder = charset.newDecoder(); - a = LdapDNStrConverter.getDefault().parseAVA(temp.toString()); - oid = a.getOid(); - value = a.getValue(); + CharBuffer charBuffer = decoder.decode(ByteBuffer.wrap(buffer)); + + AVA a = LdapDNStrConverter.getDefault().parseAVA(charBuffer.toString()); + oid = a.getOid(); + value = a.getValue(); + + } catch (UnsupportedCharsetException e) { + throw new IOException("UTF8 encoding not supported", e); + } } /** diff --git a/pki/base/util/src/netscape/security/x509/DirStrConverter.java b/pki/base/util/src/netscape/security/x509/DirStrConverter.java index 261a909d1..f6ade91aa 100644 --- a/pki/base/util/src/netscape/security/x509/DirStrConverter.java +++ b/pki/base/util/src/netscape/security/x509/DirStrConverter.java @@ -18,10 +18,13 @@ package netscape.security.x509; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetEncoder; import netscape.security.util.ASN1CharStrConvMap; import netscape.security.util.DerValue; -import sun.io.CharToByteConverter; /** * A DirStrConverter converts a string to a DerValue of ASN.1 Directory String, @@ -31,10 +34,10 @@ import sun.io.CharToByteConverter; *

The string to DerValue conversion is done as follows. * If the string has only PrintableString characters it is converted * to a ASN.1 Printable String using the PrintableString - * CharToByteConverter from the global default ASN1CharStrConvMap. + * encoder from the global default ASN1CharStrConvMap. * If it has only characters covered in the PrintableString or T.61 * character set it is converted to a ASN.1 T.61 string using the T.61 - * CharToByteConverter from the ASN1CharStrCovnMap. + * encoder from the ASN1CharStrCovnMap. * Otherwise it is converted to a ASN.1 UniversalString (UCS-4 character set) * which covers all characters. * @@ -68,7 +71,7 @@ public class DirStrConverter implements AVAValueConverter * @return a DerValue * * @exception IOException if the string cannot be converted, such as - * when a UniversalString CharToByteConverter + * when a UniversalString encoder * isn't available and the string contains * characters covered only in the universal * string (or UCS-4) character set. @@ -95,51 +98,29 @@ public class DirStrConverter implements AVAValueConverter /** * Like getValue(String) with specified DER tags as encoding order. */ - public DerValue getValue(String ds, byte[] tags) - throws IOException - { - // try to convert to printable, then t61 the universal - - // i.e. from minimal to the most liberal. - - int ret = -1; - CharToByteConverter cbc; - DerValue value; - byte[] bbuf, derBuf; - int i; - - if (tags == null || tags.length == 0) - tags = DefEncodingOrder; - - bbuf = new byte[4*ds.length()]; - for (i = 0; i < tags.length; i++) - { - try { - cbc = ASN1CharStrConvMap.getDefault().getCBC(tags[i]); - if (cbc == null) - continue; - ret = cbc.convert(ds.toCharArray(), 0, ds.length(), - bbuf, 0, bbuf.length); - break; - } - catch (java.io.CharConversionException e) { - continue; - } - catch (InstantiationException e) { - throw new IOException("Cannot instantiate CharToByteConverter"); - } - catch (IllegalAccessException e) { - throw new IOException( - "Illegal Access loading CharToByteConverter"); - } - } - if (ret == -1) { - throw new IOException( - "Cannot convert the directory string value to a ASN.1 type"); - } - - derBuf = new byte[ret]; - System.arraycopy(bbuf, 0, derBuf, 0, ret); - return new DerValue(tags[i], derBuf); + public DerValue getValue(String valueString, byte[] tags) throws IOException { + // try to convert to printable, then t61 the universal - + // i.e. from minimal to the most liberal. + + if (tags == null || tags.length == 0) tags = DefEncodingOrder; + + for (int i = 0; i < tags.length; i++) { + try { + CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(tags[i]); + if (encoder == null) continue; + + CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); + ByteBuffer byteBuffer = encoder.encode(charBuffer); + + return new DerValue(tags[i], byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); + + } catch (CharacterCodingException e) { + continue; + } + } + + throw new IOException( + "Cannot convert the directory string value to a ASN.1 type"); } /** @@ -177,7 +158,7 @@ public class DirStrConverter implements AVAValueConverter * * @param avaValue a DerValue * @return a string if the value can be converted. - * @exception IOException if a ByteToCharConverter needed for the + * @exception IOException if a decoder needed for the * conversion is not available. */ public String getAsString(DerValue avaValue) @@ -190,7 +171,7 @@ public class DirStrConverter implements AVAValueConverter avaValue.tag != DerValue.tag_T61String) throw new IllegalArgumentException( "Invalid Directory String value"); - // NOTE will return null if a ByteToCharConverter is not available. + // NOTE will return null if a decoder is not available. */ return avaValue.getASN1CharString(); } diff --git a/pki/base/util/src/netscape/security/x509/GenericValueConverter.java b/pki/base/util/src/netscape/security/x509/GenericValueConverter.java index 5c906d09f..64377e6eb 100644 --- a/pki/base/util/src/netscape/security/x509/GenericValueConverter.java +++ b/pki/base/util/src/netscape/security/x509/GenericValueConverter.java @@ -18,10 +18,13 @@ package netscape.security.x509; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetEncoder; import netscape.security.util.ASN1CharStrConvMap; import netscape.security.util.DerValue; -import sun.io.CharToByteConverter; /** * A GenericValueConverter converts a string that is not associated with @@ -30,9 +33,9 @@ import sun.io.CharToByteConverter; * Universal String. * *

The conversion is done as follows. - * A CharToByteConverter is obtained for the all the character sets + * An encoder is obtained for the all the character sets * from the global default ASN1CharStrConvMap. - * The CharToByteConverters are then used to convert the string to the + * The encoders are then used to convert the string to the * smallest character set first -- printableString. * If the string contains characters outside of that character set, * it is converted to the next character set -- IA5String character set. @@ -54,18 +57,18 @@ public class GenericValueConverter implements AVAValueConverter * as a PrintableString, IA5String, T.61String, BMPString or * UniversalString. The string is not expected to be encoded in any form. * - *

If a CharToByteConverter is not available for a character set that + *

If an encoder is not available for a character set that * is needed to convert the string, the string cannot be converted and * an IOException is thrown. For example, if the string contains characters * outside the PrintableString character and only a PrintableString - * CharToByteConverter is available then an IOException is thrown. + * encoder is available then an IOException is thrown. * * @param s A string representing a generic attribute string value. * * @return The DER value of the attribute. * * @exception IOException if the string cannot be converted, such as - * when a CharToByteConverter needed is + * when an encoder needed is * unavailable. */ public DerValue getValue(String s) @@ -74,50 +77,29 @@ public class GenericValueConverter implements AVAValueConverter return getValue(s, null); } - public DerValue getValue(String s, byte[] tags) - throws IOException - { - // try to convert to printable, then t61 the universal - - // i.e. from minimal coverage to the broadest. - int ret = -1; - CharToByteConverter cbc; - DerValue value; - byte[] bbuf, derBuf; - int i; + public DerValue getValue(String valueString, byte[] tags) throws IOException { + // try to convert to printable, then t61 the universal - + // i.e. from minimal coverage to the broadest. + + if (tags == null || tags.length == 0) tags = DefEncodingTags; + + for (int i = 0; i < tags.length; i++) { + try { + CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(tags[i]); + if (encoder == null) continue; + + CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); + ByteBuffer byteBuffer = encoder.encode(charBuffer); - if (tags == null || tags.length == 0) - tags = DefEncodingTags; + return new DerValue(tags[i], byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); - bbuf = new byte[4*s.length()]; - for (i = 0; i < tags.length; i++) - { - try { - cbc = ASN1CharStrConvMap.getDefault().getCBC(tags[i]); - if (cbc == null) - continue; - ret = cbc.convert(s.toCharArray(), 0, s.length(), - bbuf, 0, bbuf.length); - break; - } - catch (java.io.CharConversionException e) { - continue; - } - catch (InstantiationException e) { - throw new IOException("Cannot instantiate CharToByteConverter"); - } - catch (IllegalAccessException e) { - throw new IOException( - "Illegal Access loading CharToByteConverter"); - } - } - if (ret == -1) { - throw new IllegalArgumentException( - "Cannot convert the string value to a ASN.1 type"); - } + } catch (CharacterCodingException e) { + continue; + } + } - derBuf = new byte[ret]; - System.arraycopy(bbuf, 0, derBuf, 0, ret); - return new DerValue(tags[i], derBuf); + throw new IOException( + "Cannot convert the string value to a ASN.1 type"); } /** @@ -146,7 +128,7 @@ public class GenericValueConverter implements AVAValueConverter * * @param avaValue A DerValue * @return A string representing the attribute value. - * @exception IOException if a ByteToCharConverter needed for the + * @exception IOException if a decoder needed for the * conversion is not available or if BER value * is not one of the ASN1 character string types * here. diff --git a/pki/base/util/src/netscape/security/x509/IA5StringConverter.java b/pki/base/util/src/netscape/security/x509/IA5StringConverter.java index f3fa50da0..fe3e3eb18 100644 --- a/pki/base/util/src/netscape/security/x509/IA5StringConverter.java +++ b/pki/base/util/src/netscape/security/x509/IA5StringConverter.java @@ -18,10 +18,13 @@ package netscape.security.x509; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetEncoder; import netscape.security.util.ASN1CharStrConvMap; import netscape.security.util.DerValue; -import sun.io.CharToByteConverter; /** * A AVAValueConverter that converts a IA5String attribute to a DerValue @@ -49,7 +52,7 @@ public class IA5StringConverter implements AVAValueConverter * * @return a DerValue. * - * @exception IOException if a IA5String CharToByteConverter is not + * @exception IOException if a IA5String encoder is not * available for the conversion. */ public DerValue getValue(String valueString) @@ -58,29 +61,20 @@ public class IA5StringConverter implements AVAValueConverter return getValue(valueString, null); } - public DerValue getValue(String valueString, byte[] encodingOrder) - throws IOException - { - ASN1CharStrConvMap map; - CharToByteConverter cbc; - byte[] bbuf = new byte[valueString.length()]; - map = ASN1CharStrConvMap.getDefault(); - try { - cbc = map.getCBC(DerValue.tag_IA5String); - if (cbc == null) - throw new IOException("No CharToByteConverter for IA5String"); - cbc.convert(valueString.toCharArray(), 0, valueString.length(), - bbuf, 0, bbuf.length); - } - catch (java.io.CharConversionException e) { - throw new IllegalArgumentException( - "Invalid IA5String AVA Value string"); - } catch (InstantiationException e) { - throw new IOException("Cannot instantiate CharToByteConverter"); - } catch (IllegalAccessException e) { - throw new IOException("Illegal access loading CharToByteConverter"); - } - return new DerValue(DerValue.tag_IA5String, bbuf); + public DerValue getValue(String valueString, byte[] tags) throws IOException { + try { + CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(DerValue.tag_IA5String); + if (encoder == null) throw new IOException("No encoder for IA5String"); + + CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); + ByteBuffer byteBuffer = encoder.encode(charBuffer); + + return new DerValue(DerValue.tag_IA5String, + byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); + + } catch (CharacterCodingException e) { + throw new IllegalArgumentException("Invalid IA5String AVA Value string"); + } } /* diff --git a/pki/base/util/src/netscape/security/x509/LdapV3DNStrConverter.java b/pki/base/util/src/netscape/security/x509/LdapV3DNStrConverter.java index 114cc64a1..32670f672 100644 --- a/pki/base/util/src/netscape/security/x509/LdapV3DNStrConverter.java +++ b/pki/base/util/src/netscape/security/x509/LdapV3DNStrConverter.java @@ -23,11 +23,17 @@ import java.io.IOException; import java.io.PushbackReader; import java.io.StringReader; import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.UnsupportedCharsetException; +import java.util.Arrays; import java.util.Vector; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; -import sun.io.ByteToCharConverter; /** * A converter that converts Ldap v3 DN strings as specified in @@ -835,46 +841,32 @@ public class LdapV3DNStrConverter extends LdapDNStrConverter * Parse a sequence of hex pairs, each pair a UTF8 byte to a java string. * For example, "4C75C48D" is "Luc", the last c with caron. */ - protected static char[] getStringFromHexpairs(char[] hexPairs) - throws UnsupportedEncodingException - { - ByteToCharConverter utf8_bcc; - byte utf8_buf[]; - char char_buf[]; - int ret; - int i,j; + protected static char[] getStringFromHexpairs(char[] hexPairs) throws UnsupportedEncodingException { + try { + byte[] buffer = new byte[hexPairs.length/2]; + + for (int i=0; i < buffer.length; i++) { + buffer[i] = (byte) + ((Character.digit( hexPairs[i*2], 16 ) << 4) + + Character.digit( hexPairs[i*2+1], 16 )); + } - try { - utf8_bcc = ByteToCharConverter.getConverter("UTF8"); - } - catch (UnsupportedEncodingException e) { - throw new UnsupportedEncodingException( - "No UTF8 byte to char converter to use for "+ - "parsing LDAP DN String"); - } - utf8_bcc.setSubstitutionMode(false); + Charset charset = Charset.forName("UTF-8"); + CharsetDecoder decoder = charset.newDecoder(); - utf8_buf = new byte[hexPairs.length/2]; - char_buf = new char[utf8_buf.length*utf8_bcc.getMaxCharsPerByte()]; + CharBuffer charBuffer = decoder.decode(ByteBuffer.wrap(buffer)); - for ( i=0,j=0 ; i < hexPairs.length ; i++,j++ ) - { - utf8_buf[j] = (byte) - ((Character.digit( hexPairs[i++], 16 ) << 4) + - Character.digit( hexPairs[i], 16 )); - } - try { - ret = utf8_bcc.convert( utf8_buf, 0, utf8_buf.length, - char_buf, 0, char_buf.length ); - } - catch (java.io.CharConversionException e) { - throw new IllegalArgumentException( - "Invalid hex pair in LDAP DN String." ); - } + return Arrays.copyOfRange(charBuffer.array(), + charBuffer.arrayOffset(), charBuffer.arrayOffset() + charBuffer.limit()); - char [] out_buf = new char[ ret ]; - System.arraycopy( char_buf, 0, out_buf, 0, ret ); - return out_buf; - } + } catch (UnsupportedCharsetException e) { + throw new UnsupportedEncodingException( + "No UTF8 byte to char converter to use for "+ + "parsing LDAP DN String"); + } catch (CharacterCodingException e) { + throw new IllegalArgumentException( + "Invalid hex pair in LDAP DN String."); + } + } } diff --git a/pki/base/util/src/netscape/security/x509/PrintableConverter.java b/pki/base/util/src/netscape/security/x509/PrintableConverter.java index b4c58739d..b3bcd7322 100644 --- a/pki/base/util/src/netscape/security/x509/PrintableConverter.java +++ b/pki/base/util/src/netscape/security/x509/PrintableConverter.java @@ -18,10 +18,13 @@ package netscape.security.x509; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetEncoder; import netscape.security.util.ASN1CharStrConvMap; import netscape.security.util.DerValue; -import sun.io.CharToByteConverter; /** * A AVAValueConverter that converts a Printable String attribute to a DerValue @@ -48,7 +51,7 @@ public class PrintableConverter implements AVAValueConverter * * @return a DerValue. * - * @exception IOException if a Printable CharToByteConverter is not + * @exception IOException if a Printable encoder is not * available for the conversion. */ public DerValue getValue(String valueString) @@ -57,31 +60,20 @@ public class PrintableConverter implements AVAValueConverter return getValue(valueString, null); } - public DerValue getValue(String valueString, byte[] encodingOrder) - throws IOException - { - CharToByteConverter printable; - byte[] bbuf = new byte[valueString.length()]; - try { - printable = ASN1CharStrConvMap.getDefault().getCBC( - DerValue.tag_PrintableString); - if (printable == null) { - throw new IOException("No CharToByteConverter for printable"); - } - printable.convert(valueString.toCharArray(), 0, - valueString.length(), bbuf, 0, bbuf.length); - } - catch (java.io.CharConversionException e) { - throw new IllegalArgumentException( - "Invalid Printable String AVA Value"); - } - catch (InstantiationException e) { - throw new IOException("Cannot instantiate CharToByteConverter"); - } - catch (IllegalAccessException e) { - throw new IOException("Cannot load CharToByteConverter"); - } - return new DerValue(DerValue.tag_PrintableString, bbuf); + public DerValue getValue(String valueString, byte[] tags) throws IOException { + try { + CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(DerValue.tag_PrintableString); + if (encoder == null) throw new IOException("No encoder for printable"); + + CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); + ByteBuffer byteBuffer = encoder.encode(charBuffer); + + return new DerValue(DerValue.tag_PrintableString, + byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); + + } catch (CharacterCodingException e) { + throw new IllegalArgumentException("Invalid Printable String AVA Value", e); + } } /** -- cgit