From ec8dd4540b7be98f80e073c1df7bbc536241571a Mon Sep 17 00:00:00 2001
From: dugan <dugan@localhost>
Date: Tue, 05 Dec 2006 04:16:14 +0000
Subject: [PATCH] org.opends.server.schema.LDAPSyntaxDescription.java does not accept extensions as specified by RFC4512 :

---
 opendj-sdk/opends/src/server/org/opends/server/schema/LDAPSyntaxDescriptionSyntax.java            |   98 ++++++++++++++++++++++++
 opendj-sdk/opends/src/server/org/opends/server/messages/SchemaMessages.java                       |   26 ++++++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/LDAPSyntaxTest.java |   73 +++++++++++++++---
 3 files changed, 183 insertions(+), 14 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/SchemaMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/SchemaMessages.java
index 4d55bd4..47e7233 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/SchemaMessages.java
+++ b/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.");
   }
 }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/schema/LDAPSyntaxDescriptionSyntax.java b/opendj-sdk/opends/src/server/org/opends/server/schema/LDAPSyntaxDescriptionSyntax.java
index 290db5f..c719c6e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/schema/LDAPSyntaxDescriptionSyntax.java
+++ b/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;
+  }
 }
 
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/LDAPSyntaxTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/LDAPSyntaxTest.java
index 418ccf3..2024535 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/LDAPSyntaxTest.java
+++ b/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},
+      };
   }
 
 }

--
Gitblit v1.10.0