/** * Reads the value of a string enclosed in single quotes, skipping over the quotes and any leading * or trailing spaces, and appending the string to the provided buffer. * * @param valueStr The user-provided representation of the DIT content rule definition. * @param lowerStr The all-lowercase representation of the DIT content rule definition. * @param userBuffer The buffer into which the user-provided representation of the value will be * placed. * @param lowerBuffer The buffer into which the all-lowercase representation of the value will be * placed. * @param startPos The position in the provided string at which to start reading the quoted * string. * @return The position of the first character that is not part of the quoted string or one of the * trailing spaces after it. * @throws DirectoryException If a problem is encountered while reading the quoted string. */ private static int readQuotedString( String valueStr, String lowerStr, StringBuilder userBuffer, StringBuilder lowerBuffer, int startPos) throws DirectoryException { // Skip over any spaces at the beginning of the value. char c = '\u0000'; int length = lowerStr.length(); while (startPos < length && ((c = lowerStr.charAt(startPos)) == ' ')) { startPos++; } if (startPos >= length) { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(lowerStr); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } // The next character must be a single quote. if (c != '\'') { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_EXPECTED_QUOTE_AT_POS.get(valueStr, startPos, c); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } // Read until we find the closing quote. startPos++; while (startPos < length && ((c = lowerStr.charAt(startPos)) != '\'')) { lowerBuffer.append(c); userBuffer.append(valueStr.charAt(startPos)); startPos++; } // Skip over any trailing spaces after the value. startPos++; while (startPos < length && ((c = lowerStr.charAt(startPos)) == ' ')) { startPos++; } // If we're at the end of the value, then that's illegal. if (startPos >= length) { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(lowerStr); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } // Return the position of the first non-space character after the token. return startPos; }
/** * Reads the next token name from the DIT content rule definition, skipping over any leading or * trailing spaces, and appends it to the provided buffer. * * @param valueStr The string representation of the DIT content rule definition. * @param tokenName The buffer into which the token name will be written. * @param startPos The position in the provided string at which to start reading the token name. * @return The position of the first character that is not part of the token name or one of the * trailing spaces after it. * @throws DirectoryException If a problem is encountered while reading the token name. */ private static int readTokenName(String valueStr, StringBuilder tokenName, int startPos) throws DirectoryException { // Skip over any spaces at the beginning of the value. char c = '\u0000'; int length = valueStr.length(); while (startPos < length && ((c = valueStr.charAt(startPos)) == ' ')) { startPos++; } if (startPos >= length) { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } // Read until we find the next space. while (startPos < length && ((c = valueStr.charAt(startPos++)) != ' ')) { tokenName.append(c); } // Skip over any trailing spaces after the value. while (startPos < length && ((c = valueStr.charAt(startPos)) == ' ')) { startPos++; } // Return the position of the first non-space character after the token. return startPos; }
/** * Reads the value for an "extra" parameter. It will handle a single unquoted word (which is * technically illegal, but we'll allow it), a single quoted string, or an open parenthesis * followed by a space-delimited set of quoted strings or unquoted words followed by a close * parenthesis. * * @param valueStr The string containing the information to be read. * @param valueList The list of "extra" parameter values read so far. * @param startPos The position in the value string at which to start reading. * @return The "extra" parameter value that was read. * @throws DirectoryException If a problem occurs while attempting to read the value. */ private static int readExtraParameterValues(String valueStr, List<String> valueList, int startPos) throws DirectoryException { // Skip over any leading spaces. int length = valueStr.length(); char c = '\u0000'; while (startPos < length && ((c = valueStr.charAt(startPos)) == ' ')) { startPos++; } if (startPos >= length) { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } // Look at the next character. If it is a quote, then parse until the next // quote and end. If it is an open parenthesis, then parse individual // values until the close parenthesis and end. Otherwise, parse until the // next space and end. if (c == '\'') { // Parse until the closing quote. StringBuilder valueBuffer = new StringBuilder(); startPos++; while (startPos < length && ((c = valueStr.charAt(startPos)) != '\'')) { valueBuffer.append(c); startPos++; } startPos++; valueList.add(valueBuffer.toString()); } else if (c == '(') { startPos++; // We're expecting a list of values. Quoted, space separated. while (true) { // Skip over any leading spaces; while (startPos < length && ((c = valueStr.charAt(startPos)) == ' ')) { startPos++; } if (startPos >= length) { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } if (c == ')') { // This is the end of the list. startPos++; break; } else if (c == '(') { // This is an illegal character. LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR.get(valueStr, c, startPos); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } else if (c == '\'') { // We have a quoted string StringBuilder valueBuffer = new StringBuilder(); startPos++; while (startPos < length && ((c = valueStr.charAt(startPos)) != '\'')) { valueBuffer.append(c); startPos++; } valueList.add(valueBuffer.toString()); startPos++; } else { // Consider unquoted string StringBuilder valueBuffer = new StringBuilder(); while (startPos < length && ((c = valueStr.charAt(startPos)) != ' ')) { valueBuffer.append(c); startPos++; } valueList.add(valueBuffer.toString()); } if (startPos >= length) { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } } } else { // Parse until the next space. StringBuilder valueBuffer = new StringBuilder(); while (startPos < length && ((c = valueStr.charAt(startPos)) != ' ')) { valueBuffer.append(c); startPos++; } valueList.add(valueBuffer.toString()); } // Skip over any trailing spaces. while (startPos < length && valueStr.charAt(startPos) == ' ') { startPos++; } if (startPos >= length) { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } return startPos; }
/** * Reads an attributeType/objectclass description or numeric OID from the provided string, * skipping over any leading or trailing spaces, and appending the value to the provided buffer. * * @param lowerStr The string from which the name or OID is to be read. * @param woidBuffer The buffer into which the name or OID should be appended. * @param startPos The position at which to start reading. * @return The position of the first character after the name or OID that is not a space. * @throws DirectoryException If a problem is encountered while reading the name or OID. */ private static int readWOID(String lowerStr, StringBuilder woidBuffer, int startPos) throws DirectoryException { // Skip over any spaces at the beginning of the value. char c = '\u0000'; int length = lowerStr.length(); while (startPos < length && ((c = lowerStr.charAt(startPos)) == ' ')) { startPos++; } if (startPos >= length) { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(lowerStr); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } // The next character must be either numeric (for an OID) or alphabetic (for // an attribute type/objectclass description). if (isDigit(c)) { // This must be a numeric OID. In that case, we will accept only digits // and periods, but not consecutive periods. boolean lastWasPeriod = false; while (startPos < length && ((c = lowerStr.charAt(startPos++)) != ' ')) { if (c == '.') { if (lastWasPeriod) { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_DOUBLE_PERIOD_IN_NUMERIC_OID.get(lowerStr, startPos - 1); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } else { woidBuffer.append(c); lastWasPeriod = true; } } else if (!isDigit(c)) { // Technically, this must be an illegal character. However, it is // possible that someone just got sloppy and did not include a space // between the name/OID and a closing parenthesis. In that case, // we'll assume it's the end of the value. What's more, we'll have // to prematurely return to nasty side effects from stripping off // additional characters. if (c == ')') { return startPos - 1; } // This must have been an illegal character. LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR_IN_NUMERIC_OID.get(lowerStr, c, startPos - 1); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } else { woidBuffer.append(c); lastWasPeriod = false; } } } else if (isAlpha(c)) { // This must be an attribute type/objectclass description. In this case, // we will only accept alphabetic characters, numeric digits, and the hyphen. while (startPos < length && ((c = lowerStr.charAt(startPos++)) != ' ')) { if (isAlpha(c) || isDigit(c) || c == '-' || (c == '_' && DirectoryServer.allowAttributeNameExceptions())) { woidBuffer.append(c); } else { // Technically, this must be an illegal character. However, it is // possible that someone just got sloppy and did not include a space // between the name/OID and a closing parenthesis. In that case, // we'll assume it's the end of the value. What's more, we'll have // to prematurely return to nasty side effects from stripping off // additional characters. if (c == ')') { return startPos - 1; } // This must have been an illegal character. LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR_IN_STRING_OID.get(lowerStr, c, startPos - 1); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } } } else { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR.get(lowerStr, c, startPos); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } // Skip over any trailing spaces after the value. while (startPos < length && ((c = lowerStr.charAt(startPos)) == ' ')) { startPos++; } // If we're at the end of the value, then that's illegal. if (startPos >= length) { LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(lowerStr); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } // Return the position of the first non-space character after the token. return startPos; }