org.opends.server.schema.LDAPSyntaxDescription.java does not accept extensions
as specified by RFC4512 :
SyntaxDescription = LPAREN WSP
numericoid ; object identifier
[ SP "DESC" SP qdstring ] ; description
extensions WSP RPAREN ; extensions
see SYNTAX_LDAP_SYNTAX_OID from org.opends.server.schema.LDAPSyntaxTest.java
Issue 640.
| | |
| | | public static final int MSGID_ATTR_SYNTAX_AUTHPW_INVALID_TRAILING_CHAR = |
| | | CATEGORY_MASK_SCHEMA | SEVERITY_MASK_SEVERE_ERROR | 263; |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an attribute syntax |
| | | * extension value cannot be parsed because an invalid character was found. |
| | | * This takes a two arguments, which are the provided value, and the position |
| | | * of the invalid character. |
| | | */ |
| | | public static final int |
| | | MSGID_ATTR_SYNTAX_ATTRSYNTAX_EXTENSION_INVALID_CHARACTER = |
| | | CATEGORY_MASK_SCHEMA | SEVERITY_MASK_MILD_ERROR | 264; |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an attribute syntax |
| | | * extension value cannot be parsed. This takes one argument, a string |
| | | * representation of the exception that was caught. |
| | | */ |
| | | public static final int |
| | | MSGID_ATTR_SYNTAX_ATTRSYNTAX_INVALID_EXTENSION = |
| | | CATEGORY_MASK_SCHEMA | SEVERITY_MASK_MILD_ERROR | 265; |
| | | |
| | | /** |
| | | * Associates a set of generic messages with the message IDs defined in this |
| | |
| | | registerMessage(MSGID_ATTR_SYNTAX_RELATIVE_SUBTREE_SPECIFICATION_INVALID, |
| | | "The provided value \"%s\" could not be parsed as a" + |
| | | " valid relative subtree specification."); |
| | | |
| | | registerMessage(MSGID_ATTR_SYNTAX_ATTRSYNTAX_EXTENSION_INVALID_CHARACTER, |
| | | "The provided value \"%s\" could not be parsed as an " + |
| | | "attribute syntax extension because an invalid character"+ |
| | | "was found at position %d."); |
| | | |
| | | registerMessage(MSGID_ATTR_SYNTAX_ATTRSYNTAX_INVALID_EXTENSION, |
| | | "The attribute syntax could not be parsed because of an"+ |
| | | "invalid extension."+ "%s."); |
| | | } |
| | | } |
| | | |
| | |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | |
| | | //Check if we have a RFC 4512 style extension. |
| | | if ((c = valueStr.charAt(pos)) != ')') |
| | | { |
| | | try { |
| | | pos=parseExtension(valueStr, pos); |
| | | } catch (Exception e) { |
| | | assert debugException(CLASS_NAME, "valueIsAcceptable", e); |
| | | int msgID = MSGID_ATTR_SYNTAX_ATTRSYNTAX_INVALID_EXTENSION; |
| | | invalidReason.append(getMessage(msgID, |
| | | stackTraceToSingleLineString(e))); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // The next character must be the closing parenthesis and there should not |
| | | // be anything after it (except maybe some spaces). |
| | |
| | | // Return the position of the first non-space character after the token. |
| | | return startPos; |
| | | } |
| | | |
| | | /** Parses a RFC 4512 extensions (see 4.1.5 and 4.1 of the RFC) definition. |
| | | * |
| | | * From 4.1.5 of the spec: |
| | | * |
| | | * LDAP syntax definitions are written according to the ABNF: |
| | | * |
| | | * SyntaxDescription = LPAREN WSP |
| | | * numericoid ; object identifier |
| | | * [ SP "DESC" SP qdstring ] ; description |
| | | * extensions WSP RPAREN ; extensions |
| | | * |
| | | * @param valueStr The user-provided representation of the extensions |
| | | * definition. |
| | | * |
| | | * @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 the extensions definition could not be |
| | | * parsed. |
| | | */ |
| | | private static int parseExtension(String valueStr, int startPos) |
| | | throws DirectoryException { |
| | | |
| | | int pos=startPos, len=valueStr.length(); |
| | | char c; |
| | | while(true) |
| | | { |
| | | StringBuilder tokenNameBuffer = new StringBuilder(); |
| | | pos = readTokenName(valueStr, tokenNameBuffer, pos); |
| | | String tokenName = tokenNameBuffer.toString(); |
| | | if((tokenName.length() <= 2) || (!tokenName.startsWith("X-"))) |
| | | { |
| | | int msgID = |
| | | MSGID_ATTR_SYNTAX_ATTRSYNTAX_EXTENSION_INVALID_CHARACTER; |
| | | String message = getMessage(msgID, valueStr); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | String xstring = tokenName.substring(2); |
| | | //Only allow a-z,A-Z,-,_ characters after X- |
| | | if(xstring.split("^[A-Za-z_-]+").length > 0) |
| | | { |
| | | int msgID = |
| | | MSGID_ATTR_SYNTAX_ATTRSYNTAX_EXTENSION_INVALID_CHARACTER; |
| | | String message = getMessage(msgID, valueStr); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | if((c=valueStr.charAt(pos)) == '\'') |
| | | { |
| | | StringBuilder qdString = new StringBuilder(); |
| | | pos = readQuotedString(valueStr, qdString, pos); |
| | | |
| | | } else if(c == '(') |
| | | { |
| | | pos++; |
| | | StringBuilder qdString = new StringBuilder(); |
| | | while ((c=valueStr.charAt(pos)) != ')') |
| | | pos = readQuotedString(valueStr, qdString, pos); |
| | | pos++; |
| | | } else |
| | | { |
| | | int msgID = |
| | | MSGID_ATTR_SYNTAX_ATTRSYNTAX_EXTENSION_INVALID_CHARACTER; |
| | | String message = getMessage(msgID, valueStr); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | if (pos >= len) |
| | | { |
| | | int msgID = MSGID_ATTR_SYNTAX_ATTRSYNTAX_TRUNCATED_VALUE; |
| | | String message = getMessage(msgID, valueStr); |
| | | throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, |
| | | message, msgID); |
| | | } |
| | | if(valueStr.charAt(pos) == ')') |
| | | break; |
| | | } |
| | | return pos; |
| | | } |
| | | } |
| | | |
| | |
| | | @DataProvider(name="acceptableValues") |
| | | public Object[][] createAcceptableValues() |
| | | { |
| | | return new Object [][] { |
| | | // disabled because test is failing : |
| | | // { |
| | | // "( 2.5.4.3 DESC 'full syntax description' " |
| | | // + "( this is an extension ) )", true}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' )", true}, |
| | | {" ( 2.5.4.3 DESC ' syntax description' )", true}, |
| | | {"( 2.5.4.3 DESC syntax description )", false}, |
| | | {"($%^*&!@ DESC 'syntax description' )", false}, |
| | | {"(temp-oid DESC 'syntax description' )", true}, |
| | | {"2.5.4.3 DESC 'syntax description' )", false}, |
| | | {"(2.5.4.3 DESC 'syntax description' ", false}, |
| | | }; |
| | | return new Object [][] { |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-9EN ('this' 'is' 'a' 'test'))", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "(X-name 'this", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "(X-name 'this'", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "Y-name 'this')", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name 'this' 'is')", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name )", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X- ('this' 'is' 'a' 'test'))", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name ('this' 'is' 'a' 'test') X-name-a 'this' X-name-b ('this')", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name ('this' 'is' 'a' 'test') X-name-a 'this' X-name-b ('this'", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name ('this' 'is' 'a' 'test') X-name-a 'this' X-name-b ('this'))))", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name ('this' 'is' 'a' 'test') X-name-a X-name-b ('this'))))", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name ('this' 'is' 'a' 'test') X-name-a 'X-name-b' ('this'))))", |
| | | false}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name ('this' 'is' 'a' 'test') X-name-a 'this' X-name-b ('this'))", |
| | | true}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-a-_eN_- ('this' 'is' 'a' 'test'))", |
| | | true}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name ('this'))", |
| | | true}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name 'this')", |
| | | true}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' " + |
| | | "X-name 'this' X-name-a 'test')", |
| | | true}, |
| | | {"( 2.5.4.3 DESC 'full syntax description' )", true}, |
| | | {" ( 2.5.4.3 DESC ' syntax description' )", true}, |
| | | {"( 2.5.4.3 DESC syntax description )", false}, |
| | | {"($%^*&!@ DESC 'syntax description' )", false}, |
| | | {"(temp-oid DESC 'syntax description' )", true}, |
| | | {"2.5.4.3 DESC 'syntax description' )", false}, |
| | | {"(2.5.4.3 DESC 'syntax description' ", false}, |
| | | }; |
| | | } |
| | | |
| | | } |