FileDocCategorySizeDatePackage
RFC2253Name.javaAPI DocphoneME MR2 API (J2ME)16933Wed May 02 18:00:38 BST 2007com.sun.satsa.pki

RFC2253Name

public class RFC2253Name extends Object
This class provides support for distinguished name formatted according to RFC 2253.

Fields Summary
private static final String
specialChars2253
In RFC2253, if the value has any of these characters in it, it must be quoted by a preceding \.
private static final byte[]
dcOID
DomainComponent type OID.
private static String[]
names
Component type names.
private static byte[]
OIDs
Component type OIDs.
private String
src
Original name.
private int
index
Current offset in the name.
private boolean
complete
Is RelativeDistinguishedName complete?
private boolean
encoded
Is value hex encoded (starts with #)?
private StringBuffer
tmp
Temporary string buffer for parser.
Constructors Summary
private RFC2253Name(String name)
Creates a new RFC2253Name instance.

param
name distinguished name

        src = name;
    
Methods Summary
public static java.lang.StringNameToString(TLV name)
Returns string representation for parsed RFC2253 name.

param
name the name
return
string representation of the name or null in case of error


        try {
            String result = "";
            name = name.child;
            while (name != null) {

                String s = "";
                TLV rdn = name.child;
                name = name.next;

                while (rdn != null) {

                    if (s.length() != 0) {
                        s = s + " + ";
                    }

                    TLV t = rdn.child;
                    rdn = rdn.next;

                    boolean encodeValue = true;

                    for (int i = 0; i < OIDs.length; i++) {
                        if (Utils.byteMatch(OIDs[i], 0, OIDs[i].length,
                                     t.data, t.valueOffset, t.length)) {
                            s += names[i];
                            encodeValue = false;
                            break;
                        }
                    }

                    if (encodeValue) {
                        s += "OID." + Utils.OIDtoString(t.data,
                                               t.valueOffset, t.length);
                    }

                    t = t.next;

                    String value;
                    try {
                        value = new String(t.data, t.valueOffset,
                                           t.length, Utils.utf8);
                    } catch (UnsupportedEncodingException uee) {
                        encodeValue = true;
                        value = null;
                    }

                    if (encodeValue) {
                        byte[] data = t.getDERData();
                        value = "#" + Utils.hexNumber(data, 0, data.length);
                    } else {
                        boolean special = value.startsWith(" ") ||
                                value.startsWith("#") ||
                                value.endsWith(" ");
                        for (int i = 0; i < specialChars2253.length(); i++) {
                            special |= value.indexOf(
                                       specialChars2253.charAt(i)) > -1;
                        }

                        if (special) {
                            int i = value.length();
                            while (i-- > 0) {
                                char c = value.charAt(i);
                                if (c == '"" || c == '\\") {
                                    value = value.substring(0, i) + "\\" +
                                            value.substring(i);
                                }
                            }
                            value = "\"" + value + "\"";
                        }

                        int i = value.length();
                        while (i-- > 0) {
                            char c = value.charAt(i);
                            if (c > -1 && c < 32) {
                                value = value.substring(0, i) +
                                        "\\" + Utils.hexByte(c) +
                                        value.substring(i + 1);
                            }
                        }
                    }
                    s += "=" + value;
                }
                result = result.length() == 0 ? s : s + ", " + result;
            }
            return result;
        } catch (NullPointerException npe) {
            return null;
        } catch (IndexOutOfBoundsException iobe) {
            return null;
        } catch (IllegalArgumentException iae) {
            return null;
        }
    
public static booleancompare(TLV name1, TLV name2)
Compares two names in TLV form.

param
name1 the 1st name
param
name2 the 2nd name
return
true if the names are equal
exception
IllegalArgumentException in case of any error


        try {
            TLV set1 = name1.child;
            TLV set2 = name2.child;
    
            while (true) {
    
                if (set1 == null || set2 == null) {
                    return (set1 == set2);
                }
    
                TLV seq1 = set1.child;
                TLV seq2 = set2.child;
    
                while (true) {
    
                    if (seq1 == null && seq2 == null) {
                        break;
                    }
    
                    if (seq1 == null || seq2 == null) {
                        return false;
                    }
    
                    TLV v1 = seq1.child;
                    TLV v2 = seq2.child;
    
                    if (! v1.match(v2)) {
                        return false;
                    }
    
                    v1 = v1.next;
                    v2 = v2.next;
    
                    if (! (v1.match(v2) || stringsMatch(v1, v2))) {
                        return false;
                    }
    
                    seq1 = seq1.next;
                    seq2 = seq2.next;
                }
    
                set1 = set1.next;
                set2 = set2.next;
            }
        } catch (IllegalArgumentException iae) {
            throw iae;
        } catch (NullPointerException npe) {
            throw new IllegalArgumentException("Invalid TLV");
        } catch (IndexOutOfBoundsException iobe) {
            throw new IllegalArgumentException("Invalid TLV");
        }
    
private TLVencode()
Parses the name and returns TLV object.

return
DER encoded name


        if (src == null || src.trim().length() == 0) {
            throw new IllegalArgumentException();
        }

        ByteArrayOutputStream buf = null;
        TLV atvSet = null;
        TLV atvSetTail = null;
        TLV rdnSequence = null;

        while (index < src.length()) {

            String id = getName();
            String s = getValue();

            int i = -1;
            for (int j = 0; j < names.length; j++) {
                if (id.equals(names[j])) {
                    i = j;
                    break;
                }
            }

            TLV type;

            if (i == -1) {
                if (id.startsWith("OID.")) {
                    id = id.substring(4);
                }
                type = TLV.createOID(id);
            } else {
                type = new TLV(TLV.OID_TYPE, OIDs[i]);
            }

            TLV value = null;

            if (encoded) {

                if (buf == null) {
                    buf = new ByteArrayOutputStream(s.length() / 2);
                } else {
                    buf.reset();
                }

                for (i = 0; i < s.length(); i += 2) {
                    buf.write(Integer.parseInt(s.substring(i, i + 2), 16));
                }

                value = new TLV(buf.toByteArray(), 0);
                if (value.getDERSize() != (s.length() + 1) / 2) {
                    throw new IllegalArgumentException();
                }

            } else {
                byte[] typeOID = type.getValue();
                if (Utils.byteMatch(dcOID, 0, dcOID.length, 
                                    typeOID, 0, typeOID.length)) {
                    value = TLV.createIA5String(s);
                } else {
                    value = TLV.createUTF8String(s);
                }
            }

            TLV tv = TLV.createSequence();
            tv.setChild(type).setNext(value);

            if (atvSet == null) {
                atvSet = tv;
            } else {
                atvSetTail.setNext(tv);
            }
            atvSetTail = tv;

            if (complete) {
                TLV set = new TLV(TLV.SET_TYPE);
                set.setChild(atvSet);
                set.setNext(rdnSequence);
                rdnSequence = set;
                atvSet = null;
            }
        }

        if (! complete) {
            throw new IllegalArgumentException();
        }

        TLV name = TLV.createSequence();
        name.setChild(rdnSequence);

        return name;
    
private static char[]getChars(TLV v)
Returns array of characters for comparison.

param
v attribute value
return
array of characters
throws
IllegalArgumentException if conversion to utf-8 fails


        try {
            return (new String(v.data, v.valueOffset, v.length, Utils.utf8)).
                    trim().toUpperCase().toCharArray();
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException("invalid encoding");
        }
    
private java.lang.StringgetName()
Returns the next attribute name.

return
name


        int i = index;
        index = src.indexOf('=", index);
        if (index == -1) {
            throw new IllegalArgumentException();
        }
        return src.substring(i, index++).trim().toUpperCase();
    
private java.lang.StringgetValue()
Returns the next attribute value.

return
attribute value


        tmp.delete(0, tmp.length());
        complete = true;
        encoded = false;
        boolean quote = false;
        int expectedLength = -1;
        boolean firstSpace = false;

        while (index < src.length()) {

            char c = src.charAt(index++);

            if (c == '\"") {
                if (quote) {
                    expectedLength = tmp.length();
                } else
                if (tmp.length() != 0) {
                    throw new IllegalArgumentException();
                }
                quote = ! quote;
                continue;
            }

            if (! quote && tmp.length() == 0) {
                if (c == ' ") {
                    continue;
                }
                if (c == '#") {
                    encoded = true;
                    continue;
                }
            }

            if (c == '\\") {

                c = src.charAt(index++);

                if (c == '#" || specialChars2253.indexOf(c) != -1) {
                    tmp.append(c);
                    continue;
                }

                if (! quote && c == ' ") {
                    if (expectedLength > 1) {
                        // only the 1st and the last space can be escaped
                        throw new IllegalArgumentException();
                    }
                    tmp.append(c);
                    expectedLength = tmp.length();
                    firstSpace = (tmp.length() == 1);
                    continue;
                }

                tmp.append((char) Integer.parseInt(
                        src.substring(index - 1, index + 1), 16));
                index++;
                continue;
            }

            if (! quote && (specialChars2253.indexOf(c) != -1)) {
                if (c == '," || c == ';") {
                    if (index == src.length()) {
                        throw new IllegalArgumentException();
                    }
                    break;
                }
                if (c == '+") {
                    complete = false;
                    break;
                }
                throw new IllegalArgumentException();
            }

            tmp.append(c);
        }

        if (quote) {
            throw new IllegalArgumentException();
        }

        int i = tmp.length();
        while (i > 0 && i-- > expectedLength && tmp.charAt(i) == ' ") {
            tmp.deleteCharAt(i);
        }

        if (! (expectedLength == -1 || firstSpace ||
            tmp.length() == expectedLength)) {
            throw new IllegalArgumentException();
        }

        return tmp.toString();
    
private static booleanstringsMatch(TLV v1, TLV v2)
Compares two attribute values ignoring multiple spaces and register.

param
v1 1st attribute value
param
v2 2nd attribute value
return
true if equal


        if (! (v1.isString() && v2.isString())) {
            return false;
        }

        char[] c1 = getChars(v1);
        char[] c2 = getChars(v2);

        int i1 = 0;
        int i2 = 0;

        while (true) {

            if (i1 == c1.length || i2 == c2.length) {
                return (i1 == c1.length && i2 == c2.length);
            }

            while (c1[i1] == ' " && c1[i1 + 1] == ' ") {
                i1++;
            }

            while (c2[i2] == ' " && c2[i2 + 1] == ' ") {
                i2++;
            }

            if (c1[i1++] != c2[i2++]) {
                return false;
            }
        }
    
public static byte[]toDER(java.lang.String name)
This method converts distinguished name from string to DER encoding.

param
name distinguished name
return
DER encoded name
throws
IllegalArgumentException on any error.


                                
         

        try {
            return new RFC2253Name(name).encode().getDERData();
        } catch (TLVException tlve) {
            throw new IllegalArgumentException(name);
        } catch (StringIndexOutOfBoundsException siobe) {
            throw new IllegalArgumentException(name);
        } catch (IllegalArgumentException iae) {
            throw new IllegalArgumentException(name);
        }
    
public static TLVtoTLV(java.lang.String name)
This method converts distinguished name from string to TLV object.

param
name distinguished name
return
DER encoded name
throws
IllegalArgumentException on any error.


        try {
            return new RFC2253Name(name).encode();
        } catch (TLVException e) {
            throw new IllegalArgumentException(name);
        } catch (StringIndexOutOfBoundsException siobe) {
            throw new IllegalArgumentException(name);
        } catch (IllegalArgumentException iae) {
            throw new IllegalArgumentException(name);
        }