mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

dugan
05.16.2006 ec8dd4540b7be98f80e073c1df7bbc536241571a
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.
3 files modified
197 ■■■■■ changed files
opendj-sdk/opends/src/server/org/opends/server/messages/SchemaMessages.java 26 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/schema/LDAPSyntaxDescriptionSyntax.java 98 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/LDAPSyntaxTest.java 73 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/messages/SchemaMessages.java
@@ -2945,7 +2945,24 @@
  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
@@ -4178,6 +4195,15 @@
    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.");
  }
}
opendj-sdk/opends/src/server/org/opends/server/schema/LDAPSyntaxDescriptionSyntax.java
@@ -469,7 +469,19 @@
                                      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).
@@ -642,5 +654,89 @@
    // 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;
  }
}
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/LDAPSyntaxTest.java
@@ -51,19 +51,66 @@
  @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},
      };
  }
}