?? ava.java
字號(hào):
/* * @(#)AVA.java 1.35 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */package sun.security.x509;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.OutputStream;import java.io.Reader;import java.util.Map;import java.util.HashMap;import java.util.ArrayList;import java.util.Locale;import sun.text.Normalizer;import sun.security.util.*;import sun.security.pkcs.PKCS9Attribute;/** * X.500 Attribute-Value-Assertion (AVA): an attribute, as identified by * some attribute ID, has some particular value. Values are as a rule ASN.1 * printable strings. A conventional set of type IDs is recognized when * parsing (and generating) RFC 1779 or RFC 2253 syntax strings. * * <P>AVAs are components of X.500 relative names. Think of them as being * individual fields of a database record. The attribute ID is how you * identify the field, and the value is part of a particular record. * <p> * Note that instances of this class are immutable. * * @see X500Name * @see RDN * * @version 1.35, 10/10/06 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */public class AVA implements DerEncoder { private static final Debug debug = Debug.getInstance("x509", "\t[AVA]"); /** * DEFAULT format allows both RFC1779 and RFC2253 syntax and * additional keywords. */ final static int DEFAULT = 1; /** * RFC1779 specifies format according to RFC1779. */ final static int RFC1779 = 2; /** * RFC2253 specifies format according to RFC2253. */ final static int RFC2253 = 3; // currently not private, accessed directly from RDN final ObjectIdentifier oid; final DerValue value; /* * If the value has any of these characters in it, it must be quoted. * Backslash and quote characters must also be individually escaped. * Leading and trailing spaces, also multiple internal spaces, also * call for quoting the whole string. */ private static final String specialChars = ",+=\n<>#;"; /* * In RFC2253, if the value has any of these characters in it, it * must be quoted by a preceding \. */ private static final String specialChars2253 = ",+\"\\<>;"; /* * includes special chars from RFC1779 and RFC2253, as well as ' ' */ private static final String specialCharsAll = ",=\n+<>#;\\\" "; /* * Values that aren't printable strings are emitted as BER-encoded * hex data. */ private static final String hexDigits = "0123456789ABCDEF"; public AVA(ObjectIdentifier type, DerValue val) { if ((type == null) || (val == null)) { throw new NullPointerException(); } oid = type; value = val; } /** * Parse an RFC 1779 or RFC 2253 style AVA string: CN=fee fie foe fum * or perhaps with quotes. Not all defined AVA tags are supported; * of current note are X.400 related ones (PRMD, ADMD, etc). * * This terminates at unescaped AVA separators ("+") or RDN * separators (",", ";"), or DN terminators (">"), and removes * cosmetic whitespace at the end of values. */ AVA(Reader in) throws IOException { this(in, DEFAULT); } /** * Parse an AVA string formatted according to format. * * NOTE: format RFC1779 should only allow RFC1779 syntax but is * actually DEFAULT with RFC1779 keywords. */ AVA(Reader in, int format) throws IOException { // assume format is one of DEFAULT, RFC1779, RFC2253 StringBuffer temp = new StringBuffer(); int c; /* * First get the keyword indicating the attribute's type, * and map it to the appropriate OID. */ while (true) { c = readChar(in, "Incorrect AVA format"); if (c == '=') { break; } temp.append((char)c); } oid = AVAKeyword.getOID(temp.toString(), format); /* * Now parse the value. "#hex", a quoted string, or a string * terminated by "+", ",", ";", ">". Whitespace before or after * the value is stripped away unless format is RFC2253. */ temp.setLength(0); if (format == RFC2253) { // read next character c = in.read(); if (c == ' ') { throw new IOException("Incorrect AVA RFC2253 format - " + "leading space must be escaped"); } // read next character skipping whitespace do { c = in.read(); } while ((c == ' ') || (c == '\n')); } if (c == -1) { // empty value value = new DerValue(""); return; } if (c == '#') { value = parseHexString(in, format); } else if ((c == '"') && (format != RFC2253)) { value = parseQuotedString(in, temp); } else { value = parseString(in, c, format, temp); } } /** * Get the ObjectIdentifier of this AVA. */ public ObjectIdentifier getObjectIdentifier() { return oid; } /** * Get the value of this AVA as a DerValue. */ public DerValue getDerValue() { return value; } /** * Get the value of this AVA as a String. * * @exception RuntimeException if we could not obtain the string form * (should not occur) */ public String getValueString() { try { String s = value.getAsString(); if (s == null) { throw new RuntimeException("AVA string is null"); } return s; // should not occur throw new RuntimeException("AVA error: " + e, e); } } private static DerValue parseHexString (Reader in, int format) throws IOException { int c; ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte b = 0; int cNdx = 0; while (true) { c = in.read(); if (isTerminator(c, format)) { break; } int cVal = hexDigits.indexOf(Character.toUpperCase((char)c)); if (cVal == -1) { throw new IOException("AVA parse, invalid hex " + "digit: "+ (char)c); } if ((cNdx % 2) == 1) { b = (byte)((b * 16) + (byte)(cVal)); baos.write(b); } else { b = (byte)(cVal); } cNdx++; } // throw exception if no hex digits if (cNdx == 0) { throw new IOException("AVA parse, zero hex digits"); } // throw exception if odd number of hex digits if (cNdx % 2 == 1) { throw new IOException("AVA parse, odd number of hex digits"); } return new DerValue(baos.toByteArray()); } private DerValue parseQuotedString (Reader in, StringBuffer temp) throws IOException { // RFC1779 specifies that an entire RDN may be enclosed in double // quotes. In this case the syntax is any sequence of // backslash-specialChar, backslash-backslash, // backslash-doublequote, or character other than backslash or // doublequote. int c = readChar(in, "Quoted string did not end in quote"); ArrayList embeddedHex = new ArrayList(); boolean isPrintableString = true; while (c != '"') { if (c == '\\') { c = readChar(in, "Quoted string did not end in quote"); // check for embedded hex pairs Byte hexByte = null; if ((hexByte = getEmbeddedHexPair(c, in)) != null) { // always encode AVAs with embedded hex as UTF8 isPrintableString = false; // append consecutive embedded hex // as single string later embeddedHex.add(hexByte); c = in.read(); continue; } if (c != '\\' && c != '"' && specialChars.indexOf((char)c) < 0) { throw new IOException ("Invalid escaped character in AVA: " + (char)c); } } // add embedded hex bytes before next char if (embeddedHex.size() > 0) { String hexString = getEmbeddedHexString(embeddedHex); temp.append(hexString); embeddedHex.clear(); } // check for non-PrintableString chars isPrintableString &= DerValue.isPrintableStringChar((char)c); temp.append((char)c); c = readChar(in, "Quoted string did not end in quote"); } // add trailing embedded hex bytes if (embeddedHex.size() > 0) { String hexString = getEmbeddedHexString(embeddedHex); temp.append(hexString); embeddedHex.clear(); } do { c = in.read(); } while ((c == '\n') || (c == ' ')); if (c != -1) { throw new IOException("AVA had characters other than " + "whitespace after terminating quote"); } // encode as PrintableString unless value contains // non-PrintableString chars if (this.oid.equals(PKCS9Attribute.EMAIL_ADDRESS_OID)) { // EmailAddress must be IA5String return new DerValue(DerValue.tag_IA5String, temp.toString().trim()); } else if (isPrintableString) { return new DerValue(temp.toString().trim()); } else { return new DerValue(DerValue.tag_UTF8String, temp.toString().trim()); } } private DerValue parseString (Reader in, int c, int format, StringBuffer temp) throws IOException { ArrayList embeddedHex = new ArrayList(); boolean isPrintableString = true; boolean escape = false; boolean leadingChar = true; int spaceCount = 0; do { escape = false; if (c == '\\') { escape = true; c = readChar(in, "Invalid trailing backslash"); // check for embedded hex pairs Byte hexByte = null; if ((hexByte = getEmbeddedHexPair(c, in)) != null) { // always encode AVAs with embedded hex as UTF8 isPrintableString = false; // append consecutive embedded hex // as single string later embeddedHex.add(hexByte); c = in.read(); leadingChar = false; continue; } // check if character was improperly escaped if ((format == DEFAULT && specialCharsAll.indexOf((char)c) == -1) || (format == RFC1779 && specialChars.indexOf((char)c) == -1 && c != '\\' && c != '\"')) { throw new IOException ("Invalid escaped character in AVA: '" + (char)c + "'"); } else if (format == RFC2253) { if (c == ' ') { // only leading/trailing space can be escaped if (!leadingChar && !trailingSpace(in)) { throw new IOException ("Invalid escaped space character " + "in AVA. Only a leading or trailing " + "space character can be escaped."); } } else if (c == '#') { // only leading '#' can be escaped if (!leadingChar) { throw new IOException ("Invalid escaped '#' character in AVA. " + "Only a leading '#' can be escaped."); } } else if (specialChars2253.indexOf((char)c) == -1) { throw new IOException ("Invalid escaped character in AVA: '" + (char)c + "'"); } } } else { // check if character should have been escaped
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -